/* (C) 2003-2007 Willem Jan Hengeveld * Web: http://www.xs4all.nl/~itsme/ * http://wiki.xda-developers.com/ * * $Id$ * * 0x0002= WM_DESTROY (0,0) * 0x0010= WM_CLOSE (0,0) * 0x000A= WM_ENABLE (fEnable, 0) * 0x0012= WM_QUIT (nExitCode, 0) * 0x0111= WM_COMMAND (wNotify<<16 | wId, hWndCtl) * BN_CLICKED = 0 * * * todo: add parser to pass struct contents, like this: * * { dw:0x124, w:0x1234, w:0, {"ptrtostring"} , sz32:"fixedstring" } * * example usage: * ppostmsg -w Listview 0x104b 0 -rl 44 { dw:0 dw:2 } * should return info about the item at position 2 * * * todo: add option to send string as many 'WM_CHAR' messages * todo: add option to use hProc, or hWnd in getwindowlist * */ #include #ifdef WINCEPOSTMSG #include "itsutils.h" #include "wintrace.h" #include "dllversion.h" #include #endif #include "debug.h" #include "stringutils.h" #include "args.h" #include "ptrutils.h" #include "vectorutils.h" #include #include #ifdef WIN32POSTMSG #include "procthreadstructs.h" // ITSWindowInfo #endif #ifdef WINCEPOSTMSG struct show_value_map { DWORD dwShowValue; std::string command; }; show_value_map showvalues[]= { { SW_HIDE , "hide" }, { SW_SHOWNORMAL , "shownormal" }, { SW_SHOWNOACTIVATE , "shownoactivate" }, { SW_SHOW , "show" }, { SW_MINIMIZE , "minimize" }, { SW_SHOWNA , "showna" }, { SW_SHOWMAXIMIZED , "showmaximized" }, { SW_MAXIMIZE , "maximize" }, { SW_RESTORE , "restore" }, { SW_SETFOREGROUND , "setforeground" }, { SW_SETACTIVE , "setactive" }, { SW_SETCAPTURE , "setcapture" }, { SW_BRINGTOTOP , "bringtotop" }, { SW_DRAWMENUBAR , "drawmenubar" }, { SW_DESTROYWINDOW , "destroywindow" }, { SW_UPDATEWINDOW , "updatewindow" }, { SW_HIDECARET , "hidecaret" }, { SW_SHOWCARET , "showcaret" }, { SW_SETFOCUS , "setfocus" }, { SW_ENABLEWINDOW , "enablewindow" }, { SW_DISABLEWINDOW , "disablewindow" }, { SW_ENDDIALOGOK , "enddialogok" }, { SW_ENDDIALOGCANCEL , "enddialogcancel" }, { SW_ENDDIALOGCLOSE , "enddialogclose" }, { SW_ENDDIALOGABORT , "enddialogabort" }, }; #define N_SHOWVALS (sizeof(showvalues)/sizeof(*showvalues)) #endif bool g_verbose= false; typedef std::vector WindowInfoList; #ifdef WINCEPOSTMSG HANDLE ITGetProcessHandle(const std::string& processname); bool ITTraceWindow(int cmd, HWND hWnd); #endif bool ITGetWindowList(WindowInfoList& list, HWND hwnd, HANDLE hproc, bool bVerbose); HWND ITGetForegroundWindow(); void fill_windowinfo(HWND hWnd, int level, bool bVerbose, ITSWindowInfo &info); HWND ITFindWindow(const std::string& classname, const std::string& windowname); bool ITShowWindow(HWND hWnd, DWORD dwShow); bool ITSendMessage(HWND hWnd, DWORD nMsg, DWORD wParam, DWORD lParam, DWORD dwFlags, const ByteVector &indata, DWORD *plResult, ByteVector &outdata); void ListWindows(HANDLE hProc, BOOL bVerbose); void ShowWindowInfo(HWND hWnd); #ifdef WIN32POSTMSG #define SMGS_WPARAM_IS_INPUTOFS 1 #define SMGS_WPARAM_IS_OUTPUTOFS 2 #define SMGS_LPARAM_IS_INPUTOFS 4 #define SMGS_LPARAM_IS_OUTPUTOFS 8 #define SMGS_POSTMESSAGE 16 #define SMGS_WAITWINDOW 32 #endif bool ParseParamString(const char *arg, ByteVector& wParamSend, DWORD& wParam) { char *p= NULL; DWORD value= strtoul(arg, &p, 0); if (p!=arg) { wParam= value; return true; } wParamSend.resize(strlen(arg)); memcpy(vectorptr(wParamSend), arg, wParamSend.size()); return true; } #ifdef WIN32POSTMSG char *GetAppPath() { static char appname[1024]; if (!GetModuleFileName(NULL, appname, 1024)) return NULL; return appname; } #endif DWORD ParseMessage(const char *msg) { char *p= NULL; DWORD dwMsg= strtoul(msg, &p, 0); if (p!=msg) return dwMsg; std::string approot= GetAppPath(); approot.resize(approot.find_last_of('\\')); approot += "\\its_windows_message_list.txt"; FILE *f= fopen(approot.c_str(), "r"); if (f==NULL) return 0; char linebuf[256]; while (fgets(linebuf, sizeof(linebuf), f)) { if (isspace(linebuf[0])) continue; char *p= strtok(linebuf, "\t \r\n"); // get message class ( 'WM' ) if (p==NULL || *p==0) continue; p= strtok(NULL, "\t \r\n"); // get message nr if (p==NULL || *p==0) continue; DWORD dwMsg= strtoul(p, 0, 0); p= strtok(NULL, "\t \r\n"); // get message name if (p==NULL || *p==0) continue; if (stringicompare(std::string(msg), std::string(p))==0) { fclose(f); return dwMsg; } } fclose(f); return 0; } void usage() { printf("(C) 2003-2008 Willem jan Hengeveld itsme@xs4all.nl\n"); printf("Usage: psendmsg [options] msg wparam lparam\n"); printf(" numbers can be specified as 0x1234abcd\n"); printf(" either specify a handle, or a name+class\n"); printf(" -p POST instead of SEND\n"); printf(" -l list all windows\n"); printf(" -v more info in list\n"); printf(" -W after message, wait until window disappears\n"); printf(" -show show window\n"); printf(" -hide hide window\n"); printf(" -t CMD trace window messages\n"); printf(" CMD: start, stop, add, del, addproc, delproc\n"); printf(" -n NAME processname, use with -t addproc\n"); printf(" -h HANDLE use window handle - default = foreground\n"); printf(" -w WINDOWNAME find window by name\n"); printf(" -c CLASSNAME limit find to classname\n"); printf(" -rw SIZE wparam is buffer of SIZE bytes\n"); printf(" -rl SIZE lparam is buffer of SIZE bytes\n"); printf(" wparam and lparam may be specified as hexnumber\n"); printf(" or as quoted string\n"); #ifdef WINCEPOSTMSG printf(" --WNDCOMMAND one of:\n"); size_t col=0; for (size_t i=0 ; i=80) { putchar('\n'); col=0; } else { putchar(' '); col++; } } printf("%s", showvalues[i].command.c_str()); col += showvalues[i].command.size(); } printf("\n"); #endif } #ifdef WINCEPOSTMSG DWORD getShowValue(const char*name) { for (size_t i=0 ; ihWnd; RapiFree(outbuf); return hWnd; } HWND ITGetForegroundWindow() { DWORD outsize=0; GetForegroundWindowResult *outbuf=NULL; HRESULT res= ItsutilsInvoke("ITGetForegroundWindow", 0, NULL, &outsize, (BYTE**)&outbuf); if (res || outbuf==NULL) { error(res, "ITGetForegroundWindow"); return 0; } HWND hWnd= outbuf->hwnd; RapiFree(outbuf); return hWnd; } bool ITGetWindowList(WindowInfoList& list, HWND hwnd, HANDLE hproc, bool bVerbose) { DWORD outsize=0; GetWindowListResult *outbuf=NULL; GetWindowListParams inbuf; inbuf.hWnd= (DWORD)hwnd; inbuf.hProc= (DWORD)hproc; inbuf.bVerbose= bVerbose; HRESULT res= ItsutilsInvoke("ITGetWindowList", sizeof(inbuf), (BYTE*)&inbuf, &outsize, (BYTE**)&outbuf); if (res || outbuf==NULL) { error(res, "ITGetWindowList"); return false; } list.resize(outbuf->count); memcpy(vectorptr(list), outbuf->info, outbuf->count*sizeof(ITSWindowInfo)); RapiFree(outbuf); return true; } bool ITShowWindow(HWND hWnd, DWORD dwShow) { ShowWindowParams request; DWORD reqsize= sizeof(request); request.hWnd= hWnd; request.dwShow= dwShow; DWORD repsize=0; HRESULT res= ItsutilsInvoke("ITShowWindow", reqsize, (BYTE*)&request, &repsize, NULL); if (res) { error(res, "ITShowWindow"); return false; } return true; } bool ITSendMessage(HWND hWnd, DWORD nMsg, DWORD wParam, DWORD lParam, DWORD dwFlags, const ByteVector &indata, DWORD *plResult, ByteVector &outdata) { SendMessageParams *request= NULL; DWORD reqsize= PTR_DIFF(request, request->buf+indata.size()); request= (SendMessageParams*)RapiAlloc(reqsize); request->hWnd= hWnd; request->nMsg= nMsg; request->wParam= wParam; request->lParam= lParam; if (!indata.empty()) memcpy(request->buf, vectorptr(indata), indata.size()); request->dwResultAlloc= outdata.size(); request->dwFlags= dwFlags; DWORD repsize=0; SendMessageResult *reply= NULL; HRESULT res= ItsutilsInvoke("ITSendMessage", reqsize, (BYTE*)request, &repsize, (BYTE**)&reply); if (res) { error(res, "ITSendMessage"); return false; } if (reply==NULL) { debug("ITSendMessage: reply=NULL, repsize=%d\n", repsize); return false; } *plResult= reply->lResult; DWORD outresult= repsize - PTR_DIFF(reply, reply->buf); if (outdata.size() != outresult) debug("WARNING: ITSendMessage: outsize(%d) != resultsize(%d)\n", outdata.size(), outresult); if (!outdata.empty()) { outdata.resize(outresult); memcpy(vectorptr(outdata), reply->buf, outdata.size()); } RapiFree(reply); return true; } bool ITTraceWindow(int cmd, HWND hWnd) { TraceWindowParams request; DWORD reqsize= sizeof(request); request.cmd= cmd; request.hWnd= (DWORD)hWnd; DWORD repsize=0; HRESULT res= ItsutilsInvoke("ITTraceWindow", reqsize, (BYTE*)&request, &repsize, NULL); if (res) { error(res, "ITTraceWindow"); return false; } return true; } #endif #ifdef WIN32POSTMSG HWND ITFindWindow(const std::string& classname, const std::string& windowname) { return FindWindowEx(NULL, NULL, classname.empty() ? NULL : classname.c_str(), windowname.empty() ? NULL : windowname.c_str()); } HWND ITGetForegroundWindow() { return GetForegroundWindow(); } void fill_windowinfo(HWND hWnd, int level, bool bVerbose, ITSWindowInfo &info) { info.level = level; info.hwnd= hWnd; // HWND info.nextsibling= GetWindow(hWnd, GW_HWNDNEXT); // HWND dw 00 info.parent= GetWindow(hWnd, GW_OWNER); // HWND dw 01 info.firstchild= GetWindow(hWnd, GW_CHILD); // HWND dw 02 // todo: info.wtitle GetClassNameW(hWnd, info.wclass, 32); // WCHAR[32] dw 1f.05 if (bVerbose) { GetWindowTextW(hWnd, info.wtext, 32); // WCHAR[32] dw 1a info.wtext[31]=0; } else info.wtext[0]=0; info.msgq=0; // DWORD dw 1b info.ime=0; // DWORD dw 1c info.style= GetWindowLong(hWnd, GWL_STYLE); // DWORD dw 1d info.exstyle= GetWindowLong(hWnd, GWL_EXSTYLE); // DWORD dw 1e info.usrdata= GetWindowLong(hWnd, GWL_USERDATA); // DWORD dw 21 info.pid= GetWindowLong(hWnd, GWL_HINSTANCE); // DWORD dw 22 info.tid=0; // DWORD dw 23 GetWindowThreadProcessId(hWnd, &info.pid2); // DWORD dw 24 info.wndproc= GetWindowLong(hWnd, GWL_WNDPROC); // DWORD dw 25 GetWindowRect(hWnd, &info.wrect); // RECT dw 08 GetClientRect(hWnd, &info.crect); // RECT dw 0c info.nlongs= GetClassLong(hWnd, GCL_CBWNDEXTRA); // DWORD dw 1f.00:hi // DWORD[8] dw 2e for (int i=0 ; i<8 ; i++) info.wlongs[i]= GetWindowLong(hWnd, i); } struct enuminfo { WindowInfoList *list; int level; HANDLE hProc; HWND hWnd; BOOL bVerbose; }; BOOL WINAPI enumchildren(HWND hWnd, LPARAM lParam); BOOL WINAPI addtolist(HWND hWnd, LPARAM lParam) { enuminfo *p= reinterpret_cast(lParam); // int GetWindowTextLength(hWnd) // int GetWindowText(hWnd, LPTSTR, strsize) //+ BOOL GetClientRect(hWnd, RECT*) //+ BOOL GetWindowRect(hWnd, RECT*) // DWORD GetWindowLong(hWnd, n) // GWL_WNDPROC // GWL_HINSTANCE // GWL_HWNDPARENT //+ GWL_STYLE //+ GWL_EXSTYLE // GWL_USERDATA // GWL_ID // DWORD GetClassLong(IN HWND hWnd, IN int nIndex); // CL_MENUNAME // GCL_HBRBACKGROUND // GCL_HCURSOR // GCL_HICON // GCL_HMODULE // GCL_CBWNDEXTRA // GCL_CBCLSEXTRA // GCL_WNDPROC // GCL_STYLE // GCW_ATOM // GCL_HICONSM // HWND GetParent(hWnd) // int GetClassName(hWnd, LPTSTR, maxsize) // HWND GetWindow(hWnd, n) // GW_HWNDFIRST // GW_HWNDLAST // GW_HWNDNEXT // GW_HWNDPREV // GW_OWNER // GW_CHILD // UINT GetWindowModuleFileName(hWnd, LPTSTR, maxsize) // // GetWindowInfo(hWnd, WINDOWINFO*) if ((p->hWnd==0 && p->hProc==0) || (p->hWnd==hWnd) || (p->hProc==(HANDLE)GetWindowLong(hWnd, GWL_HINSTANCE))) { p->list->resize(p->list->size()+1); fill_windowinfo(hWnd, p->level, p->bVerbose, p->list->back()); } enumchildren(hWnd, lParam); return TRUE;// continue enumeration } BOOL WINAPI enumchildren(HWND hWnd, LPARAM lParam) { enuminfo *p= reinterpret_cast(lParam); p->level++; if (!EnumChildWindows(hWnd, addtolist, lParam)) { //error("EnumChildWindows"); } p->level--; return TRUE;// continue enumeration } bool ITGetWindowList(WindowInfoList& list, HWND hwnd, HANDLE hproc, bool bVerbose) { enuminfo info; info.list= &list; info.hWnd= hwnd; info.hProc= hproc; info.bVerbose= bVerbose; info.level= 0; if (!EnumWindows(enumchildren, reinterpret_cast(&info))) { error("EnumWindows"); return false; } return true; } bool ITShowWindow(HWND hWnd, DWORD dwShow) { return FALSE!=ShowWindow(hWnd, dwShow); } 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; } bool ITSendMessage(HWND hWnd, DWORD nMsg, DWORD inpwParam, DWORD inplParam, DWORD dwFlags, const ByteVector &indata, DWORD *plResult, ByteVector &outdata) { WPARAM wParam = inpwParam; if (dwFlags&SMGS_WPARAM_IS_INPUTOFS) wParam += (DWORD)vectorptr(indata); else if (dwFlags&SMGS_WPARAM_IS_OUTPUTOFS) wParam += (DWORD)vectorptr(outdata); LPARAM lParam = inplParam; if (dwFlags&SMGS_LPARAM_IS_INPUTOFS) lParam += (DWORD)vectorptr(indata); else if (dwFlags&SMGS_LPARAM_IS_OUTPUTOFS) lParam += (DWORD)vectorptr(outdata); if (is_char_message(nMsg) && (dwFlags&SMGS_WPARAM_IS_INPUTOFS)) { *plResult= send_string(dwFlags&SMGS_POSTMESSAGE, hWnd, nMsg, (char*)wParam, lParam); } else if (dwFlags&SMGS_POSTMESSAGE) { debug("PostMessage(%08lx, %08lx, %08lx, %08lx) [%x]\n", hWnd, nMsg, wParam, lParam, dwFlags&15); if (!PostMessage(hWnd, nMsg, wParam, lParam)) { error("PostMessage"); return false; } } else { debug("SendMessage(%08lx, %08lx, %08lx, %08lx) [%x]\n", hWnd, nMsg, wParam, lParam, dwFlags&15); *plResult= SendMessage(hWnd, nMsg, wParam, lParam); } if (dwFlags&SMGS_WAITWINDOW) { DWORD pid; GetWindowThreadProcessId(hWnd, &pid); HANDLE hProc= OpenProcess(0,0, pid); if (WAIT_TIMEOUT==WaitForSingleObject(hProc, 20000)) return false; CloseHandle(hProc); } return true; } #endif