#include #include #include "itsutils.h" #include "stringutils.h" #include "kernelmisc.h" #include "ptrutils.h" #include "cever_deps.h" ITSUTILS_API HRESULT STDAPICALLTYPE ITShowWindow( DWORD cbInput, ShowWindowParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; switch(pbInput->dwShow) { case SW_SETFOREGROUND: if (!SetForegroundWindow(pbInput->hWnd)) return GetLastError(); break; case SW_SETACTIVE: if (NULL==SetActiveWindow(pbInput->hWnd)) return GetLastError(); break; case SW_SETCAPTURE: if (NULL==SetCapture(pbInput->hWnd)) return GetLastError(); break; case SW_BRINGTOTOP: if (!BringWindowToTop(pbInput->hWnd)) return GetLastError(); break; case SW_DRAWMENUBAR: if (!DrawMenuBar(pbInput->hWnd)) return GetLastError(); break; case SW_DESTROYWINDOW: if (!DestroyWindow(pbInput->hWnd)) return GetLastError(); break; case SW_UPDATEWINDOW: if (!UpdateWindow(pbInput->hWnd)) return GetLastError(); break; case SW_HIDECARET: if (!HideCaret(pbInput->hWnd)) return GetLastError(); break; case SW_SHOWCARET: if (!ShowCaret(pbInput->hWnd)) return GetLastError(); break; case SW_SETFOCUS: if (NULL==SetFocus(pbInput->hWnd)) return GetLastError(); break; case SW_ENABLEWINDOW: if (!EnableWindow(pbInput->hWnd, TRUE)) return GetLastError(); break; case SW_DISABLEWINDOW: if (!EnableWindow(pbInput->hWnd, FALSE)) return GetLastError(); break; case SW_ENDDIALOGOK: if (!EndDialog(pbInput->hWnd, IDOK)) return GetLastError(); break; case SW_ENDDIALOGCANCEL: if (!EndDialog(pbInput->hWnd, IDCANCEL)) return GetLastError(); break; case SW_ENDDIALOGCLOSE: if (!EndDialog(pbInput->hWnd, IDCLOSE)) return GetLastError(); break; case SW_ENDDIALOGABORT: if (!EndDialog(pbInput->hWnd, IDABORT)) return GetLastError(); break; default: if (!ShowWindow(pbInput->hWnd, pbInput->dwShow)) return GetLastError(); } return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITFindWindow( DWORD cbInput, FindWindowParams *pbInput, DWORD *pcbOutput, FindWindowResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(FindWindowResult); FindWindowResult *pOut= *ppbOutput= (FindWindowResult*)LocalAlloc(LPTR, *pcbOutput); pOut->hWnd= FindWindow(pbInput->szClassName[0]?pbInput->szClassName:NULL, pbInput->szWindowName[0]?pbInput->szWindowName:NULL); if (pOut->hWnd==NULL) return GetLastError(); return 0; } DWORD send_string(bool bPost, HWND hWnd, DWORD nMsg, const char* str, DWORD lParam) { DWORD lRes= 0; for (const char*p= str ; *p ; p++) { if (bPost) { if (!PostMessage(hWnd, nMsg, *p, lParam)) { lRes= GetLastError(); break; } } else { lRes= SendMessage(hWnd, nMsg, *p, lParam); } } return lRes; } bool is_char_message(DWORD nMsg) { return nMsg>=WM_KEYFIRST && nMsg<=WM_KEYLAST; } ITSUTILS_API HRESULT STDAPICALLTYPE ITSendMessage( DWORD cbInput, SendMessageParams *pbInput, DWORD *pcbOutput, SendMessageResult **ppbOutput, IRAPIStream *pStream) { // debug("ITSendMessage(%08lx %08lx %08lx %08lx %08lx %08lx, %d)\n", // pbInput->dwFlags, pbInput->dwResultAlloc, pbInput->hWnd, // pbInput->nMsg, pbInput->wParam, pbInput->lParam, // cbInput-PTR_DIFF(pbInput, pbInput->buf)); SendMessageResult *pOut = NULL; *pcbOutput= PTR_DIFF(pOut, pOut->buf+pbInput->dwResultAlloc); pOut= *ppbOutput= (SendMessageResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) return ERROR_NOT_ENOUGH_MEMORY; WPARAM wParam = pbInput->wParam; if (pbInput->dwFlags&SMGS_WPARAM_IS_INPUTOFS) wParam += (DWORD)pbInput->buf; else if (pbInput->dwFlags&SMGS_WPARAM_IS_OUTPUTOFS) wParam += (DWORD)pOut->buf; LPARAM lParam = pbInput->lParam; if (pbInput->dwFlags&SMGS_LPARAM_IS_INPUTOFS) lParam += (DWORD)pbInput->buf; else if (pbInput->dwFlags&SMGS_LPARAM_IS_OUTPUTOFS) lParam += (DWORD)pOut->buf; KernelMode _km; DWORD res= 0; if (is_char_message(pbInput->nMsg) && (pbInput->dwFlags&SMGS_WPARAM_IS_INPUTOFS)) { pOut->lResult= send_string(pbInput->dwFlags&SMGS_POSTMESSAGE, pbInput->hWnd, pbInput->nMsg, (char*)wParam, lParam); } else if (pbInput->dwFlags&SMGS_POSTMESSAGE) { // debug("PostMessage(%08lx, %08lx, %08lx, %08lx) [%x]\n", // pbInput->hWnd, pbInput->nMsg, wParam, lParam, pbInput->dwFlags&15); if (!PostMessage(pbInput->hWnd, pbInput->nMsg, wParam, lParam)) res= GetLastError(); pOut->lResult= 0; } else { // debug("SendMessage(%08lx, %08lx, %08lx, %08lx) [%x]\n", // pbInput->hWnd, pbInput->nMsg, wParam, lParam, pbInput->dwFlags&15); pOut->lResult= SendMessage(pbInput->hWnd, pbInput->nMsg, wParam, lParam); } if (pbInput->dwFlags&SMGS_WAITWINDOW) { DWORD pid; GetWindowThreadProcessId(pbInput->hWnd, &pid); HANDLE hProc= OpenProcess(0,0, pid); if (WAIT_TIMEOUT==WaitForSingleObject(hProc, 20000)) return WAIT_TIMEOUT; CloseHandle(hProc); } return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetForegroundWindow( DWORD cbInput, BYTE *pbInput, DWORD *pcbOutput, GetForegroundWindowResult **ppbOutput, IRAPIStream *pStream) { GetForegroundWindowResult *pOut=NULL; *pcbOutput= sizeof(GetForegroundWindowResult); pOut= *ppbOutput= (GetForegroundWindowResult*)LocalAlloc(LPTR, *pcbOutput); pOut->hwnd= GetForegroundWindow(); return 0; } DWORD GetGwesVMbase() { static DWORD gwesbase= 0; if (gwesbase) return gwesbase; PROCESS *gwesproc= FindProcessForName(L"gwes.exe"); if (gwesproc==NULL) return 0; gwesbase= getProcessVMBase(gwesproc); return gwesbase; } DWORD ReadGwesDword(DWORD pdw) { return *(DWORD*)MapPtrWithBits(pdw, GetGwesVMbase()); } void CopyGwesString(WCHAR *str, DWORD pstr, int maxsize) { if (pstr==NULL) { str[0]= 0; return; } wcsncpy(str, (WCHAR*)MapPtrWithBits(pstr, GetGwesVMbase()), maxsize); } void ReadGwesData(void *dst, DWORD src, int size) { memcpy(dst, (void*)MapPtrWithBits(src, GetGwesVMbase()), size); } bool wnd_shortstruct(DWORD hwnd) { static bool bShortStruct= (ReadGwesDword(hwnd+4*3)==0x574e4457); return bShortStruct; } DWORD HWND_GetParent(DWORD hwnd) { if (hwnd==NULL) return NULL; if (wnd_shortstruct(hwnd)) return ReadGwesDword(hwnd+4*1); else return ReadGwesDword(hwnd+4*2); } DWORD HWND_GetFirstChild(DWORD hwnd) { if (hwnd==NULL) return NULL; if (wnd_shortstruct(hwnd)) return ReadGwesDword(hwnd+4*2); else return ReadGwesDword(hwnd+4*3); } DWORD HWND_GetNextSibling(DWORD hwnd) { if (hwnd==NULL) return NULL; return ReadGwesDword(hwnd+4*0); } DWORD HWND_GetProcess(DWORD hwnd) { if (hwnd==NULL) return NULL; if (wnd_shortstruct(hwnd)) return ReadGwesDword(hwnd+4*0x22); else return ReadGwesDword(hwnd+4*0x26); } DWORD FindWndRoot() { DWORD hWnd= (DWORD)GetForegroundWindow(); if (hWnd==NULL) return 0x7c070060; DWORD hParent; while (hParent=HWND_GetParent(hWnd)) hWnd= hParent; return hWnd; } class WindowInfo { public: WindowInfo(DWORD hwnd, int level, bool bVerbose) : _verbose(bVerbose) { memset(&info, 0, sizeof(info)); info.hwnd= (HWND)hwnd; info.level= level; if (ReadGwesDword(hwnd+4*3)==0x574e4457) load_shortwnd(hwnd); else if (ReadGwesDword(hwnd+4*5)==0x574e4457) load_longwnd(hwnd); else { // not a HWND return; } } void load_shortwnd(DWORD hwnd) { info.nextsibling= (HWND)HWND_GetNextSibling(hwnd); info.parent= (HWND)HWND_GetParent(hwnd); info.firstchild= (HWND)HWND_GetFirstChild(hwnd); // 0x03 magic 'WNDW' // 0x04 parentB // 0x05 1stchldB // 0x06 nextsibB // 0x07 ? ReadGwesData(&info.wrect, hwnd+4*8, sizeof(RECT)); ReadGwesData(&info.crect, hwnd+4*12, sizeof(RECT)); // 0x10 type pw1 ( 0x50 sized struct ) // 0x11 type pw1 ( 0x50 sized struct ) // 0x12 type pw1 ( 0x50 sized struct ) // 0x13 // 0x14 // 0x15 // 0x16 // 0x17 type (0x28 sized struct) // 0x18 // 0x19 type (0x68 sized struct) CopyGwesString(info.wtitle, ReadGwesDword(hwnd+0x1a*4), 32); if (info.wtitle[0]==0xffff || info.wtitle[1]==0xffff) { debug("%08lx title: %s\n", hwnd, hexdump((BYTE*)info.wtitle, 32, 2).c_str()); // todo: not sure what this means, wtitle contains { 0xffff, 0x10, 0 ... } // maybe it is a resource reference info.wtitle[0]= '?'; info.wtitle[1]= '?'; info.wtitle[2]= '?'; } info.wtitle[31]=0; info.msgq= ReadGwesDword(hwnd+4*0x1b); info.ime= ReadGwesDword(hwnd+4*0x1c); info.style= ReadGwesDword(hwnd+4*0x1d); info.exstyle= ReadGwesDword(hwnd+4*0x1e); DWORD hcls= ReadGwesDword(hwnd+0x1f*4); // 0x20 window id info.usrdata= ReadGwesDword(hwnd+4*0x21); info.pid= HWND_GetProcess(hwnd); info.tid= ReadGwesDword(hwnd+4*0x23); info.pid2= ReadGwesDword(hwnd+4*0x24); info.wndproc= ReadGwesDword(hwnd+4*0x25); // 0x26 // 0x27 // 0x28 // 0x29 // 0x2a // 0x2b // 0x2c // 0x2d if (hcls) { load_class(hcls); ReadGwesData(info.wlongs, hwnd+0x2e*4, std::min(info.nlongs,(DWORD)8)*sizeof(DWORD)); } if (_verbose) { GetWindowText((HWND)hwnd, info.wtext, 32); info.wtext[31]= 0; } else { info.wtext[0]= 0; } } void load_longwnd(DWORD hwnd) { info.nextsibling= (HWND)HWND_GetNextSibling(hwnd); // 0x01 previous sibling info.parent= (HWND)HWND_GetParent(hwnd); info.firstchild= (HWND)HWND_GetFirstChild(hwnd); // 0x04 last child // 0x05 magic 'WNDW' // 0x06 parentB // 0x07 1stchldB // 0x08 nextsibB // 0x09 ? some wnd ReadGwesData(&info.wrect, hwnd+4*10, sizeof(RECT)); ReadGwesData(&info.crect, hwnd+4*14, sizeof(RECT)); // 0x12 type pw1 ( 0x50 sized struct in gwes mem ) // 0x13 type pw1 ( 0x50 sized struct in gwes mem ) // 0x14 type pw1 ( 0x50 sized struct in gwes mem ) // 0x15 0 // 0x16 0 // 0x17 0 // 0x18 0 // 0x19 ( 0x30 sized struct in gwes mem ) // 0x1a 0 or 0x10 // 0x1b ( 0x70 sized struct in gwes mem ) // 0x1c ( 0x10 sized struct in gwes mem ) containing ptr -> ( 0x30 sized struct ) CopyGwesString(info.wtitle, ReadGwesDword(hwnd+0x1d*4), 32); if (info.wtitle[0]==0xffff || info.wtitle[1]==0xffff) { debug("%08lx title: %s\n", hwnd, hexdump((BYTE*)info.wtitle, 32, 2).c_str()); // todo: not sure what this means, wtitle contains { 0xffff, 0x10, 0 ... } // maybe it is a resource reference info.wtitle[0]= '?'; info.wtitle[1]= '?'; info.wtitle[2]= '?'; } info.wtitle[31]=0; info.msgq= ReadGwesDword(hwnd+4*0x1e); //info.ime ?? // 0x1f -> 0x20 sized struct in process space // 0x20 some pid info.style= ReadGwesDword(hwnd+4*0x21); info.exstyle= ReadGwesDword(hwnd+4*0x22); DWORD hcls= ReadGwesDword(hwnd+0x23*4); // 0x24 window id info.usrdata= ReadGwesDword(hwnd+4*0x25); info.pid= HWND_GetProcess(hwnd); info.tid= ReadGwesDword(hwnd+4*0x27); info.pid2= ReadGwesDword(hwnd+4*0x28); info.wndproc= ReadGwesDword(hwnd+4*0x29); // 0x2a 0 // 0x2b 2 words // 0x2c 2 words // 0x2d 2 words // 0x2e 0 // 0x2f -> points to 0x70 size struct // 0x30 -> {0x1ff0000, 0x00ff0000} // 0x31 0 // 0x32 {0,8,0xc} // 0x33 0 // 0x34 2 words // 0x35 {0,2} // 0x36 0 // 0x37 0 // 0x38 misc, wnd, and other ptrs // 0x39 misc if (hcls) { load_class(hcls); ReadGwesData(info.wlongs, hwnd+0x3a*4, std::min(info.nlongs,(DWORD)8)*sizeof(DWORD)); } if (_verbose) { GetWindowText((HWND)hwnd, info.wtext, 32); info.wtext[31]= 0; } else { info.wtext[0]= 0; } } void load_class(DWORD hcls) { CopyGwesString(info.wclass, ReadGwesDword(hcls+5*4), 32); info.wclass[31]=0; info.nlongs= ReadGwesDword(hcls)>>18; } bool _verbose; ITSWindowInfo info; }; typedef std::vector WindowInfoList; bool GetWindowList(DWORD hwnd, DWORD hproc, bool bVerbose, WindowInfoList& list, int level) { if (hwnd==NULL) hwnd= FindWndRoot(); else hwnd= HWND_GetFirstChild(hwnd); while (hwnd) { if (hproc==0 || HWND_GetProcess(hwnd)==hproc) { list.push_back(WindowInfo(hwnd, level, bVerbose)); GetWindowList(hwnd, hproc, bVerbose, list, level+1); } hwnd= HWND_GetNextSibling(hwnd); } // todo: get directly from heap at 0x7c070000 return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetWindowList( DWORD cbInput, GetWindowListParams *pbInput, DWORD *pcbOutput, GetWindowListResult **ppbOutput, IRAPIStream *pStream) { GetWindowListResult *pOut = *ppbOutput =NULL; *pcbOutput= 0; KernelMode _km; WindowInfoList list; if (!GetWindowList(pbInput->hWnd, pbInput->hProc, pbInput->bVerbose, list, 0)) { return ERROR_NOT_FOUND; } *pcbOutput= PTR_DIFF(pOut, pOut->info+list.size()); pOut= *ppbOutput= (GetWindowListResult*)LocalAlloc(LPTR, *pcbOutput); pOut->count= list.size(); for (unsigned i=0 ; iinfo[i], &list[i].info, sizeof(ITSWindowInfo)); } return 0; }