#include "stdafx.h" #include "userlog.h" #include "windowsx.h" #include #include #include "helpers.h" #ifdef __USING_MTRACE__ #define OS_WIN32 #include "msl/merror/inc/trace.h" #ifdef __ENCODE_BASE64__ #include "encode.h" #endif const static int traceLevel = 3; static int level; #endif #ifdef __USING_COSTUMLOG__ static std::ofstream logfile; #endif #ifdef __TIMING__ static unsigned long long timing = 0; static unsigned long long msgCounter = 0; static unsigned long long totalMsgCounter = 0; static bool msgCounterChange = false; #endif static MSG lastmsg; static bool keysPressed[256]; inline bool keyAlreadyPressed(const MSG & msg) { return (msg.message==WM_KEYDOWN || msg.message==WM_SYSKEYDOWN) && keysPressed[msg.wParam]; } inline bool keyNotPressed(const MSG & msg) { return (msg.message==WM_KEYUP || msg.message==WM_SYSKEYUP) && !keysPressed[msg.wParam]; } HANDLE mutex; USERLOG_API void __cdecl InitUsagelog() { mutex = CreateMutex(NULL, FALSE, TEXT("USAGELOGMUTEX")); if( mutex == NULL ) { MessageBox(0, L"MutexFailure", L"MutexFailure", 0); } for(int i=0; i<256; i++) { keysPressed[i] = false; } #ifdef __USING_COSTUMLOG__ InitLogfile(); #endif InitHookdata(); InitHooks(); #ifdef __USING_MTRACE__ MTrace_AddToLevel(traceLevel,"%s", LOGPREFIX); #endif #ifdef __USING_COSTUMLOG__ logfile << LOGPREFIX << "" << std::endl; #endif } USERLOG_API void __cdecl ReleaseUsagelog() { ReleaseHooks(); #ifdef __USING_MTRACE__ #ifdef __TIMING__ char * mtraceBuffer = new char[128]; sprintf(mtraceBuffer, "ul timing: %llu \t\t %llu \t\t %llu", timing, msgCounter, totalMsgCounter); MTrace_AddToLevel(traceLevel,mtraceBuffer); delete mtraceBuffer; msgCounterChange = false; #endif MTrace_AddToLevel(traceLevel,"%s", LOGPREFIX); #endif #ifdef __USING_COSTUMLOG__ logfile << LOGPREFIX << "" << std::endl; CloseLogfile(); #endif } #ifdef __USING_COSTUMLOG__ void InitLogfile() { logfile.open(LOGFILE, std::ios_base::app); if( logfile.fail() ) { MessageBox(0, L"Logfile could not be opend", L"Error", MB_OK); } } #endif #ifdef __USING_COSTUMLOG__ void CloseLogfile() { logfile.close(); } #endif void InitHookdata() { myhookdata[CALLWNDHOOKID].nType = WH_CALLWNDPROC; myhookdata[CALLWNDHOOKID].hkproc = CallWndProc; myhookdata[GETMSGHOOKID].nType = WH_GETMESSAGE; myhookdata[GETMSGHOOKID].hkproc = GetMsgProc; } void InitHooks() { for( int i=0 ; ihwnd; msg.message = cwpMsg->message; msg.lParam = cwpMsg->lParam; msg.wParam = cwpMsg->wParam; msg.pt.x = -1; msg.pt.y = -1; msg.time = -1; HookProc(CALLWNDHOOKID, nCode, &msg); return CallNextHookEx(myhookdata[CALLWNDHOOKID].hookhandle, nCode, wParam, lParam); } LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { PMSG msg = (PMSG) lParam; HookProc(GETMSGHOOKID,nCode, msg); return CallNextHookEx(myhookdata[GETMSGHOOKID].hookhandle, nCode, wParam, lParam); } void HookProc(int nFrom, int nCode, PMSG msg) { #ifdef __TIMING__ SYSTEMTIME systemTime; GetSystemTime( &systemTime ); int startTime = systemTime.wMilliseconds+systemTime.wSecond*1000; #endif DWORD waitResult; // simple heuristic to eliminate duplicate messages if( !( MessageEquals(*msg, lastmsg) || keyAlreadyPressed(*msg) || keyNotPressed(*msg) ) ) { lastmsg = *msg; if( msg->message==WM_KEYDOWN || msg->message==WM_SYSKEYDOWN ) { keysPressed[msg->wParam] = true; } if( msg->message==WM_KEYUP || msg->message==WM_SYSKEYUP ) { keysPressed[msg->wParam] = false; } // message filter: // all messages that are defined in this switch statement will be part of the log switch(msg->message) { // messages for monitoring GUI state case WM_CREATE: case WM_DESTROY: case WM_SETTEXT: // mouse messages case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_MBUTTONDBLCLK: case WM_XBUTTONDOWN: case WM_XBUTTONUP: case WM_XBUTTONDBLCLK: case WM_NCLBUTTONDOWN: case WM_NCLBUTTONUP: case WM_NCLBUTTONDBLCLK: case WM_NCRBUTTONDOWN: case WM_NCRBUTTONUP: case WM_NCRBUTTONDBLCLK: case WM_NCMBUTTONDOWN: case WM_NCMBUTTONUP: case WM_NCMBUTTONDBLCLK: case WM_NCXBUTTONDOWN: case WM_NCXBUTTONUP: case WM_NCXBUTTONDBLCLK: // keyboard messages case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: // internal messages usefull for replay/matching of events case WM_KILLFOCUS: case WM_SETFOCUS: case WM_COMMAND: case WM_SYSCOMMAND: case WM_HSCROLL: case WM_VSCROLL: case WM_MENUSELECT: case WM_USER: waitResult = WaitForSingleObject(mutex, 1000); if( waitResult==WAIT_OBJECT_0 ) { WriteLogentryWString(msg, nFrom); ReleaseMutex(mutex); } #ifdef __TIMING__ msgCounter++; msgCounterChange = true; #endif // __TIMING__ break; default: break; } } #ifdef __TIMING__ GetSystemTime( &systemTime ); timing += systemTime.wMilliseconds+systemTime.wSecond*1000-startTime; totalMsgCounter++; if( msgCounterChange && msgCounter%100==0 ) { #ifdef __USING_MTRACE__ char * mtraceBuffer = new char[128]; sprintf(mtraceBuffer, "ul timing: %llu \t\t %llu \t\t %llu", timing, msgCounter, totalMsgCounter); MTrace_AddToLevel(traceLevel,mtraceBuffer); delete mtraceBuffer; msgCounterChange = false; #endif // __USING_MTRACE__ } #endif // __TIMING__ } void WriteLogentryWString(PMSG msg, int nFrom) { wchar_t * messageStr = NULL; wchar_t buffer[128]; wchar_t * newWindowText = NULL; wchar_t * windowName = NULL; unsigned int command = 0; int sourceType = -1; HWND source = NULL; HWND parentHandle = NULL; wchar_t * windowClass = NULL; bool isPopup = false; bool isModal = false; bool htMenu = false; HWND menuHandle = NULL; int scrollPos = -1; unsigned int scrollType = 0; HWND scrollBarHandle = NULL; int retVal = 0; int pointx = -1; int pointy = -1; // debug vars retVal = GetWindowText(msg->hwnd, buffer, 128); if( retVal > 0 && retValhwnd); if( windowResourceId<0 ) { windowResourceId = 0; } //************************************** // Message specific variables //************************************** if( msg->message==WM_COMMAND ) { command = LOWORD(msg->wParam); sourceType = HIWORD(msg->wParam); source = (HWND) msg->lParam; } if( msg->message==WM_SYSCOMMAND ) { command = LOWORD(msg->wParam); } if( msg->message==WM_CREATE ) { parentHandle = GetParent(msg->hwnd); retVal = GetClassName(msg->hwnd, buffer, 128); if( retVal > 0 && retValmessage==WM_SETTEXT ) { wchar_t * newWindowTextBuffer = (wchar_t*)msg->lParam; if( newWindowTextBuffer!=NULL ) { size_t len = wcslen(newWindowTextBuffer); replaceWithXmlEntitiesWString(newWindowTextBuffer, &newWindowText, len+1); } } if( msg->message==WM_LBUTTONUP || msg->message==WM_RBUTTONUP || msg->message==WM_MBUTTONUP || msg->message==WM_LBUTTONDOWN || msg->message==WM_RBUTTONDOWN || msg->message==WM_MBUTTONDOWN || msg->message==WM_LBUTTONDBLCLK || msg->message==WM_RBUTTONDBLCLK || msg->message==WM_MBUTTONDBLCLK) { RECT r; DWORD dCursorPos = GetMessagePos(); GetWindowRect(msg->hwnd, &r); //dont log absolut coordinates but relativ ones so you can use them in rule "LeftClickRelativ" pointx = GET_X_LPARAM(dCursorPos)-r.left; pointy = GET_Y_LPARAM(dCursorPos)-r.top; } if( msg->message==WM_NCLBUTTONDOWN ) { if( msg->wParam==HTMENU ) { htMenu = true; } } if( msg->message==WM_INITMENU ) { menuHandle = (HWND) msg->wParam; } if( msg->message==WM_HSCROLL || msg->message==WM_VSCROLL ) { scrollType = LOWORD(msg->wParam); scrollPos = HIWORD(msg->wParam); scrollBarHandle = (HWND) msg->lParam; } /***************************************/ // put debugging variables here /***************************************/ /*************************************** * Printing part ***************************************/ size_t bufsize = 2048; wchar_t * msgBuffer = new wchar_t[bufsize]; size_t pos = 0; //pos += swprintf_s(msgBuffer+pos, bufsize-pos,LOGPREFIXWSTRING); // print msg information pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"",msg->message); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", msg->wParam); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", msg->lParam); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", msg->hwnd); if( msg->message==WM_COMMAND ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"",command); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"",sourceType); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"",source); } if( msg->message==WM_SYSCOMMAND ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", command); } if( msg->message==WM_LBUTTONUP || msg->message==WM_RBUTTONUP || msg->message==WM_MBUTTONUP || msg->message==WM_LBUTTONDOWN || msg->message==WM_RBUTTONDOWN || msg->message==WM_MBUTTONDOWN || msg->message==WM_LBUTTONDBLCLK || msg->message==WM_RBUTTONDBLCLK || msg->message==WM_MBUTTONDBLCLK) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", pointx); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", pointy); if(msg->message == WM_LBUTTONUP) { //check the listBox selection, store it in "scrollPos" //no selection = -1 //this is only working for listBoxes with style 'selection = single' retVal = GetClassName(msg->hwnd, buffer, 128); if( retVal >= -1 && retVal < MAXINT && !lstrcmpi(buffer, L"ListBox") ) { scrollPos = (int)SendMessage(msg->hwnd, LB_GETCURSEL, 0, 0); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", scrollPos); } //check the TabControl selection, store it in "scrollPos" //no selection = -1 retVal = GetClassName(msg->hwnd, buffer, 128); if( retVal >= -1 && retVal < MAXINT && !lstrcmpi(buffer, L"SysTabControl32") ) { scrollPos = (int)SendMessage(msg->hwnd, (UINT)4875, 0, 0); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", scrollPos); } } } if( msg->message==WM_MOUSEACTIVATE ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", (HWND) msg->wParam); } if( msg->message==WM_KEYUP || msg->message==WM_KEYDOWN || msg->message==WM_SYSKEYUP || msg->message==WM_SYSKEYDOWN ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", LOWORD(msg->wParam)); } if( msg->message==WM_SETTEXT ) { if( newWindowText!=NULL ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", newWindowText); } } if( msg->message==WM_NCLBUTTONDOWN && htMenu ) { pos += swprintf_s(msgBuffer+pos, bufsize-pos,L""); } if( msg->message==WM_INITMENU ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", menuHandle); } if( msg->message==WM_CREATE ) { // print window information if( windowName!=NULL ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", windowName); } if( windowResourceId>0 ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", windowResourceId); } if( msg->message==WM_CREATE ) { if( parentHandle!=NULL ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", parentHandle); } if( windowClass!=NULL ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", windowClass); } if( isModal ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L""); } } } if( msg->message==WM_HSCROLL || msg->message==WM_VSCROLL ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", scrollType); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", scrollPos); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", scrollBarHandle); } if( msg->time!=-1 ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", msg->time); } /***************************************/ // put debugging and experimental output stuff here /***************************************/ #ifdef __INCLUDEHOOKINFO__ pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", nFrom); #endif pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", msg->hwnd); #ifdef __USING_MTRACE__ #ifdef __ENCODE_BASE64__ size_t arraySize = (pos+1)*2; size_t encodingSize = arraySize*2; char * base64Buffer = new char[encodingSize]; base64::encoder enc; retVal = enc.encode((char*)msgBuffer, arraySize, base64Buffer); base64Buffer[retVal] = '\0'; char * mtraceBuffer = new char[retVal+30]; sprintf_s(mtraceBuffer,retVal+29,"%s%s", LOGPREFIX, base64Buffer); delete base64Buffer; #else char * mtraceBuffer = new char[pos+1]; size_t numConverted; wcstombs_s(&numConverted,mtraceBuffer, pos+1, msgBuffer, pos); #endif // __ENCODE_BASE64__ MTrace_AddToLevel(traceLevel,mtraceBuffer); delete mtraceBuffer; #endif // __USING_MTRACE__ #ifdef __USING_COSTUMLOG__ SYSTEMTIME currentTime; GetSystemTime(¤tTime); logfile << currentTime.wDay << "." << currentTime.wMonth << "." << currentTime.wYear << " "; logfile << currentTime.wHour << ":" << currentTime.wMinute << ":" << currentTime.wSecond << ":"; logfile << currentTime.wMilliseconds << "\t"; logfile << buffer << std::endl; #endif delete messageStr; delete newWindowText; delete windowName; delete windowClass; delete msgBuffer; }