1 /*---------------------------------------------------------------------------- 2 ** wpickclick.c 3 ** Utilty to pick clicks posted to Wine Windows 4 ** 5 ** 6 **--------------------------------------------------------------------------- 7 ** Copyright 2004 Jozef Stefanka for CodeWeavers, Inc. 8 ** Copyright 2005 Francois Gouget for CodeWeavers, Inc. 9 ** Copyright 2005 Dmitry Timoshkov for CodeWeavers, Inc. 10 ** 11 ** This program is free software; you can redistribute it and/or modify 12 ** it under the terms of the GNU General Public License as published by 13 ** the Free Software Foundation; either version 2 of the License, or 14 ** (at your option) any later version. 15 ** 16 ** This program is distributed in the hope that it will be useful, 17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 ** GNU General Public License for more details. 20 ** 21 ** You should have received a copy of the GNU General Public License 22 ** along with this program; if not, write to the Free Software 23 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 ** 25 **--------------------------------------------------------------------------*/ 26 #include <stdio.h> 27 #include <fcntl.h> 28 #include <io.h> 29 #include <windows.h> 30 31 #include "hook.h" 32 33 34 #define APP_NAME "wpickclick.exe" 35 36 37 static BOOL (WINAPI *pInstallHooks)(HMODULE hdll); 38 static void (WINAPI *pRemoveHooks)(); 39 static action_t* (WINAPI *pGetAction)(); 40 static void (WINAPI *pFreeAction)(action_t* action); 41 42 43 /* 44 * Provide some basic debugging support. 45 */ 46 #ifdef __GNUC__ 47 #define __PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args))) 48 #else 49 #define __PRINTF_ATTR(fmt,args) 50 #endif 51 static int debug_on=0; 52 static int init_debug() 53 { 54 char* str=getenv("CXTEST_DEBUG"); 55 if (str && strstr(str, "+hook")) 56 debug_on=1; 57 return debug_on; 58 } 59 60 static void cxlog(const char* format, ...) __PRINTF_ATTR(1,2); 61 static void cxlog(const char* format, ...) 62 { 63 va_list valist; 64 65 if (debug_on) 66 { 67 va_start(valist, format); 68 vfprintf(stderr, format, valist); 69 va_end(valist); 70 } 71 } 72 73 static HINSTANCE load_hook_dll() 74 { 75 HINSTANCE hinstDll; 76 char dllpath[MAX_PATH]; 77 char* p; 78 79 hinstDll=LoadLibrary("hook.dll"); 80 if (hinstDll != NULL) 81 return hinstDll; 82 83 if (!GetModuleFileName(NULL,dllpath,sizeof(dllpath))) 84 return NULL; 85 86 p=strrchr(dllpath,'\\'); 87 if (!p) 88 return NULL; 89 *p='\0'; 90 p=strrchr(dllpath,'\\'); 91 if (!p) 92 return NULL; 93 *p='\0'; 94 strcat(dllpath,"\\hookdll\\hook.dll"); 95 hinstDll=LoadLibrary(dllpath); 96 return hinstDll; 97 } 98 99 char* cleanup(char* str) 100 { 101 char* s; 102 103 while (*str==' ' || *str=='\t' || *str=='\r' || *str=='\n') 104 str++; 105 s=strchr(str,'\n'); 106 if (!s) 107 s=str+strlen(str)-1; 108 while (s>str && (*s==' ' || *s=='\t' || *s=='\r' || *s=='\n')) 109 s--; 110 *(s+1)='\0'; 111 return str; 112 } 113 114 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 115 LPSTR lpCmdLine, int nCmdShow) 116 { 117 HINSTANCE hDll; 118 action_t* action; 119 120 init_debug(); 121 122 /* Our scripts expect Unix-style line ends */ 123 _setmode(1,_O_BINARY); 124 _setmode(2,_O_BINARY); 125 126 if (strstr(lpCmdLine,"--help")) 127 { 128 fprintf(stderr,"%s - Utility to print coordinates, component, window title, component class and window class name of a click\n", APP_NAME); 129 fprintf(stderr,"----------------------------------------------\n"); 130 fprintf(stderr,"Usage: %s\n",APP_NAME); 131 fprintf(stderr,"The options are as follows:\n"); 132 fprintf(stderr,"After starting you can\n"); 133 fprintf(stderr,"select where to click. If we properly track the click, it will be reported\n"); 134 fprintf(stderr,"in the following format:\n"); 135 fprintf(stderr," button-name x y component_name window_name component_class_name window_class_name\n"); 136 fprintf(stderr,"Note that x and y can be negative; this typically happens if you click within the\n"); 137 fprintf(stderr,"window manager decorations of a given window.\n"); 138 fprintf(stderr,"On success, %s returns 0, non zero on some failure\n",APP_NAME); 139 exit(0); 140 }; 141 142 /* Load the hook library */ 143 hDll = load_hook_dll(); 144 if (!hDll) 145 { 146 fprintf(stderr, "Error: Unable to load 'hook.dll'\n"); 147 printf("failed\n"); 148 return 1; 149 } 150 151 pInstallHooks=(void*)GetProcAddress(hDll, "InstallHooks"); 152 pRemoveHooks=(void*)GetProcAddress(hDll, "RemoveHooks"); 153 pGetAction=(void*)GetProcAddress(hDll, "GetAction"); 154 pFreeAction=(void*)GetProcAddress(hDll, "FreeAction"); 155 if (!pInstallHooks || !pRemoveHooks || !pGetAction) 156 { 157 fprintf(stderr, "Error: Unable to get the hook.dll functions (%ld)\n", 158 GetLastError()); 159 printf("failed\n"); 160 return 1; 161 } 162 163 if (!pInstallHooks(hDll)) 164 { 165 fprintf(stderr, "Error: Unable to install the hooks (%ld)\n", 166 GetLastError()); 167 printf("failed\n"); 168 return 1; 169 } 170 171 fprintf(stderr, "Ready for capture...\n"); 172 action=pGetAction(); 173 if (!action) 174 { 175 fprintf(stderr, "Error: GetAction() failed\n"); 176 printf("failed\n"); 177 return 1; 178 } 179 180 switch (action->action) 181 { 182 case ACTION_FAILED: 183 printf("failed\n"); 184 break; 185 case ACTION_NONE: 186 printf("none\n"); 187 break; 188 case ACTION_FIND: 189 printf("find\n"); 190 break; 191 case ACTION_BUTTON1: 192 case ACTION_BUTTON2: 193 case ACTION_BUTTON3: 194 printf("button%d %ld %ld\n", action->action-ACTION_BUTTON1+1, 195 action->x, action->y); 196 break; 197 default: 198 fprintf(stderr, "Error: Unknown action %d\n",action->action); 199 printf("%d\n", action->action); 200 break; 201 } 202 printf("%s\n", action->window_class); 203 printf("%s\n", action->window_title); 204 printf("%ld\n", action->control_id); 205 printf("%s\n", action->control_class); 206 printf("%s\n", cleanup(action->control_caption)); 207 208 cxlog("\n%s: action=%d x=%ld y=%ld\n", __FILE__, action->action, 209 action->x, action->y); 210 cxlog("window_class='%s'\n", action->window_class); 211 cxlog("window_title='%s'\n", action->window_title); 212 cxlog("control_id=%ld\n", action->control_id); 213 cxlog("control_class='%s'\n", action->control_class); 214 cxlog("control_caption='%s'\n", action->control_caption); 215 216 pFreeAction(action); 217 pRemoveHooks(); 218 return 0; 219 } 220