#include "stdafx.h" #include "userlog.h" #include #include #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; HANDLE mutex; USERLOG_API void __cdecl InitUsagelog() { mutex = CreateMutex(NULL, FALSE, TEXT("USAGELOGMUTEX")); if( mutex == NULL ) { MessageBox(0, L"MutexFailure", L"MutexFailure", 0); } #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; if( !MessageEquals(lastmsg, msg) ) { lastmsg = msg; 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; if( !MessageEquals(*msg, lastmsg)) { lastmsg = *msg; 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; // inverse filter: defined messages will be filtered, all else just passes through // may be replaced with a lookup-table to improve perfomance // upon completion of the rules, i.e., when it is clear which messages are required, // this should be changed to a "normal" filter. switch(msg->message) { case WM_NULL: case WM_MOVE: case WM_SIZE: case WM_GETTEXT: case WM_GETTEXTLENGTH: case WM_PAINT: case WM_ERASEBKGND: case WM_SHOWWINDOW: case WM_CANCELMODE: case WM_SETCURSOR: case WM_GETMINMAXINFO: case WM_GETFONT: case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: case WM_NOTIFY: case WM_STYLECHANGING: case WM_STYLECHANGED: case WM_GETICON: case WM_NCCREATE: case WM_NCDESTROY: case WM_NCCALCSIZE: case WM_NCHITTEST: case WM_NCPAINT: case WM_GETDLGCODE: case 0x0090: // WM_UAHDESTROYWINDOW case 0x0091: // WM_UAHDRAWMENU case 0x0092: // WM_UADRAWMENUITEM case 0x0093: // WM_UAHINITMENU case 0x0094: // WM_UAHMEASUREMENUITEM case 0x0095: // WM_UAHNCPAINTMENUPOPUP case WM_NCMOUSEMOVE: case WM_TIMER: case WM_ENTERIDLE: case WM_CTLCOLORMSGBOX: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLORSCROLLBAR: case WM_CTLCOLORSTATIC: case WM_MOUSEMOVE: case WM_PARENTNOTIFY: case WM_MDIGETACTIVE: case WM_IME_NOTIFY: case WM_IME_SETCONTEXT: case WM_AFXFIRST: case WM_AFXFIRST+1: case WM_AFXFIRST+2: case WM_AFXFIRST+3: case WM_AFXFIRST+4: case WM_AFXFIRST+5: case WM_AFXFIRST+6: case WM_AFXFIRST+7: case WM_AFXFIRST+8: case WM_AFXFIRST+9: case WM_AFXFIRST+10: case WM_AFXFIRST+11: case WM_AFXFIRST+12: case WM_AFXFIRST+13: case WM_AFXFIRST+14: case WM_AFXFIRST+15: case WM_AFXFIRST+16: case WM_AFXFIRST+17: case WM_AFXFIRST+18: case WM_AFXFIRST+19: case WM_AFXFIRST+20: case WM_AFXFIRST+21: case WM_AFXFIRST+22: case WM_AFXFIRST+23: case WM_AFXFIRST+24: case WM_AFXFIRST+25: case WM_AFXFIRST+26: case WM_AFXFIRST+27: case WM_AFXFIRST+28: case WM_AFXFIRST+29: case WM_AFXFIRST+30: case WM_AFXLAST: case 1025: case 1031: case 1142: case 2024: case 4100: case 4101: case 4103: case 4352: case 4362: case 4363: case 4364: case 4365: case 4372: case 4613: break; default: // exclude messages 0xC000-0xFFFF if( !(msg->message>=0xC000 && msg->message<=0xFFFF) ) { waitResult = WaitForSingleObject(mutex, 1000); if( waitResult==WAIT_OBJECT_0 ) { WriteLogentryWString(msg, nFrom); ReleaseMutex(mutex); } #ifdef __TIMING__ msgCounter++; msgCounterChange = true; #endif // __TIMING__ } 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__ } /////////////////////////////////////////////////////////// // 2 Byte character functions /////////////////////////////////////////////////////////// bool MessageEquals(const MSG & msg1, const MSG & msg2) { bool retVal = false; if( (msg1.time==-1 && msg1.pt.x==-1 && msg1.pt.y==-1) || (msg2.time==-1 && msg2.pt.x==-1 && msg2.pt.y==-1) ) { retVal = msg1.hwnd==msg2.hwnd && msg1.message==msg2.message && msg1.lParam==msg2.lParam && msg1.wParam==msg2.wParam; } else { retVal = msg1.hwnd==msg2.hwnd && msg1.message==msg2.message && msg1.lParam==msg2.lParam && msg1.wParam==msg2.wParam && msg1.time==msg2.time && msg1.pt.x==msg2.pt.x && msg1.pt.y==msg2.pt.y; } return retVal; } int replaceWithXmlEntitiesWString(const wchar_t * source, wchar_t ** target, size_t sourceLength) { size_t j=0; size_t extraLength = 0; size_t bufsize = 300; wchar_t * tmpTarget = new wchar_t[sourceLength+bufsize]; size_t i; for( i=0; i': tmpTarget[j] = L'&'; tmpTarget[j+1]=L'g'; tmpTarget[j+2]=L't'; tmpTarget[j+3]=L';'; j += 4; extraLength += 3; break; case L'\"': tmpTarget[j] = L'&'; tmpTarget[j+1]=L'q'; tmpTarget[j+2]=L'u'; tmpTarget[j+3]=L'o'; tmpTarget[j+4]=L't'; tmpTarget[j+5]=L';'; j += 6; extraLength += 5; break; case L'\'': tmpTarget[j] = L'&'; tmpTarget[j+1]=L'a'; tmpTarget[j+2]=L'p'; tmpTarget[j+3]=L'o'; tmpTarget[j+4]=L's'; tmpTarget[j+5]=L';'; j += 6; extraLength += 5; break; case L'%': tmpTarget[j] = L'\\'; tmpTarget[j+1] = L'%'; j += 2; extraLength += 1; break; default: tmpTarget[j] = source[i]; j++; } } *target = new wchar_t[j+1]; memcpy(*target,tmpTarget,j*sizeof(wchar_t)); (*target)[j] = '\0'; return j; } 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; // 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_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) { if( msg->time>-1 ) { pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", msg->pt.x); pos += swprintf_s(msgBuffer+pos,bufsize-pos,L"", msg->pt.y); } 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); } } } 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; }