2009-02-10 18:37:48 +00:00
/*
Copyright ( C ) 2002 Kimmo Pekkola + few lsapi developers
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2009-10-07 16:45:14 +00:00
# include "StdAfx.h"
2009-02-10 18:37:48 +00:00
# include "Litestep.h"
# include "Error.h"
2009-07-21 12:26:50 +00:00
# include "Rainmeter.h"
2010-09-11 19:39:45 +00:00
# include "System.h"
2009-02-10 18:37:48 +00:00
2009-07-21 12:26:50 +00:00
extern CRainmeter * Rainmeter ;
2009-02-10 18:37:48 +00:00
typedef BOOL ( * FPADDBANGCOMMAND ) ( LPCSTR command , BangCommand f ) ;
FPADDBANGCOMMAND fpAddBangCommand = NULL ;
typedef HRGN ( * FPBITMAPTOREGION ) ( HBITMAP hBmp , COLORREF cTransparentColor , COLORREF cTolerance , int xoffset , int yoffset ) ;
FPBITMAPTOREGION fpBitmapToRegion = NULL ;
typedef HWND ( * FPGETLITESTEPWND ) ( void ) ;
FPGETLITESTEPWND fpGetLitestepWnd = NULL ;
typedef BOOL ( * FPGETRCSTRING ) ( LPCSTR lpKeyName , LPSTR value , LPCSTR defStr , int maxLen ) ;
FPGETRCSTRING fpGetRCString = NULL ;
2010-12-25 08:43:26 +00:00
//typedef int (*FPGETRCINT)(LPCSTR lpKeyName, int nDefault);
//FPGETRCINT fpGetRCInt = NULL;
2009-02-10 18:37:48 +00:00
typedef HINSTANCE ( * FPLSEXECUTE ) ( HWND Owner , LPCSTR szCommand , int nShowCmd ) ;
FPLSEXECUTE fpLSExecute = NULL ;
typedef BOOL ( * FPREMOVEBANGCOMMAND ) ( LPCSTR command ) ;
FPREMOVEBANGCOMMAND fpRemoveBangCommand = NULL ;
2010-12-25 08:43:26 +00:00
//typedef void (*FPTRANSPARENTBLTLS)(HDC dc, int nXDest, int nYDest, int nWidth, int nHeight, HDC tempDC, int nXSrc, int nYSrc, COLORREF colorTransparent);
//FPTRANSPARENTBLTLS fpTransparentBltLS = NULL;
2009-02-10 18:37:48 +00:00
typedef void ( * FPVAREXPANSION ) ( LPSTR buffer , LPCSTR value ) ;
FPVAREXPANSION fpVarExpansion = NULL ;
typedef BOOL ( WINAPI * FPLSLOG ) ( int nLevel , LPCSTR pszModule , LPCSTR pszMessage ) ;
FPLSLOG fpLSLog = NULL ;
2011-08-31 11:06:35 +00:00
static CRITICAL_SECTION g_CsLog = { 0 } ;
static CRITICAL_SECTION g_CsLogDelay = { 0 } ;
2009-02-10 18:37:48 +00:00
static int logFound = 0 ;
void ResetLoggingFlag ( )
{
logFound = 0 ;
}
void InitalizeLitestep ( )
{
2011-08-31 11:06:35 +00:00
InitializeCriticalSection ( & g_CsLog ) ;
InitializeCriticalSection ( & g_CsLogDelay ) ;
if ( ! CRainmeter : : GetDummyLitestep ( ) )
2009-02-10 18:37:48 +00:00
{
2011-08-31 11:06:35 +00:00
// Use lsapi's methods instead of the stubs
HINSTANCE h = CSystem : : RmLoadLibrary ( L " lsapi.dll " ) ;
if ( h ! = NULL )
{
fpAddBangCommand = ( FPADDBANGCOMMAND ) GetProcAddress ( h , " AddBangCommand " ) ;
fpBitmapToRegion = ( FPBITMAPTOREGION ) GetProcAddress ( h , " BitmapToRegion " ) ;
fpGetLitestepWnd = ( FPGETLITESTEPWND ) GetProcAddress ( h , " GetLitestepWnd " ) ;
fpGetRCString = ( FPGETRCSTRING ) GetProcAddress ( h , " GetRCString " ) ;
//fpGetRCInt = (FPGETRCINT)GetProcAddress(h, "GetRCInt");
fpLSExecute = ( FPLSEXECUTE ) GetProcAddress ( h , " LSExecute " ) ;
fpRemoveBangCommand = ( FPREMOVEBANGCOMMAND ) GetProcAddress ( h , " RemoveBangCommand " ) ;
//fpTransparentBltLS = (FPTRANSPARENTBLTLS)GetProcAddress(h, "TransparentBltLS");
fpVarExpansion = ( FPVAREXPANSION ) GetProcAddress ( h , " VarExpansion " ) ;
fpLSLog = ( FPLSLOG ) GetProcAddress ( h , " _LSLog@12 " ) ;
}
2009-02-10 18:37:48 +00:00
}
}
2011-08-31 11:06:35 +00:00
void FinalizeLitestep ( )
{
DeleteCriticalSection ( & g_CsLog ) ;
DeleteCriticalSection ( & g_CsLogDelay ) ;
}
2009-02-10 18:37:48 +00:00
BOOL AddBangCommand ( LPCSTR command , BangCommand f )
{
// Use the lsapi.dll version of the method if possible
if ( fpAddBangCommand ) return fpAddBangCommand ( command , f ) ;
// The stub implementation
return true ;
}
HWND GetLitestepWnd ( void )
{
// Use the lsapi.dll version of the method if possible
if ( fpGetLitestepWnd ) return fpGetLitestepWnd ( ) ;
// The stub implementation
return NULL ;
}
BOOL RemoveBangCommand ( LPCSTR command )
{
// Use the lsapi.dll version of the method if possible
if ( fpRemoveBangCommand ) return fpRemoveBangCommand ( command ) ;
// The stub implementation
return true ;
}
BOOL GetRCString ( LPCSTR lpKeyName , LPSTR value , LPCSTR defStr , int maxLen )
{
// Use the lsapi.dll version of the method if possible
if ( fpGetRCString ) return fpGetRCString ( lpKeyName , value , defStr , maxLen ) ;
// The stub implementation
return false ;
}
2010-12-25 08:43:26 +00:00
//int GetRCInt(LPCSTR lpKeyName, int nDefault)
//{
// // Use the lsapi.dll version of the method if possible
// if (fpGetRCInt) return fpGetRCInt(lpKeyName, nDefault);
//
// // The stub implementation
// return nDefault;
//}
2009-02-10 18:37:48 +00:00
void VarExpansion ( LPSTR buffer , LPCSTR value )
{
// Use the lsapi.dll version of the method if possible
2011-03-29 19:21:57 +00:00
if ( fpVarExpansion )
2009-02-10 18:37:48 +00:00
{
fpVarExpansion ( buffer , value ) ;
}
else
{
// The stub implementation
if ( buffer ! = value )
{
strcpy ( buffer , value ) ;
}
}
}
HRGN BitmapToRegion ( HBITMAP hbm , COLORREF clrTransp , COLORREF clrTolerance , int xoffset , int yoffset )
{
// Use the lsapi.dll version of the method if possible
if ( fpBitmapToRegion ) return fpBitmapToRegion ( hbm , clrTransp , clrTolerance , xoffset , yoffset ) ;
// start with a completely transparent rgn
// this is more correct as no bmp, should render a transparent background
HRGN hRgn = CreateRectRgn ( 0 , 0 , 0 , 0 ) ;
if ( hbm )
{
// create a dc for the 32 bit dib
HDC hdcMem = CreateCompatibleDC ( NULL ) ;
if ( hdcMem )
{
VOID * pbits32 ;
HBITMAP hbm32 ;
BITMAP bm ;
// get the size
GetObject ( hbm , sizeof ( BITMAP ) , & bm ) ;
BITMAPINFOHEADER bmpInfo32 ;
bmpInfo32 . biSize = sizeof ( BITMAPINFOHEADER ) ;
bmpInfo32 . biWidth = bm . bmWidth ;
bmpInfo32 . biHeight = bm . bmHeight ;
bmpInfo32 . biPlanes = 1 ;
bmpInfo32 . biBitCount = 32 ;
bmpInfo32 . biCompression = BI_RGB ;
bmpInfo32 . biSizeImage = 0 ;
bmpInfo32 . biXPelsPerMeter = 0 ;
bmpInfo32 . biYPelsPerMeter = 0 ;
bmpInfo32 . biClrUsed = 0 ;
bmpInfo32 . biClrImportant = 0 ;
hbm32 = CreateDIBSection ( hdcMem , ( BITMAPINFO * ) & bmpInfo32 , DIB_RGB_COLORS , & pbits32 , NULL , 0 ) ;
if ( hbm32 )
{
HBITMAP hbmOld32 = ( HBITMAP ) SelectObject ( hdcMem , hbm32 ) ;
// Create a DC just to copy the bitmap into the memory D
HDC hdcTmp = CreateCompatibleDC ( hdcMem ) ;
if ( hdcTmp )
{
// Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits
int y = 0 ;
BITMAP bm32 ;
GetObject ( hbm32 , sizeof ( bm32 ) , & bm32 ) ;
while ( bm32 . bmWidthBytes % 4 )
bm32 . bmWidthBytes + + ;
// get the limits for the colors
BYTE clrHiR = ( 0xff - GetRValue ( clrTolerance ) > GetRValue ( clrTransp ) ) ? GetRValue ( clrTransp ) + GetRValue ( clrTolerance ) : 0xff ;
BYTE clrHiG = ( 0xff - GetGValue ( clrTolerance ) > GetGValue ( clrTransp ) ) ? GetGValue ( clrTransp ) + GetGValue ( clrTolerance ) : 0xff ;
BYTE clrHiB = ( 0xff - GetBValue ( clrTolerance ) > GetBValue ( clrTransp ) ) ? GetBValue ( clrTransp ) + GetBValue ( clrTolerance ) : 0xff ;
BYTE clrLoR = ( GetRValue ( clrTolerance ) < GetRValue ( clrTransp ) ) ? GetRValue ( clrTransp ) - GetRValue ( clrTolerance ) : 0x00 ;
BYTE clrLoG = ( GetGValue ( clrTolerance ) < GetGValue ( clrTransp ) ) ? GetGValue ( clrTransp ) - GetGValue ( clrTolerance ) : 0x00 ;
BYTE clrLoB = ( GetBValue ( clrTolerance ) < GetBValue ( clrTransp ) ) ? GetBValue ( clrTransp ) - GetBValue ( clrTolerance ) : 0x00 ;
// Copy the bitmap into the memory D
HBITMAP hbmOld = ( HBITMAP ) SelectObject ( hdcTmp , hbm ) ;
BitBlt ( hdcMem , 0 , 0 , bm . bmWidth , bm . bmHeight , hdcTmp , 0 , 0 , SRCCOPY ) ;
// Scan each bitmap row from bottom to top (the bitmap is inverted vertically
BYTE * p ;
BYTE * p32 = ( BYTE * ) bm32 . bmBits + ( bm32 . bmHeight - 1 ) * bm32 . bmWidthBytes ;
while ( y < bm . bmHeight )
{
int x = 0 ;
while ( x < bm . bmWidth )
{
int x0 = 0 ;
// loop through all transparent pixels...
while ( x < bm . bmWidth )
{
p = p32 + 4 * x ;
// if the pixel is non-transparent
2010-12-25 08:43:26 +00:00
if ( * p < clrLoB | | * p > clrHiB )
break ;
p + + ;
if ( * p < clrLoG | | * p > clrHiG )
break ;
p + + ;
if ( * p < clrLoR | | * p > clrHiR )
break ;
2009-02-10 18:37:48 +00:00
x + + ;
}
// set first non transparent pixel
x0 = x ;
// loop through all non transparent pixels
while ( x < bm . bmWidth )
{
p = p32 + 4 * x ;
// if the pixel is transparent, then break
if ( * p > = clrLoB & & * p < = clrHiB )
{
p + + ;
if ( * p > = clrLoG & & * p < = clrHiG )
{
p + + ;
if ( * p > = clrLoR & & * p < = clrHiR )
break ;
}
}
x + + ;
}
// if found one or more non-transparent pixels in a row, add them to the rgn...
2010-12-25 08:43:26 +00:00
if ( x ! = x0 )
2009-02-10 18:37:48 +00:00
{
HRGN hTempRgn = CreateRectRgn ( x0 + xoffset , y + yoffset , x + xoffset , y + 1 + yoffset ) ;
CombineRgn ( hRgn , hRgn , hTempRgn , RGN_OR ) ;
DeleteObject ( hTempRgn ) ;
}
x + + ;
}
y + + ;
p32 - = bm32 . bmWidthBytes ;
}
// Clean up
SelectObject ( hdcTmp , hbmOld ) ;
DeleteDC ( hdcTmp ) ;
}
SelectObject ( hdcMem , hbmOld32 ) ;
DeleteObject ( hbm32 ) ;
}
DeleteDC ( hdcMem ) ;
}
}
return hRgn ;
}
2009-07-21 12:26:50 +00:00
HINSTANCE LSExecuteAsAdmin ( HWND Owner , LPCTSTR szCommand , int nShowCmd )
{
BOOL IsInAdminGroup = FALSE ;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY ;
PSID AdministratorsGroup ;
// Initialize SID.
2011-03-29 19:21:57 +00:00
if ( ! AllocateAndInitializeSid ( & NtAuthority ,
2009-07-21 12:26:50 +00:00
2 ,
SECURITY_BUILTIN_DOMAIN_RID ,
DOMAIN_ALIAS_RID_ADMINS ,
0 , 0 , 0 , 0 , 0 , 0 ,
& AdministratorsGroup ) )
{
// Initializing SID Failed.
IsInAdminGroup = FALSE ;
}
else
{
// Check whether the token is present in admin group.
2011-03-29 19:21:57 +00:00
if ( ! CheckTokenMembership ( NULL ,
2009-07-21 12:26:50 +00:00
AdministratorsGroup ,
& IsInAdminGroup ) )
{
// Error occurred.
IsInAdminGroup = FALSE ;
}
// Free SID and return.
FreeSid ( AdministratorsGroup ) ;
}
if ( IsInAdminGroup )
{
return ExecuteCommand ( Owner , szCommand , nShowCmd , L " open " ) ;
}
else
{
return ExecuteCommand ( Owner , szCommand , nShowCmd , L " runas " ) ;
}
}
2009-02-10 18:37:48 +00:00
HINSTANCE LSExecute ( HWND Owner , LPCTSTR szCommand , int nShowCmd )
{
// Use the lsapi.dll version of the method if possible
2011-03-29 19:21:57 +00:00
if ( fpLSExecute )
2009-02-10 18:37:48 +00:00
{
std : : string asc = ConvertToAscii ( szCommand ) ;
return fpLSExecute ( Owner , asc . c_str ( ) , nShowCmd ) ;
}
2009-07-21 12:26:50 +00:00
return ExecuteCommand ( Owner , szCommand , nShowCmd , L " open " ) ;
}
HINSTANCE ExecuteCommand ( HWND Owner , LPCTSTR szCommand , int nShowCmd , LPCTSTR szVerb )
{
2009-02-10 18:37:48 +00:00
// The stub implementation (some of this code is taken from lsapi.cpp)
2010-11-25 15:34:49 +00:00
if ( szCommand = = NULL | | * szCommand = = 0 ) return NULL ;
2009-02-10 18:37:48 +00:00
std : : wstring args ;
std : : wstring command = szCommand ;
2011-07-18 00:32:09 +00:00
size_t notwhite = command . find_first_not_of ( L " \t \r \n " ) ;
2009-02-10 18:37:48 +00:00
command . erase ( 0 , notwhite ) ;
2011-07-18 00:32:09 +00:00
if ( command . empty ( ) ) return NULL ;
2009-02-10 18:37:48 +00:00
2011-08-28 10:58:26 +00:00
size_t quotePos = command . find ( L ' " ' ) ;
2009-02-10 18:37:48 +00:00
if ( quotePos = = 0 )
{
2011-08-28 10:58:26 +00:00
size_t quotePos2 = command . find ( L ' " ' , quotePos + 1 ) ;
2009-02-10 18:37:48 +00:00
if ( quotePos2 ! = std : : wstring : : npos )
{
2011-07-14 00:26:53 +00:00
args . assign ( command , quotePos2 + 1 , command . length ( ) - ( quotePos2 + 1 ) ) ;
command . assign ( command , quotePos + 1 , quotePos2 - quotePos - 1 ) ;
2009-02-10 18:37:48 +00:00
}
else
{
2011-07-14 00:26:53 +00:00
command . erase ( 0 , 1 ) ;
2009-02-10 18:37:48 +00:00
}
}
else
{
2011-08-28 10:58:26 +00:00
size_t spacePos = command . find ( L ' ' ) ;
2009-02-10 18:37:48 +00:00
if ( spacePos ! = std : : wstring : : npos )
{
2011-07-14 00:26:53 +00:00
args . assign ( command , spacePos + 1 , command . length ( ) - ( spacePos + 1 ) ) ;
command . erase ( spacePos ) ;
2009-02-10 18:37:48 +00:00
}
}
DWORD type = GetFileAttributes ( command . c_str ( ) ) ;
if ( type & FILE_ATTRIBUTE_DIRECTORY & & type ! = 0xFFFFFFFF )
{
2009-07-21 12:26:50 +00:00
HINSTANCE instance = ShellExecute ( Owner , szVerb , command . c_str ( ) , NULL , NULL , nShowCmd ? nShowCmd : SW_SHOWNORMAL ) ;
2009-02-10 18:37:48 +00:00
return instance ;
}
2009-07-26 21:08:46 +00:00
std : : wstring dir = CRainmeter : : ExtractPath ( command ) ;
2009-02-10 18:37:48 +00:00
2010-11-25 22:00:34 +00:00
SHELLEXECUTEINFO si = { sizeof ( SHELLEXECUTEINFO ) } ;
2009-02-10 18:37:48 +00:00
si . hwnd = Owner ;
2009-07-21 12:26:50 +00:00
si . lpVerb = szVerb ;
2009-02-10 18:37:48 +00:00
si . lpFile = command . c_str ( ) ;
si . lpParameters = args . c_str ( ) ;
si . lpDirectory = dir . c_str ( ) ;
si . nShow = nShowCmd ? nShowCmd : SW_SHOWNORMAL ;
si . fMask = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI ;
ShellExecuteEx ( & si ) ;
return si . hInstApp ;
}
2010-12-25 08:43:26 +00:00
//void TransparentBltLS(HDC hdcDst, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, COLORREF colorTransparent)
//{
// // Use the lsapi.dll version of the method if possible
2011-03-29 19:21:57 +00:00
// if (fpTransparentBltLS)
2010-12-25 08:43:26 +00:00
// {
// fpTransparentBltLS(hdcDst, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, colorTransparent);
// }
// else
// {
// HDC hdcMem, hdcMask, hdcDstCpy;
// HBITMAP hbmMask, hbmMem, hbmDstCpy;
// HBITMAP hbmOldMem, hbmOldMask, hbmOldDstCpy;
//
// // create a destination compatble dc containing
// // a copy of the destination dc
// hdcDstCpy = CreateCompatibleDC(hdcDst);
// hbmDstCpy = CreateCompatibleBitmap(hdcDst, nWidth, nHeight);
// hbmOldDstCpy = (HBITMAP)SelectObject(hdcDstCpy, hbmDstCpy);
//
// BitBlt(hdcDstCpy, 0, 0, nWidth, nHeight, hdcDst, nXDest, nYDest, SRCCOPY);
//
// // create a destination compatble dc containing
// // a copy of the source dc
// hdcMem = CreateCompatibleDC(hdcDst);
// hbmMem = CreateCompatibleBitmap(hdcDst, nWidth, nHeight);
// hbmOldMem = (HBITMAP)SelectObject(hdcMem, hbmMem);
//
// BitBlt(hdcMem, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
//
// // the transparent color should be selected as
// // bkcolor into the memory dc
// SetBkColor(hdcMem, colorTransparent);
//
// // Create monochrome bitmap for the mask
// hdcMask = CreateCompatibleDC(hdcDst);
// hbmMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
// hbmOldMask = (HBITMAP)SelectObject(hdcMask, hbmMask);
//
// // Create the mask from the memory dc
// BitBlt(hdcMask, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
//
// // Set the background in hdcMem to black. Using SRCPAINT with black
// // and any other color results in the other color, thus making
// // black the transparent color
// SetBkColor(hdcMem, RGB(0, 0, 0));
// SetTextColor(hdcMem, RGB(255, 255, 255));
//
// BitBlt(hdcMem, 0, 0, nWidth, nHeight, hdcMask, 0, 0, SRCAND);
//
// // Set the foreground to black. See comment above.
// SetBkColor(hdcDst, RGB(255, 255, 255));
// SetTextColor(hdcDst, RGB(0, 0, 0));
//
// BitBlt(hdcDstCpy, 0, 0, nWidth, nHeight, hdcMask, 0, 0, SRCAND);
//
// // Combine the foreground with the background
// BitBlt(hdcDstCpy, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCPAINT);
//
// // now we have created the image we want to blt
// // in the destination copy dc
// BitBlt(hdcDst, nXDest, nYDest, nWidth, nHeight, hdcDstCpy, 0, 0, SRCCOPY);
//
// SelectObject(hdcMask, hbmOldMask);
// DeleteObject(hbmMask);
// DeleteDC(hdcMask);
//
// SelectObject(hdcMem, hbmOldMem);
// DeleteObject(hbmMem);
// DeleteDC(hdcMem);
//
// SelectObject(hdcDstCpy, hbmOldDstCpy);
// DeleteObject(hbmDstCpy);
// DeleteDC(hdcDstCpy);
// }
//}
2009-02-10 18:37:48 +00:00
std : : string ConvertToAscii ( LPCTSTR str )
{
std : : string szAscii ;
2009-09-12 11:11:40 +00:00
if ( str & & * str )
2009-02-10 18:37:48 +00:00
{
2011-08-28 16:06:23 +00:00
int strLen = ( int ) wcslen ( str ) ;
2009-09-12 11:11:40 +00:00
int bufLen = WideCharToMultiByte ( CP_ACP , 0 , str , strLen , NULL , 0 , NULL , NULL ) ;
if ( bufLen > 0 )
{
2011-08-28 16:06:23 +00:00
szAscii . resize ( bufLen ) ;
2011-08-28 10:58:26 +00:00
WideCharToMultiByte ( CP_ACP , 0 , str , strLen , & szAscii [ 0 ] , bufLen , NULL , NULL ) ;
2009-09-12 11:11:40 +00:00
}
2009-02-10 18:37:48 +00:00
}
return szAscii ;
}
std : : wstring ConvertToWide ( LPCSTR str )
{
std : : wstring szWide ;
2009-09-12 11:11:40 +00:00
if ( str & & * str )
2009-02-10 18:37:48 +00:00
{
2011-08-28 16:06:23 +00:00
int strLen = ( int ) strlen ( str ) ;
2009-09-12 11:11:40 +00:00
int bufLen = MultiByteToWideChar ( CP_ACP , 0 , str , strLen , NULL , 0 ) ;
if ( bufLen > 0 )
{
2011-08-28 16:06:23 +00:00
szWide . resize ( bufLen ) ;
2011-08-28 10:58:26 +00:00
MultiByteToWideChar ( CP_ACP , 0 , str , strLen , & szWide [ 0 ] , bufLen ) ;
2009-09-12 11:11:40 +00:00
}
2009-02-10 18:37:48 +00:00
}
return szWide ;
2011-07-29 11:49:46 +00:00
}
std : : string ConvertToUTF8 ( LPCWSTR str )
{
std : : string szAscii ;
if ( str & & * str )
{
2011-08-28 16:06:23 +00:00
int strLen = ( int ) wcslen ( str ) ;
2011-07-29 11:49:46 +00:00
int bufLen = WideCharToMultiByte ( CP_UTF8 , 0 , str , strLen , NULL , 0 , NULL , NULL ) ;
if ( bufLen > 0 )
{
2011-08-28 16:06:23 +00:00
szAscii . resize ( bufLen ) ;
2011-08-28 10:58:26 +00:00
WideCharToMultiByte ( CP_UTF8 , 0 , str , strLen , & szAscii [ 0 ] , bufLen , NULL , NULL ) ;
2011-07-29 11:49:46 +00:00
}
}
return szAscii ;
}
std : : wstring ConvertUTF8ToWide ( LPCSTR str )
{
std : : wstring szWide ;
if ( str & & * str )
{
2011-08-28 16:06:23 +00:00
int strLen = ( int ) strlen ( str ) ;
2011-07-29 11:49:46 +00:00
int bufLen = MultiByteToWideChar ( CP_UTF8 , 0 , str , strLen , NULL , 0 ) ;
if ( bufLen > 0 )
{
2011-08-28 16:06:23 +00:00
szWide . resize ( bufLen ) ;
2011-08-28 10:58:26 +00:00
MultiByteToWideChar ( CP_UTF8 , 0 , str , strLen , & szWide [ 0 ] , bufLen ) ;
2011-07-29 11:49:46 +00:00
}
}
return szWide ;
2009-02-10 18:37:48 +00:00
}
2011-08-31 11:06:35 +00:00
BOOL LogInternal ( int nLevel , LPCTSTR pszModule , ULONGLONG elapsed , LPCTSTR pszMessage )
2009-02-10 18:37:48 +00:00
{
// Add timestamp
2010-09-13 20:06:52 +00:00
WCHAR buffer [ 128 ] ;
2011-08-31 11:06:35 +00:00
_snwprintf_s ( buffer , _TRUNCATE , L " %02llu:%02llu:%02llu.%03llu " , elapsed / ( 1000 * 60 * 60 ) , ( elapsed / ( 1000 * 60 ) ) % 60 , ( elapsed / 1000 ) % 60 , elapsed % 1000 ) ;
2011-08-28 10:58:26 +00:00
if ( Rainmeter )
{
Rainmeter - > AddAboutLogInfo ( nLevel , buffer , pszMessage ) ;
}
2009-02-10 18:37:48 +00:00
2011-08-28 10:58:26 +00:00
std : : wstring message = L " ( " ;
message + = buffer ;
message + = L " ) " ;
2009-02-10 18:37:48 +00:00
message + = pszMessage ;
# ifdef _DEBUG
_RPT0 ( _CRT_WARN , ConvertToAscii ( message . c_str ( ) ) . c_str ( ) ) ;
_RPT0 ( _CRT_WARN , " \n " ) ;
# endif
// Use the lsapi.dll version of the method if possible
2011-03-29 19:21:57 +00:00
if ( fpLSLog )
2009-02-10 18:37:48 +00:00
{
std : : string asc = ConvertToAscii ( message . c_str ( ) ) ;
std : : string mod = ConvertToAscii ( pszModule ) ;
return fpLSLog ( nLevel , mod . c_str ( ) , asc . c_str ( ) ) ;
}
// The stub implementation
2010-07-07 23:46:44 +00:00
if ( Rainmeter & & Rainmeter - > GetLogging ( ) )
2009-02-10 18:37:48 +00:00
{
2009-07-21 12:26:50 +00:00
std : : wstring logfile = Rainmeter - > GetLogFile ( ) ;
if ( logFound = = 0 )
2009-02-10 18:37:48 +00:00
{
2009-07-21 12:26:50 +00:00
// Check if the file exists
2010-07-08 10:59:06 +00:00
if ( _waccess ( logfile . c_str ( ) , 0 ) ! = - 1 )
2009-07-21 12:26:50 +00:00
{
logFound = 1 ;
2009-02-10 18:37:48 +00:00
2009-07-21 12:26:50 +00:00
// Clear the file
2010-07-08 10:59:06 +00:00
FILE * logFile = _wfopen ( logfile . c_str ( ) , L " w " ) ;
2009-07-21 12:26:50 +00:00
fclose ( logFile ) ;
}
else
{
2010-07-08 10:59:06 +00:00
logFound = 2 ; // not found
2009-07-21 12:26:50 +00:00
}
2009-02-10 18:37:48 +00:00
}
2009-07-21 12:26:50 +00:00
if ( logFound = = 1 )
2009-02-10 18:37:48 +00:00
{
2010-07-08 10:59:06 +00:00
if ( _waccess ( logfile . c_str ( ) , 0 ) = = - 1 )
{
// Disable logging if the file was deleted manually
Rainmeter - > StopLogging ( ) ;
}
else
2009-02-10 18:37:48 +00:00
{
2010-07-08 10:59:06 +00:00
FILE * logFile = _wfopen ( logfile . c_str ( ) , L " a+, ccs=UTF-8 " ) ;
if ( logFile )
2009-07-21 12:26:50 +00:00
{
2011-08-28 10:58:26 +00:00
message . insert ( 0 , L " : " ) ;
switch ( nLevel )
{
case LOG_ERROR :
message . insert ( 0 , L " ERROR " ) ;
break ;
case LOG_WARNING :
message . insert ( 0 , L " WARNING " ) ;
break ;
case LOG_NOTICE :
message . insert ( 0 , L " NOTICE " ) ;
break ;
case LOG_DEBUG :
message . insert ( 0 , L " DEBUG " ) ;
break ;
}
message + = L " \n " ;
2010-07-08 10:59:06 +00:00
fputws ( message . c_str ( ) , logFile ) ;
fclose ( logFile ) ;
2009-07-21 12:26:50 +00:00
}
2009-02-10 18:37:48 +00:00
}
}
}
2011-08-31 11:06:35 +00:00
2009-02-10 18:37:48 +00:00
return TRUE ;
}
2011-08-28 10:58:26 +00:00
BOOL LSLog ( int nLevel , LPCTSTR pszModule , LPCTSTR pszMessage )
2010-12-15 22:03:36 +00:00
{
2011-09-03 16:45:29 +00:00
// Ignore LOG_DEBUG messages from plugins unless in debug mode
2011-08-28 10:58:26 +00:00
if ( nLevel ! = LOG_DEBUG | | Rainmeter - > GetDebug ( ) )
{
2011-09-03 16:45:29 +00:00
Log ( nLevel , pszMessage , pszModule ) ;
}
2011-08-31 11:06:35 +00:00
2011-09-03 16:45:29 +00:00
return TRUE ;
}
2011-08-31 11:06:35 +00:00
2011-09-03 16:45:29 +00:00
void Log ( int nLevel , const WCHAR * message , const WCHAR * module )
{
struct DELAYED_LOG_INFO
{
int level ;
std : : wstring module ;
ULONGLONG elapsed ;
std : : wstring message ;
} ;
static std : : list < DELAYED_LOG_INFO > c_LogDelay ;
2011-08-31 11:06:35 +00:00
2011-09-03 16:45:29 +00:00
static ULONGLONG startTime = CSystem : : GetTickCount64 ( ) ;
ULONGLONG elapsed = CSystem : : GetTickCount64 ( ) - startTime ;
2011-08-31 11:06:35 +00:00
2011-09-03 16:45:29 +00:00
if ( TryEnterCriticalSection ( & g_CsLog ) )
{
// Log the queued messages first
EnterCriticalSection ( & g_CsLogDelay ) ;
2011-08-31 11:06:35 +00:00
2011-09-03 16:45:29 +00:00
while ( ! c_LogDelay . empty ( ) )
{
DELAYED_LOG_INFO & logInfo = c_LogDelay . front ( ) ;
LogInternal ( logInfo . level , logInfo . module . c_str ( ) , logInfo . elapsed , logInfo . message . c_str ( ) ) ;
2011-08-31 11:06:35 +00:00
2011-09-03 16:45:29 +00:00
c_LogDelay . erase ( c_LogDelay . begin ( ) ) ;
2011-08-31 11:06:35 +00:00
}
2011-09-03 16:45:29 +00:00
LeaveCriticalSection ( & g_CsLogDelay ) ;
2011-08-31 11:06:35 +00:00
2011-09-03 16:45:29 +00:00
// Log the message
LogInternal ( nLevel , module , elapsed , message ) ;
LeaveCriticalSection ( & g_CsLog ) ;
2011-08-28 10:58:26 +00:00
}
2011-09-03 16:45:29 +00:00
else
{
// Queue the message
EnterCriticalSection ( & g_CsLogDelay ) ;
2011-08-28 10:58:26 +00:00
2011-09-03 16:45:29 +00:00
DELAYED_LOG_INFO logInfo = { nLevel , module , elapsed , message } ;
c_LogDelay . push_back ( logInfo ) ;
2010-12-15 22:03:36 +00:00
2011-09-03 16:45:29 +00:00
LeaveCriticalSection ( & g_CsLogDelay ) ;
}
2010-07-07 23:46:44 +00:00
}
2010-12-19 23:06:13 +00:00
void LogWithArgs ( int nLevel , const WCHAR * format , . . . )
{
2011-02-15 13:22:19 +00:00
WCHAR * buffer = new WCHAR [ 4096 ] ;
2010-12-19 23:06:13 +00:00
va_list args ;
2011-03-29 19:21:57 +00:00
va_start ( args , format ) ;
2010-12-19 23:06:13 +00:00
_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler ( RmNullCRTInvalidParameterHandler ) ;
_CrtSetReportMode ( _CRT_ASSERT , 0 ) ;
errno = 0 ;
2011-02-15 13:22:19 +00:00
_vsnwprintf_s ( buffer , 4096 , _TRUNCATE , format , args ) ;
2010-12-19 23:06:13 +00:00
if ( errno ! = 0 )
{
nLevel = LOG_ERROR ;
2011-02-15 13:22:19 +00:00
_snwprintf_s ( buffer , 4096 , _TRUNCATE , L " LogWithArgs() internal error: %s " , format ) ;
2010-12-19 23:06:13 +00:00
}
_set_invalid_parameter_handler ( oldHandler ) ;
2011-09-03 16:45:29 +00:00
Log ( nLevel , buffer ) ;
2010-12-19 23:06:13 +00:00
va_end ( args ) ;
2011-02-15 13:22:19 +00:00
delete [ ] buffer ;
2010-12-19 23:06:13 +00:00
}
2011-08-28 10:58:26 +00:00
void RmNullCRTInvalidParameterHandler ( const wchar_t * expression , const wchar_t * function , const wchar_t * file , unsigned int line , uintptr_t pReserved )
{
// Do nothing.
}