OSDN Git Service

f70d949217755f11189973ca84d1b0a586769f08
[dokopop/dokopop.git] / DCHook / DCHook.cpp
1 //---------------------------------------------------------------------------
2 //
3 // \96â\91è\93_\81F
4 // Ver0.50
5 //
6 // \8dÅ\93K\89»\82Ì\89Û\91è\81F
7 // standard library\82ð\8eg\82í\82È\82¢\82æ\82¤\82É\82·\82é
8 // \8b¤\97L\97Ì\88æ\82ð\91\9d\82â\82·
9 //
10 // Tips:
11 // \93Ë\91RDetach\82³\82ê\82é\8c»\8fÛ
12 // --> Hook Function\82Å\97á\8aO\82ª\94­\90\82µ\82Ä\82¢\82é\89Â\94\\90«\82ª\8d\82\82¢
13 //     \82à\82µ\82­\82Í\81A\83A\83v\83\8a\83P\81[\83V\83\87\83\93\82Å\97á\8aO\94­\90\82µ\82Ä\82¢\82é
14 // \8b¤\97L\83\81\83\82\83\8a\82É\82Â\82¢\82Ä
15 // \95¨\97\9d\83\81\83\82\83\8a\82ª\93¯\88ê\82¾\82¯\82Å\82 \82Á\82Ä\81A\98_\97\9d\83A\83h\83\8c\83X\82Í\93¯\88ê\82Æ\82Í\8cÀ\82ç\82È\82¢\81I\81I
16 // \8f]\82Á\82Ä\81A\8b¤\97L\83\81\83\82\83\8a\8fã\82Épointer\82ð\94z\92u\82·\82é\82±\82Æ\82Í\8aî\96{\93I\82É\8aë\8c¯\81I\81I
17 #define STRICT
18 #include <windows.h>
19 #include <tchar.h>
20 #pragma hdrstop
21 #ifndef GWL_WNDPROC
22 #define GWL_WNDPROC         (-4)        // \82±\82Ì\92è\8b`\82ª\82È\82¢\82Æerror\82É\82È\82Á\82½ 2014.11.19
23 #endif
24 #include <tlhelp32.h>
25 #include <imagehlp.h>
26 #pragma comment(lib, "ImageHlp")
27 #include "DCHook.h"
28 #ifndef UNICODE
29 #include "..\VxD\hk95d.h"
30 #endif
31 #include "MonitorScale.h"
32
33 // Compiler //
34 #pragma warning( disable : 4710 )       // \82Ç\82¤\82µ\82Ä\82±\82¤\82¢\82¤warning\82ª\8fo\82Ä\82­\82é\82Ì\82©\81H
35
36 // Configuration //
37 #define USE_SCALING             1       // Uses DPI scaling
38
39 #define USE_DBW                 1       // DBW\82ð\8eg\97p\82·\82é
40 #define USE_SHARE0              1       // share\82µ\82Ä\82à\96â\91è\82È\82¢\95Ï\90\94
41
42 #define METAEXTTEXTOUT  1       // MetaMethod\82ÅExtTextOutx\82ðhook\82·\82é
43 #define HOOK_GETDC              0       // GetDC(),ReleaseDC()\82ðhook\82·\82é
44 #define HOOK_TEXT               0       // DrawText(Ex),TextOut,TabbedTextOut\82Ìhooking
45 #define USE_REDRAW              1
46 #define HOOK_BITBLT             0       // 2016.1.15 \8aO\82µ\82Ä\82Ý\82½
47 #define HOOK_PAINT              0
48 #define GUARD                   0       // \8b¤\97L\83\81\83\82\83\8a\82ðVirtualProtect\82Åguard\82·\82é
49                                                         // \97L\8cø\82É\82·\82é\82ÆApplication\8fI\97¹\8e\9e\82É\88Ù\8fí\8fI\97¹\82ª\94­\90\82·\82é
50                             // Application close ->
51                             // \8c´\88ö\81FDettach\82·\82é\91O\82É\81AOS or Application\82ª
52                             // Protected code\97Ì\88æ\82É\8f\91\82«\8d\9e\82Ý\82ð\8ds\82Á\82Ä\82¢\82é\82æ\82¤\82¾
53
54 #define USE_INVALIDATE          0       // \95`\89æ\91O\82ÉInvalidate\82ð\91\97\82é(IE5@Win98\82Í\95K\97v)
55 #define INVALIDATE_TRUE         0       // InvalidateRect\82Årepaint\82ð\8ds\82¤
56 #define ORG_OFFSET                      1       // ViewPort\82Ìorg offset\8f\88\97\9d\82ð\8ds\82¤
57
58 #define USE_OPTIMALINVALID      1       // \8dÄ\95`\89æ\97Ì\88æ\82ð\82È\82é\82×\82­\8f¬\82³\82­\82·\82é
59 #define USE_VXD                         0       // no longer support (Win9x)
60 #define EXC_WOW64                       0       // do not attach on WOW64
61
62 #define MAX_KEYS                        8       // \83L\81[\83t\83\89\83O\82Ì\8dÅ\91å\92è\8b`\90\94
63
64 #define DEBUG_HITTEXT           0       // for debug hit text
65
66 // ExtTextOut hooking\82ÅMetafile\82à\8eg\97p\82·\82é
67 // \92P\93Æ\82Å\8ds\82¤\8fê\8d\87\82Í\81ARETRYMETA
68 #if HOOK_PAINT || HOOK_GETDC || !USE_REDRAW
69 #define USE_META        1
70 #else
71 #define USE_META        0
72 #endif
73
74 #define RETRYMETA       1
75
76 #if USE_DBW
77 #include <stdio.h>
78 #else   // !USE_DBW
79 #undef DEBUG_HITTEXT
80 #define DEBUG_HITTEXT   0
81 #endif  // !USE_DBW
82
83 #define MOVESEND_POST   1
84
85 // Type Definitions //
86
87 // Macros //
88 #if GUARD
89 #define PROTECT_SHARE()         ShareProtect( true )
90 #define UNPROTECT_SHARE()       ShareProtect( false )
91 #else
92 #define PROTECT_SHARE()
93 #define UNPROTECT_SHARE()
94 #endif
95
96 #if USE_DBW
97 #define DBW             dbw
98 #else
99 #define DBW             (void)
100 #endif
101 void dbw(const char *format, ...);
102
103 #define WM_AMODI                                (WM_APP+0x400)  // app communication message with AMODI
104 #define WM_MOVESEND                             (WM_APP+0x208)  // DCH_MOVESEND\82Ì\91ã\82í\82è\82ÉPostMessage\82Å\91\97\82é
105 #define AMODI_CMD_QUERY                 0
106 #define AMODI_CMD_PAGE_CAPTURE  1
107
108 #define tsizeof(type)   sizeof(type)
109 #define int_bool(v)             ((v)!=0)
110
111 #pragma warning (disable : 4996)
112
113 //==============================================//
114 // TString template class                                               //
115 //==============================================//
116 template <class T>
117 class TString {
118 protected:
119         T *Buffer;
120         int Size;       // Buffer size in character
121         int Length;     // String length in character
122 public:
123         TString();
124         ~TString();
125         void Clear()
126                 { Buffer[0] = '\0'; Length = 0; }
127         void Set( const T *str, int len );
128         void Set( TString *obj )
129                 { Set( obj->c_str(), obj->Length ); }
130         void Cat( const T *str, int len );
131         operator const T *() const
132                 { return Buffer; }
133         T operator [] ( int index )
134                 { return Buffer[index]; }
135         const T *c_str()
136                 { return Buffer; }
137         int GetLength() const { return Length; }
138         int GetByte() const { return Length * sizeof(T); }
139 //      int GetSize() const { return Size; }
140 };
141 template <class T>
142 TString<T>::TString()
143 {
144         Size = 256;             // initial size
145         Buffer = new T[ Size + 1 ];
146         if (!Buffer)
147                 Size = 0;
148         Length = 0;
149 }
150 template <class T>
151 TString<T>::~TString()
152 {
153         if (Buffer)
154                 delete[] Buffer;
155 }
156 template <class T>
157 void TString<T>::Set( const T *str, int len )
158 {
159         if (Buffer){
160                 if ( Size < len ){
161                         // not enough space to store
162                         delete[] Buffer;
163                 } else goto j1;
164         }
165         Buffer = new T[ len + 1 ];
166         Size = len;
167         if (Buffer){
168 j1:;
169                 CopyMemory( Buffer, str, len*sizeof(T) );
170                 Buffer[len] = '\0';
171                 Length = len;
172         } else {
173                 Size = 0;
174                 Length = 0;
175         }
176 }
177 template <class T>
178 void TString<T>::Cat( const T *str, int len )
179 {
180         if (!Buffer){
181                 Set( str, len );
182                 return;
183         }
184         int newlen = Length + len;
185         if (Size < newlen){
186                 T *p = new T[ newlen + 1 ];
187                 if (p)
188                         CopyMemory( p, Buffer, newlen*sizeof(T) );
189                 delete[] Buffer;
190                 Buffer = p;
191                 Size = newlen;
192         }
193         if (Buffer){
194                 CopyMemory( Buffer+Length, str, len * sizeof(T) );
195                 Buffer[newlen] = '\0';
196                 Length = newlen;
197         } else {
198                 Size = 0;
199                 Length = 0;
200                 Set( str, len );
201         }
202 }
203
204 int GetTextFromPoint( HDC hdc, const char *text, int len, int pos, int pos_y, const int *dx=NULL );
205 int GetTextFromPoint( HDC hdc, const wchar_t *text, int len, int pos, int pos_y, const int *dx=NULL );
206
207 bool CaptureImage(HWND hwnd, bool movesend, bool non_block);
208 bool WaitAndGetResult(const TCHAR *text_path, unsigned waittime);
209 HANDLE WaitForResult(const TCHAR *text_path, unsigned waittime);
210 HWND FindAMODI();
211 int SendAMODI(int cmd, const char *data, int len);
212 void CheckAMODIAlive();
213 void SendMoveMessage();
214 void SendCancelMove();
215 DWORD WINAPI SendMoveThread(LPVOID vdParam);
216 void CheckWOW64();
217
218 extern "C" {
219 //==============================================//
220 // Prototypes                                                                   //
221 //==============================================//
222 typedef HDC (WINAPI *FNBeginPaint)( HWND, LPPAINTSTRUCT );
223 typedef BOOL (WINAPI *FNEndPaint)( HWND, CONST PAINTSTRUCT * );
224 typedef HDC (WINAPI *FNGetDC)( HWND );
225 typedef int (WINAPI *FNReleaseDC)( HWND, HDC );
226 typedef BOOL (WINAPI *FNExtTextOutW)(HDC hdc, int x, int y, UINT option, CONST RECT *rc, LPCWSTR str, UINT count, CONST INT *dx );
227 typedef BOOL (WINAPI *FNExtTextOutA)(HDC hdc, int x, int y, UINT option, CONST RECT *rc, LPCSTR str, UINT count, CONST INT *dx );
228 typedef BOOL (WINAPI *FNBitBlt)(HDC hdcdest, int xdest, int ydest, int width, int height, HDC hdcsrc, int xsrc, int ysrc, DWORD rop );
229
230 typedef LONG (WINAPI *FNTabbedTextOutA)( HDC hdc, int x, int y, LPCSTR str, int count, int ntabs, LPINT tabs, int origin );
231 typedef LONG (WINAPI *FNTabbedTextOutW)( HDC hdc, int x, int y, LPCWSTR str, int count, int ntabs, LPINT tabs, int origin );
232 typedef BOOL (WINAPI *FNTextOutA)( HDC hdc, int x, int y, LPCSTR str, int count );
233 typedef BOOL (WINAPI *FNTextOutW)( HDC hdc, int x, int y, LPCWSTR str, int count );
234 typedef int (WINAPI *FNDrawTextA)( HDC hdc, LPCSTR str, int count, LPRECT rc, UINT format );
235 typedef int (WINAPI *FNDrawTextW)( HDC hdc, LPCWSTR str, int count, LPRECT rc, UINT format );
236 typedef int (WINAPI *FNDrawTextExA)( HDC hdc, LPCSTR str, int count, LPRECT rc, UINT format, LPDRAWTEXTPARAMS params );
237 typedef int (WINAPI *FNDrawTextExW)( HDC hdc, LPCWSTR str, int count, LPRECT rc, UINT format, LPDRAWTEXTPARAMS params );
238
239 typedef BOOL (WINAPI *FNMoveToEx)(HDC hdc, int x, int y, LPPOINT pt );
240
241
242 HDC WINAPI _BeginPaint( HWND hwnd, LPPAINTSTRUCT ps );
243 BOOL WINAPI _EndPaint( HWND hwnd, CONST PAINTSTRUCT *ps );
244 HDC WINAPI _GetDC( HWND hwnd );
245 int WINAPI _ReleaseDC( HWND hwnd, HDC hdc );
246 BOOL  WINAPI _ExtTextOutA(HDC hdc, int x, int y, UINT option, CONST RECT *rc, LPCSTR str, UINT count, CONST INT *dx );
247 BOOL  WINAPI _ExtTextOutW(HDC hdc, int x, int y, UINT option, CONST RECT *rc, LPCWSTR str, UINT count, CONST INT *dx );
248 BOOL WINAPI _BitBlt(HDC hdcdest, int xdest, int ydest, int width, int height, HDC hdcsrc, int xsrc, int ysrc, DWORD rop );
249
250 LONG WINAPI _TabbedTextOutA( HDC hdc, int x, int y, LPCSTR str, int count, int ntabs, LPINT tabs, int origin );
251 LONG WINAPI _TabbedTextOutW( HDC hdc, int x, int y, LPCWSTR str, int count, int ntabs, LPINT tabs, int origin );
252 BOOL WINAPI _TextOutA( HDC hdc, int x, int y, LPCSTR str, int count );
253 BOOL WINAPI _TextOutW( HDC hdc, int x, int y, LPCWSTR str, int count );
254 int WINAPI _DrawTextA( HDC hdc, LPCSTR str, int count, LPRECT rc, UINT format );
255 int WINAPI _DrawTextW( HDC hdc, LPCWSTR str, int count, LPRECT rc, UINT format );
256 int WINAPI _DrawTextExA( HDC hdc, LPCSTR str, int count, LPRECT rc, UINT format, LPDRAWTEXTPARAMS params );
257 int WINAPI _DrawTextExW( HDC hdc, LPCWSTR str, int count, LPRECT rc, UINT format, LPDRAWTEXTPARAMS params );
258
259 BOOL WINAPI _MoveToEx( HDC hdc, int x, int y, LPPOINT pt );
260
261 void ShareProtect( bool f );
262 DWORD SetWriteProtect( LPVOID addr, bool f );
263 bool ChangeMemory( void *dst, const void *src, unsigned size );
264 bool LoadVxD();
265 void UnloadVxD();
266
267 static HMODULE ModuleFromAddress(PVOID pv);
268
269 // Prototypes for PSAPI.DLL //
270 typedef BOOL (WINAPI *FNEnumProcessModules)( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded );
271 typedef DWORD (WINAPI *FNGetModuleFileNameExA)( HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );
272 typedef HANDLE (WINAPI *FNCreateToolhelp32Snapshot)( DWORD dwFlags, DWORD th32ProcessID );
273 typedef BOOL (WINAPI *FNModule32First)( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
274 typedef BOOL (WINAPI *FNModule32Next)( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
275
276
277 LRESULT CALLBACK MouseProc( int code, WPARAM wParam, LPARAM lParam );
278 LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam );
279 bool CaptureText( HWND hwnd, bool movesend );
280 bool DoCapture(HWND hwnd, POINT pt, bool movesend, bool image_only=false, bool runOnLaunchedProc=false, bool nonBlock=false);
281 void DokoPopMenu( HWND hwnd );
282 void ToggleClick( HWND hwnd );
283 int CALLBACK EnumMetaFileProc( HDC hdc, HANDLETABLE *, CONST ENHMETARECORD *mfr, int nobj, LPARAM user );
284
285 //__declspec(dllexport)
286 BOOL  WINAPI _ExtTextOutA(HDC hdc, int x, int y, UINT option, CONST RECT *rc, LPCSTR str, UINT count, CONST INT *dx );
287
288 #if METAEXTTEXTOUT
289 void ExtTextOutHit();
290 #endif
291
292 void DoScale(HDC hdc, POINT *pts, int num);
293
294 // Prototypes for High DPI //
295 typedef enum _PROCESS_DPI_AWARENESS { 
296   Process_DPI_Unaware            = 0,
297   Process_System_DPI_Aware       = 1,
298   Process_Per_Monitor_DPI_Aware  = 2
299 } PROCESS_DPI_AWARENESS;
300
301 typedef HRESULT (WINAPI *FNGetProcessDPIAwareness)(HANDLE hprocess, PROCESS_DPI_AWARENESS *value);
302 typedef HRESULT (WINAPI *FNSetProcessDPIAwareness)(PROCESS_DPI_AWARENESS value);
303
304 //==============================================//
305 // Shared Section                                                               //
306 //==============================================//
307 #pragma data_seg(".sdata")
308 #pragma bss_seg( ".sbss" )
309 HWND hwndCallback = NULL;
310 #if USE_VXD
311 char VxDpathName[256];  // HK95.vxd path
312 #endif
313 DWORD siPageSize = 0;
314 HWND hwndOrg = NULL;
315 HWND hwndAMODI = NULL;
316 bool OnlyAMODI = false;
317 bool tryAMODI = false;
318 bool MoveSend = false;
319 #if USE_DBW
320 int attach = 0;
321 #endif
322 #if USE_VXD
323 bool WindowsNT;
324 #else
325 const bool WindowsNT = true;
326 #endif
327 bool Initialized = false;       // Whether this module initialized or not
328 DWORD idDokopopProcess;         // DKPP.EXE process ID
329 HHOOK hMouseHook;       // Windows Hook Handle for mouse
330 bool ClickOnlyEnabled = false;
331
332 struct TKeyConfig {
333         unsigned char Action;
334         int Flag;
335 };
336
337 TKeyConfig KeyConfig[MAX_KEYS] = {
338         { KA_POPUP, KF_CONTROL },                       // Ctrl+click
339         { KA_POPUP_NC, KF_CLICKONLY },                  // click\82¾\82¯\82Åpopup(DO NOT CHANGE)
340 //      { KA_MENU, KF_CONTROL | KF_MENU },      // dokopop menu
341 //      { KA_MENU, KF_CONTROL | KF_MENU | KF_CLICKONLY },       // dokopop menu
342         { KA_TOGGLE, KF_CONTROL | KF_MENU },    // dokopop menu
343         { 0, 0 }
344 };
345
346 bool fWow64 = false;
347
348 POINT CursorPoint;      // Client area coordinate //
349 POINT ScreenPoint;      // Screen coordinate //
350 POINT PrevCursorPoint;
351 HWND hwndLast = NULL;
352 DWORD PrevMoveTime = 0;
353 bool MoveSent = true;
354 bool OnlyImage = false;
355
356 bool MouseMoving;
357
358 RECT rcClient;
359 RECT rcInvalid;
360 RECT rcOrgInvalid;      // \8dÄ\95`\89æ\91O\82Éinvalid\82¾\82Á\82½\97Ì\88æ
361 bool HitFound;
362 bool RButtonUpCancel = false;   // \8e\9f\82ÌRButtonUp\82Í\94j\8aü\82·\82é
363 bool LButtonUpCancel = false;   // \8e\9f\82ÌLButtonUp\82Í\94j\8aü\82·\82é
364 bool MButtonUpCancel = false;   // \8e\9f\82ÌMButtonUp\82Í\94j\8aü\82·\82é
365 bool LButtonDown = false;
366 bool MButtonDown = false;
367
368 HINSTANCE hPSAPI;               // handle of PSAPI.DLL(NT only)
369 FNEnumProcessModules fnEnumProcessModules;
370 FNGetModuleFileNameExA fnGetModuleFileNameExA;
371 FNCreateToolhelp32Snapshot fnCreateToolhelp32Snapshot;
372 FNModule32First fnModule32First;
373 FNModule32Next fnModule32Next;
374
375 #if USE_META || RETRYMETA
376 HDC OrgHDC;
377 HDC hdcMeta;
378 #endif
379 HDC hdcExtTextOut;
380 #if HOOK_GETDC
381 HDC OrgGetDC;
382 #endif
383
384 int BitBltCount;                // \8c»\8dÝ\82ÌBitBlt\89ñ\90\94
385 int ExtTextOutCount;    // \8c»\8dÝ\82ÌBand\93à\82ÌExtTextOut\89ñ\90\94(A/W\82Æ\82à)
386 int TargetBitBltCount;  // \8c\9f\8d¸\91Î\8fÛ\82ÌBitBlt(\8f\89\89ñ\95`\89æ\8cã\82É\94»\92è) 
387 POINT TargetOffset;             // \8c\9f\8d¸\91Î\8fÛ\82ÌBitBlt\82Ì\95`\89æ\83I\83t\83Z\83b\83g(\8f\89\89ñ\95`\89æ\8cã\82É\94»\92è)
388 bool RetryPhase;
389
390 #if METAEXTTEXTOUT
391 // hit text information
392 TString<char> *FoundTextA;
393 TString<wchar_t> *FoundTextW;
394 int FoundLocA;
395 int FoundLocW;
396
397 // \8dÅ\8cã\82É\95`\89æ\82µ\82½\83e\83L\83X\83g\82Ì\8fî\95ñ
398 // for text merge
399 int LastX;      // \8dÅ\8cã\82É\95`\89æ\82µ\82½\83e\83L\83X\83g\82Ì\89E\8fã\8dÀ\95W
400 int LastY;
401 TString<char> *LastTextA;
402 TString<wchar_t> *LastTextW;
403 #endif  // METAEXTTEXTOUT
404
405 bool MoveSendMode;
406
407 TCHAR AMODIPath[256];
408 bool ExtAMODI = false;
409 int ScaleX = 0; // 96\82ð1\82Æ\82µ\82½\89æ\96Ê\82Ì\8ag\91å\97¦
410 int ScaleY = 0;
411 int generation = 0;
412 int NumPrevWords = 1;   // \89½\8cÂ\82Ü\82Å\91O\82Ì\92P\8cê\82ð\8fE\82¤\82©\81H
413
414 TCHAR ImageTextPath[256+40];    // OCR\97pimage filename or text filename
415 DWORD SaveImageTime;
416 bool CaptureImageBlocking = false;
417
418 const char STR_USER32[] = "user32.dll";
419 const char STR_GDI32[] = "gdi32.dll";
420 const char STR_KERNEL32[] = "kernel32.dll";
421 const TCHAR STR_PSAPI[] = _T("psapi.dll");
422
423 // KERNEL32.DLL //
424 const char STR_CreateToolhelp32Snapshot[] = "CreateToolhelp32Snapshot";
425 const char STR_Module32First[] = "Module32First";
426 const char STR_Module32Next[] = "Module32Next";
427
428 // PSAPI.DLL //
429 const char STR_EnumProcessModules[] = "EnumProcessModules";
430 const char STR_GetModuleFileNameExA[] = "GetModuleFileNameExA";
431
432 const char STR_BeginPaint[] = "BeginPaint";
433 const char STR_EndPaint[] = "EndPaint";
434 const char STR_BitBlt[] = "BitBlt";
435 const char STR_GetDC[] = "GetDC";
436 const char STR_ReleaseDC[] = "ReleaseDC";
437
438 const char STR_ExtTextOutA[] = "ExtTextOutA";
439 const char STR_ExtTextOutW[] = "ExtTextOutW";
440 const char STR_TabbedTextOutA[] = "TabbedTextOutA";
441 const char STR_TabbedTextOutW[] = "TabbedTextOutW";
442 const char STR_TextOutA[] = "TextOutA";
443 const char STR_TextOutW[] = "TextOutW";
444 const char STR_DrawTextA[] = "DrawTextA";
445 const char STR_DrawTextW[] = "DrawTextW";
446 const char STR_DrawTextExA[] = "DrawTextExA";
447 const char STR_DrawTextExW[] = "DrawTextExW";
448
449 #if USE_SHARE0
450 #pragma data_seg()
451 #pragma bss_seg()
452 #endif
453
454 //==============================================//
455 // Module depend values                                                 //
456 //==============================================//
457 HINSTANCE hInstance;    // attached instance
458 DWORD idProcess;                // attached process
459 HANDLE hProcess;        // Hook\8e\9eGetCurrentProcess()\82Í\8eg\82¦\82È\82¢
460                                         // Hook\8e\9e\82Ìcurrent process\82ª\8f\91\82«\8a·\82¦\82½\82¢thunk\82Ìprocess\82Æ\88ê\92v\82·\82é\82Æ\82Í\8cÀ\82ç\82È\82¢\82½\82ß
461                                         // \82»\82Ì\82½\82ß\81ADLL\82Ìattach\8e\9e\82ÉWriteProcessMemory()\97p\82Éprocess handle\82ð\8eæ\93¾\82·\82é
462 DWORD curProcess;       // hooking process
463 #if USE_VXD
464 HANDLE vxd_Handle = INVALID_HANDLE_VALUE;       // Not shared
465 #endif
466
467 #if !MOVESEND_POST
468 HANDLE SendMoveEvent = NULL;
469 DWORD SendMoveThreadId;
470 #endif
471
472 HINSTANCE hInstSHCore = NULL;
473 FNGetProcessDPIAwareness GetProcessDPIAwareness = NULL;
474
475 //==============================================//
476 // APIHOOK                                                                              //
477 //==============================================//
478 class APIHOOK {
479 public:
480         const char *ModName;
481         const char *FuncName;
482 protected:
483         bool ExcludeMe;
484         bool Hooked;
485 public:
486         PROC OrgFunc;   // not shared@NT
487 protected:
488         PROC HookFunc;  // not shared
489         // Process dedicated values //
490 public:
491         static void *MaxAppAddr;        // Maximum private memory address
492 protected:
493         static APIHOOK *LinkTop;        // top of APIHOOK link
494         APIHOOK *LinkNext;                      // next pointer of API HOOK link
495 public:
496         APIHOOK( const char *modname, const char *name, void *hookfunc, bool excme = true );
497         ~APIHOOK();
498         bool GetProcOrgFunc( HINSTANCE hInst );
499         bool GetProcOrgFunc();
500         bool HookAgain();
501         void Finish();
502 protected:
503         bool StoreCode( );
504         void RestoreCode( );
505 protected:
506         static void ReplaceIATEntryInAllMods( APIHOOK *obj, PROC pfnCurrent, PROC pfnNew );
507         static bool ReplaceIATEntryInOneMod( APIHOOK *obj, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller);
508 };
509
510 const BYTE cPushOpCode = 0x68;   // The PUSH opcode on x86 platforms
511 APIHOOK* APIHOOK::LinkTop = NULL;
512 PVOID APIHOOK::MaxAppAddr = NULL;
513
514 APIHOOK::APIHOOK( const char *modname, const char *funcname, void *hookfunc, bool excme )
515 {
516 //      DBW("APIHOOK constructor:%08X %s %s",this, modname, funcname);
517         Hooked = false;
518         ModName = modname;
519         FuncName = funcname;
520         HookFunc = (PROC)hookfunc;
521         ExcludeMe = excme;
522         LinkNext  = LinkTop;
523         LinkTop = this;
524         if (!MaxAppAddr){
525                 // Functions with address above lpMaximumApplicationAddress require
526                 // special processing (Windows 98 only)
527                 SYSTEM_INFO si;
528                 GetSystemInfo(&si);
529                 MaxAppAddr = si.lpMaximumApplicationAddress;
530         }
531 }
532
533 APIHOOK::~APIHOOK()
534 {
535         Finish();
536         // Remove this object from the linked list
537         APIHOOK* p = LinkTop;
538         if (p == this) {     // Removing the head node
539                 LinkTop = p->LinkNext;
540         } else {
541                 // Walk list from head and fix pointers
542                 for (; p->LinkNext; p = p->LinkNext){
543                         if (p->LinkNext == this) {
544                                 // Make the node that points to us point to the our next node
545                                 p->LinkNext = p->LinkNext->LinkNext;
546                                 break;
547                         }
548                 }
549         }
550 }
551 bool APIHOOK::GetProcOrgFunc()
552 {
553         return GetProcOrgFunc( GetModuleHandleA( ModName ) );
554 }
555 bool APIHOOK::GetProcOrgFunc( HINSTANCE hInst )
556 {
557         if (Hooked) return true;
558
559         // Save information about this hooked function
560         OrgFunc = ::GetProcAddress( hInst, FuncName);
561         if (!OrgFunc){
562                 DBW("Function doesn't exist =%s:%s", ModName, FuncName);
563                 return false;
564         }
565
566         if (OrgFunc > MaxAppAddr) {
567 //              DBW("The address is in a shared DLL; the address needs fixing up");
568                 PBYTE pb = (PBYTE)OrgFunc;
569                 if (pb[0] == cPushOpCode){
570                         // Skip over the PUSH op code and grab the real address
571                         PVOID pv = * (PVOID*) &pb[1];
572                         OrgFunc = (PROC) pv;
573                 }
574         }
575
576         // Set assembler code for hooking at the org entry
577         if ( !StoreCode() ){
578                 DBW("Cannot write process memory");
579                 return false;
580         }
581
582         Hooked = true;
583         return true;
584 }
585 bool APIHOOK::StoreCode( )
586 {
587         DBW("StoreCode:%s %s", ModName, FuncName);
588         // Hook this function in all currently loaded modules
589         ReplaceIATEntryInAllMods( this, OrgFunc, HookFunc );
590         return true;
591 }
592 void APIHOOK::RestoreCode()
593 {
594         DBW("RestoreCode:%s %s", ModName, FuncName);
595         ReplaceIATEntryInAllMods( this, HookFunc, OrgFunc );
596 }
597 void APIHOOK::ReplaceIATEntryInAllMods( APIHOOK *obj, PROC pfnCurrent, PROC pfnNew )
598 {
599         HMODULE hmodThisMod = obj->ExcludeMe
600                 ? ModuleFromAddress(ReplaceIATEntryInAllMods) : NULL;
601
602         DWORD cbNeeded;
603         HMODULE hMods[1024];
604         unsigned i;
605         if (fnCreateToolhelp32Snapshot){
606                 // Toolhelp\82ª\8eg\97p\82Å\82«\82é\8fê\8d\87\82Í\8eg\97p\82·\82é
607                 // Get the list of modules in this process
608                 HANDLE hSnapshot = fnCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, idProcess);
609
610                 MODULEENTRY32 me = { sizeof(me) };
611                 for (BOOL fOk = fnModule32First(hSnapshot,&me); fOk; fOk = fnModule32Next(hSnapshot,&me)){
612                         // NOTE: We don't hook functions in our own module
613                         if (me.hModule != hmodThisMod){
614         //                      DBW("Module : %s %s", me.szModule,FuncName);
615                                 // Hook this function in this module
616                                 ReplaceIATEntryInOneMod( obj, pfnCurrent, pfnNew, me.hModule);
617                         }
618                 }
619                 CloseHandle( hSnapshot );
620         } else {
621                 if( fnEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
622                 {
623                         for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
624                         {
625                                 if (hMods[i] != hmodThisMod){
626                                         char szModName[MAX_PATH];
627                                         // Get the full path to the module's file.
628                                         if ( fnGetModuleFileNameExA( hProcess, hMods[i], szModName,
629                                                                                 sizeof(szModName))){
630         //                                      DBW("Module : %s %s", szModName, FuncName );
631                                                 ReplaceIATEntryInOneMod( obj, pfnCurrent, pfnNew, hMods[i]);
632                                         }
633                                 }
634                         }
635                 }
636 #if USE_DBW
637                 else DBW("EnumProcessModules failed");
638 #endif
639         }
640 }
641
642 // This functions is almost taken from Jeffrey Richter's sample, thank you.
643 bool APIHOOK::ReplaceIATEntryInOneMod( APIHOOK *obj, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller)
644 {
645         if (!hProcess) return false;
646
647         // Get the address of the module's import section
648         ULONG ulSize;
649         PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
650                 ImageDirectoryEntryToData(hmodCaller, TRUE,
651                         IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
652
653         if (!pImportDesc){
654 //              DBW("No import section : %s", obj->ModName);
655                 return false;
656         }
657
658         // Find the import descriptor containing references to callee's functions
659         for (; pImportDesc->Name; pImportDesc++){
660                 PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
661                 if (lstrcmpiA(pszModName, obj->ModName) == 0) 
662                         break;   // Found
663         }
664
665         if (pImportDesc->Name == 0){
666 //              DBW("This module doesn't import any functions from this callee");
667                 return false;  // This module doesn't import any functions from this callee
668         }
669
670    // Get caller's import address table (IAT) for the callee's functions
671         PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) 
672                 ((PBYTE) hmodCaller + pImportDesc->FirstThunk);
673
674         // Replace current function address with new function address
675         for (; pThunk->u1.Function; pThunk++){
676                 // Get the address of the function address
677                 PROC* ppfn = (PROC*) &pThunk->u1.Function;
678                 // Is this the function we're looking for?
679                 BOOL fFound = (*ppfn == pfnCurrent);
680                 if (!fFound && (*ppfn > MaxAppAddr)){
681                         // If this is not the function and the address is in a shared DLL, 
682                         // then maybe we're running under a debugger on Windows 98. In this 
683                         // case, this address points to an instruction that may have the 
684                         // correct address.
685                         PBYTE pbInFunc = (PBYTE) *ppfn;
686                         if (pbInFunc[0] == cPushOpCode){
687                                 // We see the PUSH instruction, the real function address follows
688                                 ppfn = (PROC*) &pbInFunc[1];
689
690                                 // Is this the function we're looking for?
691                                 fFound = (*ppfn == pfnCurrent);
692                         }
693                 }
694
695                 if (fFound){
696                         // The addresses match, change the import section address
697                         if (!WriteProcessMemory(hProcess, ppfn, &pfnNew, sizeof(pfnNew), NULL)){
698                                 if (SetWriteProtect( (LPVOID)ppfn, false )==~0){        // write protection release
699                                         DBW("SetWriteProtect failed: %08X %s %s", ppfn, obj->ModName, obj->FuncName);
700                                         return false;
701                                 }
702 #if USE_VXD
703                                 if (!WindowsNT && IsBadWritePtr(ppfn,sizeof(pfnNew))){
704                                         // Windows9x shared DLL section
705                                         // change memory attribte using VxD
706                                         if (!ChangeMemory( ppfn, &pfnNew, sizeof(pfnNew) )){
707                                                 DBW("ChangeMemory failed");
708                                         }
709                                 } else
710 #endif
711                                 {
712                                         if (!WriteProcessMemory(hProcess, ppfn, &pfnNew, sizeof(pfnNew), NULL)){
713                                                 //SetWriteProtect( ppfn, true );        // restore protection
714                                                 DBW("%08X %08X %08X %08X %s %s", hProcess, ppfn, &pfnNew, sizeof(pfnNew), obj->ModName, obj->FuncName );
715                                                 DBW("WriteProcessMemory failed : %d",GetLastError());
716                                                 return false;
717                                         }
718                                 }
719                         }
720                         return true;  // We did it, get out
721                 }
722         }
723
724         //DBW("Not found");
725
726         // If we get to here, the function is not in the caller's import section
727         return false;
728 }
729 bool APIHOOK::HookAgain()
730 {
731         if ( Hooked ) return true;
732
733         // Set assembler code for hooking at the org entry
734         if ( !StoreCode() ){
735                 DBW("Cannot write process memory@rehook");
736                 return false;
737         }
738
739         Hooked = true;
740         return true;
741 }
742 void APIHOOK::Finish()
743 {
744         if ( !Hooked ) return;
745         RestoreCode();
746         Hooked = false;
747 }
748 // Returns the HMODULE that contains the specified memory address
749 static HMODULE ModuleFromAddress(PVOID pv)
750 {
751         MEMORY_BASIC_INFORMATION mbi;
752         return((VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) 
753                 ? (HMODULE) mbi.AllocationBase : NULL);
754 }
755
756 #if HOOK_PAINT || RETRYMETA
757 APIHOOK BeginPaintHook( STR_USER32, STR_BeginPaint, _BeginPaint );
758 APIHOOK EndPaintHook( STR_USER32, STR_EndPaint, _EndPaint );
759 #endif
760
761 #if HOOK_BITBLT
762 APIHOOK BitBltHook( STR_GDI32, STR_BitBlt, _BitBlt );
763 #endif
764
765 #if HOOK_GETDC
766 APIHOOK GetDCHook( STR_USER32, STR_GetDC, _GetDC );
767 APIHOOK ReleaseDCHook( STR_USER32, STR_ReleaseDC, _ReleaseDC );
768 #endif
769
770 #if METAEXTTEXTOUT
771 APIHOOK ExtTextOutAHook( STR_GDI32, STR_ExtTextOutA, _ExtTextOutA );
772 APIHOOK ExtTextOutWHook( STR_GDI32, STR_ExtTextOutW, _ExtTextOutW );
773 #if HOOK_TEXT
774 APIHOOK TabbedTextOutAHook( STR_USER32, STR_TabbedTextOutA, _TabbedTextOutA );
775 APIHOOK TabbedTextOutWHook( STR_USER32, STR_TabbedTextOutW, _TabbedTextOutW );
776 APIHOOK TextOutAHook( STR_GDI32, STR_TextOutA, _TextOutA );
777 APIHOOK TextOutWHook( STR_GDI32, STR_TextOutW, _TextOutW );
778 APIHOOK DrawTextAHook( STR_USER32, STR_DrawTextA, _DrawTextA );
779 APIHOOK DrawTextWHook( STR_USER32, STR_DrawTextW, _DrawTextW );
780 APIHOOK DrawTextExAHook( STR_USER32, STR_DrawTextExA, _DrawTextExA );
781 APIHOOK DrawTextExWHook( STR_USER32, STR_DrawTextExW, _DrawTextExW );
782 #endif
783 #endif  // METAEXTTEXTOUT
784
785 __declspec(dllexport)
786 bool WINAPI Init( HWND _hwnd, const char * /*module_name*/, bool windowsnt, const char *vxd_path )
787 {
788         DBW("Init:%08X %d", _hwnd, windowsnt);
789         hwndCallback = _hwnd;
790         if ( Initialized ){
791                 return true;
792         }
793 #if USE_VXD
794         WindowsNT = windowsnt;
795         if (vxd_path){
796 //              DBW("vxd_path=%s",vxd_path);
797                 lstrcpy( VxDpathName, "\\\\.\\" );
798                 lstrcat( VxDpathName, vxd_path );
799                 if (!LoadVxD()){
800                         DBW("Cannot open VxD:%s:%d", VxDpathName,GetLastError() );
801                         return false;
802                 }
803         }
804 #endif
805
806 //      HINSTANCE hDll = GetModuleHandle( module_name );
807         hMouseHook = SetWindowsHookEx( WH_MOUSE, (HOOKPROC)MouseProc, hInstance, NULL );
808         if (!hMouseHook){
809                 DBW("SetWindowsHookEx error: %d", GetLastError());
810                 return false;
811         }
812
813 //      hKeyHook = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)KeyboardProc, hDll, NULL );
814
815         Initialized = true;
816
817 #if GUARD
818         PROTECT_SHARE();
819         DBW("%08X(%08X) Protected", (((INT_PTR)&ExtTextOutAHook) / siPageSize) * siPageSize,&ExtTextOutAHook);
820 #endif
821
822         idDokopopProcess = GetCurrentProcessId();
823
824         // get AMODI infomation.
825         if (!tryAMODI){
826                 tryAMODI = true;
827                 hwndAMODI = FindAMODI();
828 #if 0
829                 if (hwndAMODI){
830                         DWORD procId;
831                         if (GetWindowThreadProcessId(hwnd, &procId)){
832                                 HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, procId);
833                                 if (hProc){
834                                         memset(AMODIPath, 0, sizeof(AMODIPath));
835                                         if (GetModuleFileNameEx(hProc, NULL, AMODIPath, sizeof(AMODIPath))>0){
836                                                 // OK
837                                         }
838                                         CloseHandle(hProc);
839                                 }
840                         }
841                 }
842 #endif
843         }
844
845         return true;
846 }
847
848 __declspec(dllexport)
849 void WINAPI Uninit()
850 {
851         UNPROTECT_SHARE();
852         if ( !Initialized ) return;
853
854         DBW("Uninit");
855         UnhookWindowsHookEx( hMouseHook );
856
857 //      UnhookWindowsHookEx( hKeyHook );
858
859 #if USE_VXD
860         UnloadVxD();
861 #endif
862
863         Initialized = false;
864 }
865 __declspec(dllexport)
866 int WINAPI Config( int clickonly, int keyaction, int keyflag )
867 {
868         DBW("Config:%d %d %d", clickonly, keyaction, keyflag);
869         if (clickonly!=-1)
870                 ClickOnlyEnabled = int_bool(clickonly);
871         if ( keyflag != 0 ){
872                 for ( int i=0;KeyConfig[i].Action;i++ ){
873                         if (KeyConfig[i].Action == keyaction){
874                                 KeyConfig[i].Flag = keyflag;
875                                 break;
876                         }
877                 }
878         }
879         return 0;
880 }
881 __declspec(dllexport)
882 int WINAPI Config2( const struct TDCHConfig *cfg )
883 {
884         DBW("Config2: %d %d %d %d %d", (int)cfg->ScaleX, (int)cfg->ScaleY, (int)cfg->UseAMODI, (int)ExtAMODI, cfg->UseNumPrev ? cfg->NumPrevWords : 1);
885
886         MoveSend = cfg->MoveSend ? true : false;
887         MoveSent = false;
888         OnlyImage = cfg->OnlyImage;
889         ScaleX = cfg->ScaleX;
890         ScaleY = cfg->ScaleY;
891         NumPrevWords = cfg->UseNumPrev ? cfg->NumPrevWords : 1;
892
893         if (cfg->UseAMODI){
894                 if (!ExtAMODI){
895                         if (!hwndAMODI)
896                                 hwndAMODI = FindAMODI();
897                 }
898         } else {
899                 hwndAMODI = NULL;
900                 ExtAMODI = false;
901                 return 0;
902         }
903
904         OnlyAMODI = int_bool(cfg->OnlyAMODI);
905         AMODIPath[0] = '\0';
906         ExtAMODI = false;
907         if (cfg->AMODIPath[0]){
908                 size_t len = strlen(cfg->AMODIPath);
909                 if (len<sizeof(AMODIPath)-2){
910                         memcpy(AMODIPath, cfg->AMODIPath, len);
911                         if (AMODIPath[len-1]!='\\'){
912                                 AMODIPath[len] = '\\';
913                                 len++;
914                         }
915                         AMODIPath[len] = '\0';
916                         ExtAMODI = true;
917                 }
918         }
919         dbw("Config2[%d]: %d %d %s", ++generation, cfg->ScaleX, cfg->ScaleY, AMODIPath);
920         return 0;
921 }
922 //Note:
923 //      non_block = true\82Ì\8fê\8d\87
924 //              \81Ewait\8fó\91Ô\82É\82 \82é\82©\82Ç\82¤\82©\82Í\81AWaitForCaptureResult( false, 0 ) < 0 \82Å\82í\82©\82é\81B
925 //              \81E\95K\82¸\8dÅ\8cã\82É\82ÍWaitForCaptureResult(1,...)\82ð\8cÄ\82Ñ\8fo\82·\82±\82Æ\81B
926 __declspec(dllexport)
927 int WINAPI Capture( HWND hwnd, POINT *ppt, bool movesend, bool non_block )
928 {
929         DBW("Capture:%08X %d,%d %d %d", hwnd, ppt ? ppt->x : 0, ppt ? ppt->y : 0, movesend, non_block);
930         if (!hwnd)
931                 hwnd = hwndLast;
932         POINT pt;
933         if (ppt)
934                 pt = *ppt;
935         else
936                 pt = PrevCursorPoint;
937         const bool image_only = true;
938         const bool runOnLaunchedProc = false;
939         return int_bool(DoCapture(hwnd, pt, movesend, image_only, runOnLaunchedProc, non_block));
940 }
941 //Note:
942 // waittime\82ÍCapture()\8aJ\8en\82µ\82Ä\82©\82ç\82Ì\8co\89ß\8e\9e\8aÔ
943 // polling\82·\82é\8fê\8d\87\82Íwaittime\82ð\8f­\82µ\82¸\82Â\91\9d\82â\82·\95K\97v\82 \82è(\82»\82Ì\8fê\8d\87\82Ísend_text=0)
944 // CaptureImage\82ð\8ds\82Á\82½\8fê\8d\87\82Í\81A\81u\95K\82¸\81vWaitForCaptureResult( 1, ... )\82ð\8cÄ\82Ñ\8fo\82·\95K\97v\82ª\82 \82é\81B
945 // \82»\82¤\82µ\82È\82¢\82Æ\81ACaptureImageBlocking\82ª true \82É\82È\82Á\82½\82Ü\82Ü\81B
946 //
947 // return:
948 //      0 : wait\92\86\82Ì\82à\82Ì\82Í\82È\82µ
949 //      1 : OK(text ready)
950 //      -1: timeout
951 __declspec(dllexport)
952 int WINAPI WaitForCaptureResult( bool send_text, unsigned waittime )
953 {
954         DBW("WaitForCaptureResult: %d %d %d", send_text, waittime, CaptureImageBlocking);
955         if (!CaptureImageBlocking) return 0;
956
957         if (send_text){
958                 if (WaitAndGetResult(ImageTextPath, waittime)){
959                         return 1;
960                 }
961         } else {
962                 HANDLE hf = WaitForResult(ImageTextPath, waittime);
963                 if (hf){
964                         CloseHandle(hf);
965                         return 1;
966                 }
967         }
968         return -1;
969 }
970 #if GUARD
971 void ShareProtect( bool f )
972 {
973         LPVOID BaseAddress = (LPVOID)((((INT_PTR)&ExtTextOutAHook) / siPageSize) * siPageSize);
974
975         DWORD OldProtect;
976         if ( !VirtualProtect( BaseAddress, siPageSize, f ? PAGE_READONLY : PAGE_READWRITE, &OldProtect ) ){
977                 DBW("Cannot change protect:%08X@rehook",BaseAddress);
978         }
979 }
980 #endif
981 DWORD SetWriteProtect( LPVOID addr, bool f )
982 {
983         LPVOID BaseAddress = (LPVOID)((((INT_PTR)addr) / siPageSize) * siPageSize);
984
985         DWORD OldProtect;
986         if ( !VirtualProtect( BaseAddress, siPageSize, f ? PAGE_READONLY : PAGE_READWRITE, &OldProtect ) ){
987                 DBW("Cannot change protect:%08X-%08X@rehook %d", (INT_PTR)BaseAddress>>32, BaseAddress, GetLastError());
988                 return ~0;
989         }
990         return OldProtect;
991 }
992 #if USE_VXD
993 // change write protected memory for Windows9x
994 bool ChangeMemory( void *dst, const void *src, unsigned size )
995 {
996         DWORD DIOC_count;
997         if ( vxd_Handle == INVALID_HANDLE_VALUE ){
998                 if (!LoadVxD())
999                         return false;
1000         }
1001
1002         bool r = int_bool(DeviceIoControl( vxd_Handle, DIOC_CHANGE_MEMORY, (void*)src, size, dst, 0, &DIOC_count, NULL));
1003 #if USE_DBW
1004         if ( !r ){
1005                 DBW("DeviceIoControl failed");
1006         }
1007 #endif
1008         return r;
1009 }
1010 bool LoadVxD()
1011 {
1012         if (vxd_Handle!=INVALID_HANDLE_VALUE){
1013                 DBW("Already loaded VxD");
1014                 return true;
1015         }
1016         vxd_Handle=CreateFile(&VxDpathName[0],0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
1017         return vxd_Handle != INVALID_HANDLE_VALUE;
1018 }
1019 void UnloadVxD()
1020 {
1021         if (vxd_Handle == INVALID_HANDLE_VALUE)
1022                 return;
1023         CloseHandle(vxd_Handle);
1024         vxd_Handle = INVALID_HANDLE_VALUE;
1025 }
1026 #endif
1027 int GetKeyFlag( )
1028 {
1029         int r = 0;
1030         if ( GetKeyState( VK_SHIFT ) & 0x8000 ) r |= KF_SHIFT;
1031         if ( GetKeyState( VK_CONTROL ) & 0x8000 ) r |= KF_CONTROL;
1032         if ( GetKeyState( VK_MENU ) & 0x8000 ) r |= KF_MENU;
1033         if ( GetKeyState( VK_LWIN ) & 0x8000 ) r |= KF_LWIN;
1034         if ( GetKeyState( VK_RWIN ) & 0x8000 ) r |= KF_RWIN;
1035         if ( ClickOnlyEnabled && r == 0 ) r = KF_CLICKONLY;
1036 //      if ( GetKeyState( VK_APPS ) & 0x8000 ) r |= KF_APPS;
1037         return r;
1038 }
1039 LRESULT CALLBACK MouseProc( int code, WPARAM wParam, LPARAM lParam )
1040 {
1041         if ( code < 0 || code != HC_ACTION )
1042                 return CallNextHookEx( hMouseHook, code, wParam, lParam );
1043
1044         MOUSEHOOKSTRUCT *mhs;
1045         HWND hwnd;
1046         int kf;
1047         int i;
1048
1049 #if 0
1050         if (wParam!=0x200 && wParam!=0xA0)
1051                 dbw("WParam:%08X", wParam);
1052 #endif
1053
1054         curProcess = GetCurrentProcessId();
1055         bool runOnLaunchedProc = false;
1056
1057         switch ( wParam ){
1058                 case WM_LBUTTONDOWN:
1059                 // case WM_NCLBUTTONDOWN:
1060                         LButtonDown = true;
1061                         LButtonUpCancel = false;
1062 //                      if (LButtonUpCancel)
1063 //                              goto j_end;
1064                         kf = KF_LEFTCLICK;
1065                         goto j_rbuttondown;
1066                 case WM_MBUTTONDOWN:
1067                 // case WM_NCMBUTTONDOWN:
1068                         MButtonDown = true;
1069                         MButtonUpCancel = false;
1070 //                      if (MButtonUpCancel)
1071 //                              goto j_end;
1072                         kf = KF_MIDCLICK;
1073                         goto j_rbuttondown;
1074                 case WM_RBUTTONDOWN:
1075                 //  case WM_NCRBUTTONDOWN:
1076                         DBW("RButtonDown");
1077                         RButtonUpCancel = false;
1078 //                      if (RButtonUpCancel)
1079 //                              goto j_end;
1080                         kf = 0;
1081                         if (LButtonDown){
1082                                 kf = KF_LRCLICK;
1083                         }
1084         j_rbuttondown:;
1085                         mhs = (MOUSEHOOKSTRUCT*)lParam;
1086                         hwnd = WindowFromPoint( mhs->pt );
1087                         //hwnd = mhs->hwnd;
1088 #if 0
1089                         HWND h = GetParent( hwnd );
1090                         if ( h )
1091                                 hwnd = h;
1092 #endif
1093                         kf |= GetKeyFlag();
1094
1095 #if 0
1096                         dbw("kf=%02X", kf);
1097 #endif
1098
1099                         if (curProcess == idDokopopProcess){
1100                                 // runs on launched process -> ignored.
1101                                 DBW("Runs on launched proc(%d)", curProcess);
1102                                 runOnLaunchedProc = true;
1103                         }
1104
1105                         for ( i=0;KeyConfig[i].Action;i++ ){
1106                                 //DBW("%d:%d %x", i, KeyConfig[i].Action, KeyConfig[i].Flag);
1107                                 if ( kf == KeyConfig[i].Flag ){
1108                                         switch ( KeyConfig[i].Action ){
1109                                                 case KA_POPUP:
1110                                                 case KA_POPUP_NC:
1111                                                         {
1112                                                         const bool move_send = false;
1113                                                         if (DoCapture(hwnd, mhs->pt, move_send, OnlyImage, runOnLaunchedProc)){
1114 j_discard:
1115                                                                 if (wParam == WM_LBUTTONDOWN)
1116                                                                         LButtonUpCancel = true;
1117                                                                 if (wParam == WM_MBUTTONDOWN)
1118                                                                         MButtonUpCancel = true;
1119                                                                 else
1120                                                                         RButtonUpCancel = true;
1121                                                                 return 1;       // discard this message
1122                                                         }
1123                                                         }
1124                                                         break;
1125                                                 case KA_MENU:
1126                                                         DokoPopMenu( hwnd );
1127                                                         goto j_discard;
1128                                                 case KA_TOGGLE:
1129                                                         DBW("KA_TOGGLE");
1130                                                         ToggleClick( hwnd );
1131                                                         goto j_discard;
1132                                         }
1133                                 }
1134                         }
1135                         break;
1136                 case WM_RBUTTONUP:
1137                         DBW("WM_RBUTTONUP:%d",RButtonUpCancel);
1138                         if ( RButtonUpCancel ){
1139                                 RButtonUpCancel = false;
1140                                 return 1;       // no longer process the message
1141                         }
1142                         break;
1143                 case WM_LBUTTONUP:
1144                         LButtonDown = false;
1145                         if ( LButtonUpCancel ){
1146                                 LButtonUpCancel = false;
1147                                 return 1;       // no longer process the message
1148                         }
1149                         break;
1150                 case WM_MBUTTONUP:
1151                         MButtonDown = false;
1152                         if ( MButtonUpCancel ){
1153                                 MButtonUpCancel = false;
1154                                 return 1;       // no longer process the message
1155                         }
1156                         break;
1157                 case WM_MOUSEMOVE:
1158                         if (MoveSend){
1159                                 mhs = (MOUSEHOOKSTRUCT*)lParam;
1160                                 hwnd = WindowFromPoint( mhs->pt );
1161                                 if (PrevCursorPoint.x!=mhs->pt.x || PrevCursorPoint.y!=mhs->pt.y){
1162                                         PrevMoveTime = GetTickCount();
1163                                         MoveSent = false;
1164                                         PrevCursorPoint = mhs->pt;
1165                                         hwndLast = hwnd;
1166                                         //DBW("Moving:%d %d", mhs->pt.x, mhs->pt.y);
1167                                         SendMoveMessage();
1168 #if 0
1169                                         //TODO: 5pixel\96¢\96\9e\82Å\82 \82ê\82ÎDoCapture\82·\82é
1170 #endif
1171                                 } else {
1172                                         if (!MoveSent){
1173 #if 0   // 2014.11.18 inc.srch\82Å\97\8e\82¿\82é\82Ì\82Å\82Æ\82è\82 \82¦\82¸comment out
1174                                                 const int MOVE_SEND_INTERVAL = 50;      // msec
1175                                                 if (GetTickCount()-PrevMoveTime > MOVE_SEND_INTERVAL){
1176                                                         MoveSent = true;
1177                                                         if (DoCapture(hwndLast, PrevCursorPoint, true)){
1178                                                                 // stop the capture from the main.
1179                                                                 SendCancelMove();
1180                                                         }
1181                                                 }
1182 #endif
1183                                         }
1184                                 }
1185                         }
1186                         break;
1187         }
1188
1189 //j_end:;
1190         return CallNextHookEx( hMouseHook, code, wParam, lParam );
1191 }
1192
1193 bool DoCapture(HWND hwnd, POINT pt, bool movesend, bool image_only, bool runOnLaunchedProc, bool non_block)
1194 {
1195         DBW("DoCapture: %d %d %d %d %d", image_only, runOnLaunchedProc, hwndAMODI, ExtAMODI, OnlyAMODI);
1196         CursorPoint = ScreenPoint = pt;
1197         ScreenToClient( hwnd, &CursorPoint );
1198
1199         if (!image_only && !runOnLaunchedProc){
1200                 //DBW("hwnd:%08X %d %d", (int)hwnd, CursorPoint.x, CursorPoint.y);
1201                 if ((!hwndAMODI && !ExtAMODI) || !OnlyAMODI){
1202                         // Redraw Metafile //
1203                         UNPROTECT_SHARE();
1204                         DBW("Target : %08X %d", hwnd, curProcess);
1205                         bool r = CaptureText( hwnd, movesend );
1206                         PROTECT_SHARE();
1207                         if (r){
1208                                 return true;    // discard this message
1209                         }
1210                 }
1211         }
1212         if (image_only || hwndAMODI || ExtAMODI){
1213                 if (CaptureImage(hwnd, movesend, non_block))
1214                         return true;
1215         }
1216         return false;
1217 }
1218
1219 void CallbackMain(int msg, const void *data, int len, HWND wparam=0)
1220 {
1221         COPYDATASTRUCT cds;
1222         cds.dwData = msg;
1223         cds.cbData = len;
1224         cds.lpData = (LPSTR)data;
1225         SendMessage( hwndCallback, WM_COPYDATA, (WPARAM)wparam, (LPARAM)&cds );
1226 }
1227
1228 void DokoPopMenu( HWND hwnd )
1229 {
1230         CallbackMain(DCH_MENU, NULL, 0, hwnd);
1231 }
1232 void ToggleClick( HWND hwnd )
1233 {
1234         CallbackMain(DCH_TOGGLE, NULL, 0, hwnd);
1235 }
1236 #if 0
1237 LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam )
1238 {
1239         if ( code < 0 || code != HC_ACTION )
1240                 return CallNextHookEx( hKeyHook, code, wParam, lParam );
1241
1242         if ( wParam == VK_CONTROL ){
1243                 if ( lParam & (KF_UP<<16) ){
1244                         // control key up
1245                         // -> hold on time
1246                         goto j1;
1247                 } else
1248                 if ( !(lParam & (KF_REPEAT<<16)) ){
1249                         // control key down and not repeat
1250 //                      DBW("wparam=%08X lparam=%08X",wParam,lParam);
1251                         long nowt = GetTickCount();
1252                         if ( nowt - LastTypeTime < GetDoubleClickTime() ){
1253 //                              DBW("On/off!");
1254                                 ClickOnlyEnabled = !ClickOnlyEnabled;
1255                                 MessageBeep( MB_OK );
1256                                 // -> cancel time
1257                         } else {
1258                                 // -> hold on time
1259                                 LastTypeTime = nowt;
1260                                 goto j1;
1261                         }
1262                 } else {
1263                         // control key down and repeat
1264                         // -> cancel time
1265                 }
1266         }
1267         LastTypeTime -= 10000;
1268 j1:;
1269         return CallNextHookEx( hMouseHook, code, wParam, lParam );
1270 }
1271 #endif
1272
1273 //__declspec(dllexport)
1274 #if HOOK_PAINT || RETRYMETA
1275 HDC WINAPI _BeginPaint( HWND hwnd, LPPAINTSTRUCT ps )
1276 {
1277 //      DBW("BeginPaint");
1278         HDC hdc = ((FNBeginPaint)BeginPaintHook.OrgFunc)( hwnd, ps );
1279         OrgHDC = hdc;
1280         ps->hdc = hdcMeta;
1281 #if 1
1282         ps->rcPaint.left = 0;
1283         ps->rcPaint.top = 0;
1284         ps->rcPaint.right = rcInvalid.right;
1285         ps->rcPaint.bottom = rcInvalid.bottom;
1286 #endif
1287         return hdcMeta;
1288 }
1289 //__declspec(dllexport)
1290 BOOL WINAPI _EndPaint( HWND hwnd, CONST PAINTSTRUCT *ps )
1291 {
1292         ((PAINTSTRUCT*)ps)->hdc = OrgHDC;
1293         return ((FNEndPaint)EndPaintHook.OrgFunc)( hwnd, ps );
1294 }
1295 #endif
1296 #if HOOK_GETDC
1297 HDC WINAPI _GetDC( HWND hwnd )
1298 {
1299         DBW("GetDC");
1300         HDC hdc = ((FNGetDC)GetDCHook.OrgFunc)( hwnd );
1301         OrgHDC = hdc;
1302         if ( hwnd == hwndOrg ){
1303                 return hdcMeta;
1304         } else {
1305                 return OrgHDC;
1306         }
1307 }
1308 int WINAPI _ReleaseDC( HWND hwnd, HDC hdc )
1309 {
1310         DBW("ReleaseDC");
1311         if ( hdc == hdcMeta ){
1312                 hdc = OrgHDC;
1313         }
1314         int r = ((FNReleaseDC)ReleaseDCHook.OrgFunc)( hwnd, hdc );
1315         return r;
1316 }
1317 #endif
1318
1319 #if METAEXTTEXTOUT
1320 //__declspec(dllexport)
1321 BOOL  WINAPI _ExtTextOutA(HDC hdc, int x, int y, UINT option, CONST RECT *rc, LPCSTR str, UINT count, CONST INT *dx )
1322 {
1323         DBW("_ExtTextOutA");
1324         POINT pt;
1325         GetCurrentPositionEx(hdc,&pt);
1326
1327         BOOL r = ((FNExtTextOutA)ExtTextOutAHook.OrgFunc)( hdc, x, y, option, rc, str, count, dx );
1328
1329         hdcExtTextOut = hdc;
1330
1331         if ( r
1332 #if USE_META
1333                 && hdcMeta != hdc
1334 #endif
1335                 && count > 0 ){
1336                 RECT _rc;
1337                 if ( rc ){
1338                         _rc.right = rc->right;
1339                         _rc.bottom = rc->bottom;
1340                 } else {
1341                         _rc.right = rcClient.right;
1342                         _rc.bottom = rcClient.bottom;
1343                 }
1344                 if ( GetTextAlign( hdc ) & TA_UPDATECP ){
1345                         _rc.left = pt.x;
1346                         _rc.top = pt.y;
1347                 } else {
1348                         _rc.left = x;
1349                         _rc.top = y;
1350                 }
1351                 if ( RetryPhase ){
1352                         if ( TargetBitBltCount == BitBltCount ){
1353                                 _rc.right += CursorPoint.x;     //*+++ bug \82±\82¤\82µ\82È\82¢\82Æ\95\9d\82ª\82¹\82Ü\82­\82Ähit\82µ\82È\82¢
1354                                 OffsetRect( &_rc, TargetOffset.x, TargetOffset.y );
1355                         } else {
1356                                 return r;
1357                         }
1358                 } else {
1359                         ExtTextOutCount++;
1360                 }
1361 #if ORG_OFFSET  /* fixed 2001.1.14 for IE@win2k */
1362                 POINT vpt;
1363                 POINT wpt;
1364                 GetViewportOrgEx( hdc, &vpt );
1365                 GetWindowOrgEx( hdc, &wpt );
1366                 OffsetRect( &_rc, vpt.x-wpt.x, vpt.y-wpt.y);
1367 #else
1368 #if USE_DBW
1369                 POINT vpt;
1370                 POINT wpt;
1371                 GetViewportOrgEx( hdc, &vpt );
1372                 GetWindowOrgEx( hdc, &wpt );
1373                 if (vpt.x != wpt.x || vpt.y != wpt.y)
1374                         DBW("!!!Org DIFF=%d %d",vpt.x-wpt.x, vpt.y-wpt.y);
1375 #endif
1376 #endif
1377
1378                 // \98A\91±\82µ\82½\83e\83L\83X\83g\82Ì\8fê\8d\87\82Í
1379                 // \98A\8c\8b\82·\82é
1380                 if (LastY == _rc.top && LastX == _rc.left ){
1381                         // \98A\91±\82µ\82½\83e\83L\83X\83g\95`\89æ\81¨\98A\8c\8b
1382                         LastTextA->Cat( str, count );
1383                 } else {
1384                         LastTextA->Set( str, count );
1385                 }
1386                 LastX = _rc.left;
1387                 LastY = _rc.top;
1388
1389                 if ( PtInRect( &_rc, CursorPoint ) )
1390                 {
1391 #if DEBUG_HITTEXT
1392                         char *buf = new char[ count + 1 ];
1393                         CopyMemory( buf, str, count );
1394                         buf[count] = '\0';
1395                         DBW("CheckA -- %d %d %d %d (%d,%d)", _rc.left, _rc.top, _rc.right, _rc.bottom, CursorPoint.x, CursorPoint.y, count);
1396                         DBW("%s", buf);
1397                         delete[] buf;
1398 #endif
1399                         int loc = GetTextFromPoint( hdc, str, count, CursorPoint.x - _rc.left, CursorPoint.y - _rc.top, dx );
1400                         if ( loc != -1 ){
1401                                 FoundLocA = loc + LastTextA->GetLength() - count;
1402                                 FoundTextA->Set( LastTextA );
1403 #if DEBUG_HITTEXT
1404                                 DBW("HitA loc=%d Len=%d Text=%ws", FoundLocA, FoundTextA->GetLength(), FoundTextA->c_str());
1405 #endif
1406                         }
1407                 }
1408         }
1409
1410         return r;
1411 }
1412 //__declspec(dllexport)
1413 BOOL  WINAPI _ExtTextOutW(HDC hdc, int x, int y, UINT option, CONST RECT *rc, LPCWSTR str, UINT count, CONST INT *dx )
1414 {
1415 //      DBW("_ExtTextOutW");
1416         POINT pt;
1417         GetCurrentPositionEx(hdc,&pt);
1418
1419         BOOL r = ((FNExtTextOutW)ExtTextOutWHook.OrgFunc)( hdc, x, y, option, rc, str, count, dx );
1420
1421         hdcExtTextOut = hdc;
1422
1423         if ( r
1424 #if USE_META
1425                 && hdcMeta != hdc
1426 #endif
1427                 && count > 0 ){
1428                 RECT _rc;
1429                 if ( rc ){
1430                         _rc.right = rc->right;
1431                         _rc.bottom = rc->bottom;
1432                 } else {
1433                         _rc.right = rcClient.right;
1434                         _rc.bottom = rcClient.bottom;
1435                 }
1436                 if ( GetTextAlign( hdc ) & TA_UPDATECP ){
1437                         _rc.left = pt.x;
1438                         _rc.top = pt.y;
1439                 } else {
1440                         _rc.left = x;
1441                         _rc.top = y;
1442                 }
1443                 if ( RetryPhase ){
1444                         if ( TargetBitBltCount == BitBltCount ){
1445                                 _rc.right += CursorPoint.x;     //*+++ bug \82±\82¤\82µ\82È\82¢\82Æ\95\9d\82ª\82¹\82Ü\82­\82Ähit\82µ\82È\82¢
1446                                 OffsetRect( &_rc, TargetOffset.x, TargetOffset.y );
1447                         } else {
1448                                 return r;
1449                         }
1450                 } else {
1451                         ExtTextOutCount++;
1452                 }
1453 #if ORG_OFFSET  /* fixed 2001.1.14 for IE@win2k */
1454                 POINT vpt;
1455                 POINT wpt;
1456                 GetViewportOrgEx( hdc, &vpt );
1457                 GetWindowOrgEx( hdc, &wpt );
1458                 OffsetRect( &_rc, vpt.x-wpt.x, vpt.y-wpt.y);
1459 #else   // !ORG_OFFSET
1460 #if USE_DBW
1461                 POINT vpt;
1462                 POINT wpt;
1463                 GetViewportOrgEx( hdc, &vpt );
1464                 GetWindowOrgEx( hdc, &wpt );
1465                 if (vpt.x != wpt.x || vpt.y != wpt.y)
1466                         DBW("!!!Org DIFF=%d %d",vpt.x-wpt.x, vpt.y-wpt.y);
1467 #endif  // USE_DBW
1468 #endif  // !ORG_OFFSET
1469
1470                 // \98A\91±\82µ\82½\83e\83L\83X\83g\82Ì\8fê\8d\87\82Í\98A\8c\8b\82·\82é
1471                 if (LastY == _rc.top && LastX == _rc.left ){
1472                         // \98A\91±\82µ\82½\83e\83L\83X\83g\95`\89æ\81¨\98A\8c\8b
1473                         LastTextW->Cat( str, count );
1474                 } else {
1475                         LastTextW->Set( str, count );
1476                 }
1477                 LastX = _rc.left;
1478                 LastY = _rc.top;
1479
1480                 if ( PtInRect( &_rc, CursorPoint ) )
1481                 {
1482                         DBW("%04X %04X %04X %04X",
1483                                 str[0],
1484                                 str[1],
1485                                 str[2],
1486                                 str[3]);
1487 #if DEBUG_HITTEXT
1488                         wchar_t *buf = new wchar_t[ count + 1 ];
1489                         CopyMemory( buf, str, count*sizeof(wchar_t) );
1490                         buf[count] = '\0';
1491                         DBW("CheckW -- %d %d %d %d (%d,%d)", _rc.left, _rc.top, _rc.right, _rc.bottom, CursorPoint.x, CursorPoint.y, count);
1492                         DBW("%ws", buf);
1493                         delete[] buf;
1494 #endif
1495                         int loc = GetTextFromPoint( hdc, str, count, CursorPoint.x - _rc.left, CursorPoint.y - _rc.top, dx );
1496                         if ( loc != -1 ){
1497                                 FoundLocW = loc + LastTextW->GetLength() - count;
1498                                 FoundTextW->Set( LastTextW );
1499 #if DEBUG_HITTEXT
1500                                 DBW("HitW loc=%d Len=%d Text=%ws", FoundLocW, FoundTextW->GetLength(), FoundTextW->c_str());
1501 #endif
1502                         }
1503                 }
1504         }
1505
1506         return r;
1507 }
1508 #endif  // !METAEXTTEXTOUT
1509
1510 #if HOOK_BITBLT
1511 BOOL WINAPI _BitBlt(HDC hdcdest, int xdest, int ydest, int width, int height, HDC hdcsrc, int xsrc, int ysrc, DWORD rop )
1512 {
1513         DBW("BitBlt:%08X %d %d %d %d <- %08X %d %d", hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc );
1514         BOOL r = ((FNBitBlt)BitBltHook.OrgFunc)(hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, rop );
1515 //      DBW("BitBlt:%08X %d %d %d %d <- %08X %d %d", hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc );
1516         if ( r && hdcExtTextOut == hdcsrc ){
1517                 if ( !RetryPhase ){
1518                         // \8d¡\89ñ\82ÌBitBlt\8e\9e\82ÉExtTextOut\82ª\82 \82Á\82½\82©\81H
1519                         if ( ExtTextOutCount > 0 ){
1520                                 // CursorPoint\82ª\8aÜ\82Ü\82ê\82é\82©\81H
1521                                 DBW("ExtTextOutCount=%d",ExtTextOutCount);
1522                                 if ( (xdest <= CursorPoint.x)
1523                                         && (xdest+width > CursorPoint.x)
1524                                         && (ydest <= CursorPoint.y)
1525                                         && (ydest+height > CursorPoint.y)
1526                                 ){
1527                                         TargetBitBltCount = BitBltCount;
1528                                         TargetOffset.x = xdest - xsrc;
1529                                         TargetOffset.y = ydest - ysrc;
1530                                         DBW("TargetOffset %d %d (%d,%d %dx%d)<-(%d,%d)",
1531                                                 TargetOffset.x, TargetOffset.y,xdest,ydest,width,height,xsrc,ysrc);
1532 #if USE_DBW
1533                                         {
1534                                         POINT vpt;
1535                                         POINT wpt;
1536                                         GetViewportOrgEx( hdcdest, &vpt );
1537                                         GetWindowOrgEx( hdcdest, &wpt );
1538                                         DBW("BitBlt OrgDIFF=%d %d",vpt.x-wpt.x, vpt.y-wpt.y);
1539                                         SIZE sz1;
1540                                         SIZE sz2;
1541                                         GetViewportExtEx( hdcdest, &sz1 );
1542                                         GetWindowExtEx( hdcdest, &sz2 );
1543                                         DBW("BitBlt Ext %d (%d,%d) (%d,%d)", GetMapMode(hdcdest), sz1.cx, sz1.cy, sz2.cx, sz2.cy );
1544 #if 1
1545                                         XFORM xform;
1546                                         GetWorldTransform( hdcdest, &xform );
1547                                         {
1548                                         char buf[100];
1549                                         sprintf(buf,"== [%d] %g %g %g %g %g %g", GetGraphicsMode(hdcdest), xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
1550                                         DBW(buf);
1551                                         }
1552 #endif
1553                                         }
1554 #endif
1555                                 }
1556 #if METAEXTTEXTOUT
1557                                 if ( TargetBitBltCount != -1 ){
1558                                         // \82·\82Å\82É\82Ù\82©\82Ìband\82Åhit\82µ\82Ä\82¢\82é\8fê\8d\87\81A
1559                                         // Cancel ExtTextOut
1560                                         FoundLocA = -1;
1561                                         FoundLocW = -1;
1562                                 }
1563 #endif
1564                         }
1565                 }
1566                 BitBltCount++;
1567                 DBW("BitBltCount=%d",BitBltCount);
1568                 ExtTextOutCount = 0;
1569                 return r;
1570         } else {
1571 //              DBW("Unknown destination BitBlt %08X(%d,%d %dx%d)<-%08X(%d,%d)",hdcdest,xdest,ydest,width,height,hdcsrc,xsrc,ysrc);
1572         }
1573         return r;
1574 }
1575 #endif
1576
1577 #if HOOK_TEXT
1578 #define HK1( name, ret_type, args ) \
1579         ret_type r = ((FN##name)name##Hook.OrgFunc) args; \
1580         return r
1581 LONG WINAPI _TabbedTextOutA( HDC hdc, int x, int y, LPCSTR str, int count, int ntabs, LPINT tabs, int origin )
1582 {
1583         DBW("_TabbedTextOutA");
1584         HK1( TabbedTextOutA, LONG, ( hdc, x, y, str, count, ntabs, tabs, origin ) );
1585 }
1586 LONG WINAPI _TabbedTextOutW( HDC hdc, int x, int y, LPCWSTR str, int count, int ntabs, LPINT tabs, int origin )
1587 {
1588         DBW("TabbedTextOutW");
1589         HK1( TabbedTextOutW, LONG, ( hdc, x, y, str, count, ntabs, tabs, origin ) );
1590 }
1591 BOOL WINAPI _TextOutA( HDC hdc, int x, int y, LPCSTR str, int count )
1592 {
1593         DBW("_TextOutA");
1594         HK1( TextOutA, BOOL, ( hdc, x, y, str, count ) );
1595 }
1596 BOOL WINAPI _TextOutW( HDC hdc, int x, int y, LPCWSTR str, int count )
1597 {
1598         DBW("_TextOutW");
1599         HK1( TextOutW, BOOL, ( hdc, x, y, str, count ) );
1600 }
1601 int WINAPI _DrawTextA( HDC hdc, LPCSTR str, int count, LPRECT rc, UINT format )
1602 {
1603         DBW("s5");
1604         HK1( DrawTextA, int, ( hdc, str, count, rc, format ) );
1605 }
1606 int WINAPI _DrawTextW( HDC hdc, LPCWSTR str, int count, LPRECT rc, UINT format )
1607 {
1608         DBW("s6");
1609         HK1( DrawTextW, int, ( hdc, str, count, rc, format ) );
1610 }
1611 int WINAPI _DrawTextExA( HDC hdc, LPCSTR str, int count, LPRECT rc, UINT format, LPDRAWTEXTPARAMS params )
1612 {
1613         DBW("s7");
1614         HK1( DrawTextExA, int, ( hdc, str, count, rc, format, params ) );
1615 }
1616 int WINAPI _DrawTextExW( HDC hdc, LPCWSTR str, int count, LPRECT rc, UINT format, LPDRAWTEXTPARAMS params )
1617 {
1618         DBW("s8");
1619         HK1( DrawTextExW, int, ( hdc, str, count, rc, format, params ) );
1620 }
1621 #endif  // HOOK_TEXT
1622
1623 bool CaptureText( HWND hwnd, bool movesend )
1624 {
1625         if ( !hwnd ){
1626                 return false;
1627         }
1628
1629         MoveSendMode = movesend;
1630
1631         //DoScale(NULL, &CursorPoint, 1);
1632
1633 #if METAEXTTEXTOUT
1634         FoundLocA = -1;
1635         FoundLocW = -1;
1636         FoundTextA = new TString<char>;
1637         FoundTextW = new TString<wchar_t>;
1638         LastTextA = new TString<char>;
1639         LastTextW = new TString<wchar_t>;
1640 #endif
1641
1642 #if !USE_REDRAW
1643         HRGN hRgn;
1644 #endif
1645
1646         GetClientRect( hwnd, &rcClient );
1647         GetUpdateRect( hwnd, &rcOrgInvalid, FALSE );
1648
1649 #if USE_OPTIMALINVALID
1650         SetRect( &rcInvalid, 0, max(CursorPoint.y - 64,0), rcClient.right, max(CursorPoint.y + 64,0) );
1651 #else
1652         rcInvalid = rcClient;
1653 #endif
1654
1655 #if !USE_REDRAW
1656         hRgn = CreateRectRgn( rcInvalid.left, rcInvalid.top, rcInvalid.right, rcInvalid.bottom );
1657
1658 #if USE_INVALIDATE
1659         InvalidateRect( hwnd, &rcInvalid, INVALIDATE_TRUE );
1660 #endif
1661
1662         SendMessage( hwnd, WM_PAINT, 0, 0 );
1663         SendMessage( hwnd, WM_NCPAINT, (WPARAM)hRgn, 0 );
1664 #endif
1665
1666         hwndOrg = hwnd;
1667
1668 #if USE_META
1669         HDC hdc;
1670 #endif
1671
1672         HINSTANCE hPSAPI = NULL;
1673         HMODULE hInst;
1674         HMODULE hInstGdi;
1675
1676         hInst = GetModuleHandleA( STR_KERNEL32 );
1677         fnCreateToolhelp32Snapshot = (FNCreateToolhelp32Snapshot)GetProcAddress( hInst, STR_CreateToolhelp32Snapshot );
1678         if (fnCreateToolhelp32Snapshot){
1679                 // Toolhelp\82É\82æ\82émodule enumration\82ª\8eg\97p\89Â\94\
1680                 fnModule32First = (FNModule32First)GetProcAddress( hInst, STR_Module32First );
1681                 fnModule32Next = (FNModule32Next)GetProcAddress( hInst, STR_Module32Next );
1682         } else {
1683                 // Toolhelp\82ª\91\8dÝ\82µ\82È\82¢\8fê\8d\87
1684                 hPSAPI = LoadLibrary( STR_PSAPI );
1685                 DBW("LoadLibrary : %08X",hPSAPI);
1686                 if (!hPSAPI){
1687                         DBW("Cannot load PSAPI.DLL!!");
1688                         return false;
1689                 }
1690                 fnEnumProcessModules = (FNEnumProcessModules)GetProcAddress( hPSAPI, STR_EnumProcessModules );
1691                 fnGetModuleFileNameExA = (FNGetModuleFileNameExA)GetProcAddress( hPSAPI, STR_GetModuleFileNameExA );
1692         }
1693
1694         hInst = GetModuleHandleA( STR_USER32 );
1695 #if USE_DBW
1696         if ( !hInst ){
1697                 DBW("Cannot load USER32.DLL");
1698                 return false;
1699         }
1700 #endif
1701         hInstGdi = GetModuleHandleA( STR_GDI32 );
1702 #if USE_DBW
1703         if ( !hInstGdi ){
1704                 DBW("Cannot load GDI32.DLL");
1705                 goto err9;
1706         }
1707 #endif
1708
1709 #if METAEXTTEXTOUT
1710         if ( !ExtTextOutAHook.GetProcOrgFunc( hInstGdi ) ){
1711                 DBW("Cannot find ExtTextOutA");
1712                 goto err8;
1713         }
1714         if ( !ExtTextOutWHook.GetProcOrgFunc( hInstGdi ) ){
1715                 DBW("Cannot find ExtTextOutW");
1716                 goto err7;
1717         }
1718 #endif
1719
1720 #if HOOK_BITBLT
1721         if ( !BitBltHook.GetProcOrgFunc( hInstGdi ) ){
1722                 DBW("Cannot find BitBlt");
1723                 goto err71;
1724         }
1725 #endif
1726         RetryPhase = false;
1727         TargetBitBltCount = -1;
1728         BitBltCount = 0;
1729         ExtTextOutCount = 0;
1730
1731 #if HOOK_PAINT
1732         if ( !BeginPaintHook.GetProcOrgFunc( hInst ) ){
1733                 DBW("Cannot hook BeginPaint");
1734                 goto err73;
1735         }
1736         if ( !EndPaintHook.GetProcOrgFunc( hInst ) ){
1737                 DBW("Cannot hook EndPaint");
1738                 goto err6;
1739         }
1740 #endif
1741
1742 #if HOOK_TEXT
1743         TabbedTextOutAHook.GetProcOrgFunc( hInst );
1744         TabbedTextOutWHook.GetProcOrgFunc( hInst );
1745         TextOutAHook.GetProcOrgFunc( hInstGdi );
1746         TextOutWHook.GetProcOrgFunc( hInstGdi );
1747         DrawTextAHook.GetProcOrgFunc( hInst );
1748         DrawTextWHook.GetProcOrgFunc( hInst );
1749         DrawTextExAHook.GetProcOrgFunc( hInst );
1750         DrawTextExWHook.GetProcOrgFunc( hInst );
1751 #endif
1752
1753 #if USE_META
1754         hdc = GetDC( hwnd );
1755         if ( !hdc ){
1756                 DBW("Cannot get DC");
1757                 goto err5;
1758         }
1759 #endif
1760
1761 #if HOOK_GETDC
1762         if ( !GetDCHook.GetProcOrgFunc( hInst ) ){
1763                 DBW("Cannot hook GetDC");
1764                 goto err4;
1765         }
1766         if ( !ReleaseDCHook.GetProcOrgFunc( hInst ) ){
1767                 DBW("Cannot hook ReleaseDC");
1768                 goto err3;
1769         }
1770 #endif
1771
1772         {
1773         DBW("Hooked successfully");
1774 //              rect.right = 9999;
1775 //              rect.bottom = 9999;
1776 #if 0
1777                 int iWidthMM = GetDeviceCaps(hdc, HORZSIZE);
1778                 int iHeightMM = GetDeviceCaps(hdc, VERTSIZE);
1779                 int iWidthPels = GetDeviceCaps(hdc, HORZRES);
1780                 int iHeightPels = GetDeviceCaps(hdc, VERTRES);
1781
1782                 // Use iWidthMM, iWidthPels, iHeightMM, and iHeightPels to determine the
1783                 // number of .01-millimeter units per pixel in the x and y directions.
1784
1785                 int iMMPerPelX = (iWidthMM * 100)/iWidthPels;
1786                 int iMMPerPelY = (iHeightMM * 100)/iHeightPels;
1787                 DBW("-%d %d-",iMMPerPelX, iMMPerPelY);
1788
1789                 // Convert client coordinates to .01-mm units.
1790
1791                 rcClient.left = rcClient.left * iMMPerPelX;
1792                 rcClient.top = rcClient.top * iMMPerPelY;
1793                 rcClient.right = rcClient.right * iMMPerPelX;
1794                 rcClient.bottom = rcClient.bottom * iMMPerPelY;
1795 #endif
1796
1797 #if USE_META
1798                 hdcMeta = CreateEnhMetaFile(hdc,
1799                                   NULL,
1800                                   &rcClient, "DCHook\0EnhMetaFile\0");
1801                 if ( !hdcMeta ){
1802                         DBW("Cannot create Meta file");
1803                         goto err3;
1804                 }
1805
1806                 DBW("hdcMeta=%08X", hdcMeta);
1807 #endif
1808
1809 #if USE_REDRAW
1810                 RedrawWindow( hwnd, &rcInvalid, NULL, RDW_UPDATENOW | RDW_NOERASE | RDW_NOFRAME | RDW_INVALIDATE );
1811 #else
1812                 WNDPROC PaintWndProc = (WNDPROC)GetWindowLong( hwnd, GWL_WNDPROC );
1813                 SendMessage( hwnd, WM_PAINT, (WPARAM)hdcMeta, 0 );
1814 #endif
1815 #if HOOK_GETDC
1816                 ReleaseDCHook.Finish();
1817                 GetDCHook.Finish();
1818 #endif
1819
1820 #if HOOK_TEXT
1821                 TabbedTextOutAHook.Finish( );
1822                 TabbedTextOutWHook.Finish( );
1823                 TextOutAHook.Finish( );
1824                 TextOutWHook.Finish( );
1825                 DrawTextAHook.Finish( );
1826                 DrawTextWHook.Finish( );
1827                 DrawTextExAHook.Finish( );
1828                 DrawTextExWHook.Finish( );
1829 #endif
1830
1831 #if HOOK_PAINT
1832                 EndPaintHook.Finish();
1833                 BeginPaintHook.Finish();
1834 #endif
1835
1836 #if HOOK_BITBLT
1837                 BitBltHook.Finish();
1838 #endif
1839
1840 #if METAEXTTEXTOUT
1841                 ExtTextOutAHook.Finish();
1842                 ExtTextOutWHook.Finish();
1843 #endif
1844
1845                 // Notify start enumrate meta-file
1846                 CallbackMain(DCH_START, &CursorPoint, sizeof(CursorPoint), hwnd);
1847
1848                 HitFound = false;
1849
1850 #if USE_META
1851                 HENHMETAFILE emf = CloseEnhMetaFile( hdcMeta );
1852
1853                 if ( emf )
1854 #endif
1855                 {
1856 #if METAEXTTEXTOUT
1857                         if ( FoundLocA != -1 || FoundLocW != -1 ){
1858 //                              DBW("Hit ExtText:%d %d",FoundLocA,FoundLocW);
1859                                 // ExtTextOutx hook\82Ì\82Ù\82¤\82ð\97D\90æ\82·\82é
1860                                 ExtTextOutHit( );
1861                                 HitFound = true;
1862                         } else
1863 #endif
1864                         {
1865 #if USE_META
1866                                 // Create compatible device-context for enumration
1867                                 HDC _hdc = CreateCompatibleDC( hdc );
1868                                 HBITMAP hbitmap = CreateCompatibleBitmap( hdc, rcClient.right, rcClient.bottom );
1869                                 HGDIOBJ gdiobj = SelectObject( _hdc, hbitmap );
1870
1871                                 DBW("Start meta");
1872                                 // Enumerate meta-file
1873                                 EnumEnhMetaFile( _hdc, emf, EnumMetaFileProc, NULL, &rcClient );
1874                                 DBW("End meta");
1875
1876                                 // Delete compatible device-context
1877                                 SelectObject( _hdc, gdiobj );
1878                                 DeleteObject( hbitmap );
1879                                 DeleteDC( _hdc );
1880 #endif
1881                         }
1882 #if USE_META
1883                         DeleteEnhMetaFile( emf );
1884 #endif
1885                 }
1886 #if USE_META
1887                 else {
1888                         DBW("emf is NULL");
1889                 }
1890 #endif
1891
1892 #if METAEXTTEXTOUT
1893                 if ( !HitFound && TargetBitBltCount != -1 ){
1894                         DBW("Search from band:%d",TargetBitBltCount);
1895 #if USE_META
1896                         // Band\82©\82ç\8c\9f\8dõ
1897                         hdcMeta = CreateCompatibleDC( hdc );
1898                         if ( !hdcMeta ){
1899                                 DBW("Cannot create HDC in retry");
1900                         } else
1901 #endif
1902                         {
1903 #if USE_META
1904                                 HBITMAP hbitmap = CreateCompatibleBitmap( hdc, rcClient.right, rcClient.bottom );
1905                                 HGDIOBJ gdiobj = SelectObject( hdcMeta, hbitmap );
1906                                 DBW("hdcMeata=%08X", hdcMeta);
1907 #endif
1908
1909                                 BitBltCount = 0;
1910                                 RetryPhase = true;
1911 #if METAEXTTEXOUT
1912                                 FoundLocA = -1;
1913                                 FoundLocW = -1;
1914 #endif
1915
1916 #if METAEXTTEXTOUT
1917                                 ExtTextOutAHook.HookAgain();
1918                                 ExtTextOutWHook.HookAgain();
1919 #endif
1920 #if HOOK_BITBLT
1921                                 BitBltHook.HookAgain();
1922 #endif
1923 #if HOOK_PAINT
1924                                 BeginPaintHook.HookAgain();
1925                                 EndPaintHook.HookAgain();
1926 #endif
1927
1928 //                              DBW("t1:%d %d %d %d",rcClient.left, rcClient.top,rcClient.right,rcClient.bottom);
1929
1930 #if USE_INVALIDATE
1931                                 InvalidateRect( hwnd, &rcInvalid, INVALIDATE_TRUE );
1932 #endif
1933
1934 #if USE_REDRAW
1935                                 RedrawWindow( hwnd, &rcInvalid, NULL, RDW_UPDATENOW | RDW_NOERASE | RDW_NOFRAME | RDW_INVALIDATE );
1936 #else
1937                                 CallWindowProc( (WNDPROC)PaintWndProc, hwnd, WM_PAINT, (WPARAM)hdcMeta, 0 );
1938 #endif
1939
1940 #if HOOK_PAINT
1941                                 EndPaintHook.Finish();
1942                                 BeginPaintHook.Finish();
1943 #endif
1944 #if HOOK_BITBLT
1945                                 BitBltHook.Finish();
1946 #endif
1947
1948 #if METAEXTTEXTOUT
1949                                 ExtTextOutAHook.Finish();
1950                                 ExtTextOutWHook.Finish();
1951 #endif
1952 #if USE_META
1953                                 SelectObject( hdcMeta, gdiobj );
1954                                 DeleteObject( hbitmap );
1955                                 DeleteDC( hdcMeta );
1956 #endif
1957                                 if ( FoundLocA != -1 || FoundLocW != -1 ){
1958                                         DBW("Found in BitBlt ExtText:%d %d",FoundLocA,FoundLocW);
1959                                         ExtTextOutHit( );
1960                                         HitFound = true;
1961                                 }
1962                         }
1963                 }
1964 #endif  // METAEXTTEXTOUT
1965
1966 #if RETRYMETA
1967                 if ( !HitFound ){
1968                         HENHMETAFILE emf;
1969 #if !USE_META
1970                         HDC hdc = GetDC( hwnd );
1971                         if ( !hdc ){
1972                                 DBW("Cannot get DC");
1973                                 goto err01;
1974                         }
1975 #endif
1976 #if HOOK_PAINT
1977                         if ( !BeginPaintHook.HookAgain( ) ){
1978                                 DBW("Cannot hook BeginPaint");
1979                                 goto err02;
1980                         }
1981                         if ( !EndPaintHook.HookAgain( ) ){
1982                                 DBW("Cannot hook EndPaint");
1983                                 goto err03;
1984                         }
1985 #else
1986                         if ( !BeginPaintHook.GetProcOrgFunc( hInst ) ){
1987                                 DBW("Cannot hook BeginPaint");
1988                                 goto err02;
1989                         }
1990                         if ( !EndPaintHook.GetProcOrgFunc( hInst ) ){
1991                                 DBW("Cannot hook EndPaint");
1992                                 goto err03;
1993                         }
1994 #endif
1995
1996                         hdcMeta = CreateEnhMetaFile(hdc,
1997                                           NULL,
1998                                           &rcClient, _T("DCHook\0EnhMetaFile\0"));
1999                         if ( !hdcMeta ){
2000                                 DBW("Cannot create Meta file");
2001                                 goto err04;
2002                         }
2003                         DBW("hdcMeta=%08X", hdcMeta);
2004 //                      InvalidateRect( hwnd, &rcInvalid, INVALIDATE_TRUE );
2005 #if 1           // 2000.7.15 NT\82Å\82à\82È\82º\82±\82Á\82¿\82É\82µ\82Ä\82¢\82È\82©\82Á\82½\82Ì\82©\82í\82©\82ç\82È\82¢\82ª\81E\81E\81E
2006                         SendMessage( hwnd, WM_PAINT, (WPARAM)hdcMeta, 0 );
2007 #else
2008                         // Notepad\82Å\82Í\88Ù\8fí\8fI\97¹\82·\82é\82½\82ß\8bp\89º
2009                         // \89½\82à\82È\82¢\82Æ\82±\82ë\82ÅCtrl+\89E\83N\83\8a\83b\83N
2010                         WNDPROC PaintWndProc = (WNDPROC)GetWindowLong( hwnd, GWL_WNDPROC );
2011                         if ( PaintWndProc ){
2012                                 PaintWndProc( hwnd, WM_PAINT, (WPARAM)hdcMeta, 0 );
2013                         }
2014 #endif
2015                         EndPaintHook.Finish();
2016                         BeginPaintHook.Finish();
2017
2018                         emf = CloseEnhMetaFile( hdcMeta );
2019
2020                         if ( emf ){
2021                                 HDC _hdc = CreateCompatibleDC( hdc );
2022                                 HBITMAP hbitmap = CreateCompatibleBitmap( hdc, rcClient.right, rcClient.bottom );
2023                                 HGDIOBJ gdiobj = SelectObject( _hdc, hbitmap );
2024
2025                                 DBW("Start meta-retry");
2026                                 // Enumerate meta-file
2027                                 EnumEnhMetaFile( _hdc, emf, EnumMetaFileProc, NULL, &rcClient );
2028                                 DBW("End meta-retry");
2029
2030                                 // Delete compatible device-context
2031                                 SelectObject( _hdc, gdiobj );
2032                                 DeleteObject( hbitmap );
2033                                 DeleteDC( _hdc );
2034                                 DeleteEnhMetaFile( emf );
2035                         }
2036                 err04:
2037                         EndPaintHook.Finish();
2038                 err03:
2039                         BeginPaintHook.Finish();
2040                 err02:
2041 #if !USE_META
2042                         ReleaseDC( hwnd, hdc );
2043 #endif
2044                 err01:;
2045                 }
2046 #endif
2047                 
2048                 // Notify end enumrate meta-file
2049                 CallbackMain(DCH_END | (MoveSendMode ? DCH_MOVESEND : 0), NULL, 0, hwnd);
2050         }
2051
2052 #if USE_META
2053         ReleaseDC( hwnd, hdc );
2054 #endif
2055
2056         if ( rcOrgInvalid.right != 0 ){
2057                 DBW("Update OrgInvalid--------");
2058                 InvalidateRect( hwnd, NULL, INVALIDATE_TRUE );
2059         }
2060
2061         goto jreturn;
2062
2063 #if HOOK_GETDC || USE_META
2064 err3:;
2065 #endif
2066 #if HOOK_GETDC
2067         GetDCHook.Finish();
2068 err4:;
2069 #if USE_META
2070         ReleaseDC( hwnd, hdc );
2071 #endif
2072 #endif
2073 #if USE_META
2074 err5:;
2075 #endif
2076 #if HOOK_PAINT
2077         EndPaintHook.Finish();
2078 err6:;
2079         BeginPaintHook.Finish();
2080 err73:;
2081 #endif
2082 #if HOOK_BITBLT
2083         BitBltHook.Finish();
2084 #endif
2085 #if HOOK_BITBLT
2086 err71:;
2087 #endif
2088 #if METAEXTTEXTOUT
2089         ExtTextOutWHook.Finish();
2090 err7:;
2091         ExtTextOutAHook.Finish();
2092 err8:
2093 #endif
2094         if (hPSAPI)
2095                 FreeLibrary( hPSAPI );
2096 #if USE_DBW
2097 err9:
2098 #endif
2099         HitFound = false;
2100 jreturn:;
2101 #if USE_VXD
2102         if (vxd_Handle!=INVALID_HANDLE_VALUE)
2103                 UnloadVxD();
2104 #endif
2105 #if METAEXTTEXTOUT
2106         delete FoundTextA;
2107         delete FoundTextW;
2108         delete LastTextA;
2109         delete LastTextW;
2110 #endif
2111
2112         return HitFound;
2113 }
2114 #if METAEXTTEXTOUT
2115 void ExtTextOutHit()
2116 {
2117         if ( FoundLocA != -1 ){
2118                 // Hit on ANSI
2119                 DBW("Hit on ANSI@ExtTextOut");
2120                 CallbackMain(DCH_HITTEXT1, FoundTextA->c_str(), FoundTextA->GetByte(), (HWND)FoundLocA);
2121         } else {
2122                 // Hit on UNICODE
2123                 DBW("Hit on UNICODE@ExtTextOut");
2124                 CallbackMain(DCH_HITTEXT2, FoundTextW->c_str(), FoundTextW->GetByte(), (HWND)FoundLocW);
2125         }
2126 }
2127 #endif  // METAEXTTEXTOUT
2128
2129 void DoScale(HDC hdc, POINT *pts, int num)
2130 {
2131         //TODO: hInst, proc\82Íglobal\82É\82µ\82½\82Ù\82¤\82ª\82¢\82¢\82Ì\82Å\82Í\81H
2132
2133         int scale = 0;
2134         if (ScaleX && ScaleY){
2135                 scale = ScaleX; // \8ew\92è\82µ\82½scaling parameter
2136         } else {
2137                 scale = GetMonitorScale();
2138                 if (scale == 96) return;
2139         }
2140
2141 #if 1
2142 #if 1
2143         PROCESS_DPI_AWARENESS value = Process_DPI_Unaware;
2144         if (hInstSHCore){
2145                 if (!GetProcessDPIAwareness){
2146                         GetProcessDPIAwareness = (FNGetProcessDPIAwareness)GetProcAddress(hInstSHCore, "GetProcessDpiAwareness");
2147                 }
2148                 if (GetProcessDPIAwareness){
2149                         GetProcessDPIAwareness(hProcess, &value);
2150                         DBW("DPIAware: value=%d", value);
2151                 }
2152         }
2153         if (value != Process_System_DPI_Aware){
2154                 int dpi_x = scale;
2155                 int dpi_y = scale;
2156                 DBW("dpi: %d,%d", dpi_x, dpi_y);
2157                 for (int i=0;i<num;i++){
2158                         pts[i].x = MulDiv(pts[i].x, dpi_x, 96);
2159                         pts[i].y = MulDiv(pts[i].y, dpi_y, 96);
2160                 }
2161         }
2162 #else
2163         HINSTANCE hInst = NULL;
2164         FNGetProcessDPIAwareness GetProcessDPIAwareness = NULL;
2165         //FNSetProcessDPIAwareness SetProcessDPIAwareness = NULL;
2166         //if (!GetProcessDPIAwareness)
2167         {
2168                 hInst = LoadLibrary("shcore.dll");
2169                 if (hInst){
2170                         GetProcessDPIAwareness = (FNGetProcessDPIAwareness)GetProcAddress(hInst, "GetProcessDpiAwareness");
2171                         //SetProcessDPIAwareness = (FNSetProcessDPIAwareness)GetProcAddress(hInst, "SetProcessDpiAwareness");
2172                         //DBW("DPI API:%08X %08X", GetProcessDPIAwareness, SetProcessDPIAwareness);
2173                         DBW("DPI API:%08X", GetProcessDPIAwareness);
2174                 }
2175         }
2176         if (GetProcessDPIAwareness || (ScaleX && ScaleY)){
2177                 int dpi_x, dpi_y;
2178                 PROCESS_DPI_AWARENESS value;
2179                 if (GetProcessDPIAwareness && hdc){
2180                         HRESULT hRes = GetProcessDPIAwareness(hProcess, &value);
2181                         DBW("DPIAware: value=%d", value);
2182                         //SetProcessDPIAwareness(Process_System_DPI_Aware);
2183                         dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
2184                         dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
2185                         DBW("dpi: %d, %d", dpi_x, dpi_y);
2186                 } else {
2187                         dpi_x = ScaleX;
2188                         dpi_y = ScaleY;
2189                 }
2190                 for (int i=0;i<num;i++){
2191                         pts[i].x = MulDiv(pts[i].x, dpi_x, 96);
2192                         pts[i].y = MulDiv(pts[i].y, dpi_y, 96);
2193                 }
2194 #if 0
2195                 if (SetProcessDPIAwareness){
2196                         SetProcessDPIAwareness(value);
2197                 }
2198 #endif
2199         }
2200         if (hInst){
2201                 FreeLibrary(hInst);
2202         }
2203 #endif
2204 #else   // \8b\8c\83R\81[\83h
2205         HINSTANCE hInst = NULL;
2206         if (!GetProcessDPIAwareness){
2207                 hInst = LoadLibrary("shcore.dll");
2208                 DBW("shcore=%08X", hInst);
2209                 if (hInst){
2210                         GetProcessDPIAwareness = (FNGetProcessDPIAwareness)GetProcAddress(hInst, "GetProcessDPIAwareness");
2211                         SetProcessDPIAwareness = (FNSetProcessDPIAwareness)GetProcAddress(hInst, "SetProcessDPIAwareness");
2212                         DBW("DPI API:%08X %08X", GetProcessDPIAwareness, SetProcessDPIAwareness);
2213                 }
2214         }
2215         if (GetProcessDPIAwareness || (ScaleX && ScaleY)){
2216                 int dpi_x, dpi_y;
2217                 PROCESS_DPI_AWARENESS value;
2218                 if (GetProcessDPIAwareness && hdc){
2219                         HRESULT hRes = GetProcessDPIAwareness(hProcess, &value);
2220                         SetProcessDPIAwareness(Process_System_DPI_Aware);
2221                         dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
2222                         dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
2223                 } else {
2224                         dpi_x = ScaleX;
2225                         dpi_y = ScaleY;
2226                 }
2227                 for (int i=0;i<num;i++){
2228                         pts[i].x = MulDiv(pts[i].x, dpi_x, 96);
2229                         pts[i].y = MulDiv(pts[i].y, dpi_y, 96);
2230                 }
2231                 if (SetProcessDPIAwareness){
2232                         SetProcessDPIAwareness(value);
2233                 }
2234                 if (hInst){
2235                         FreeLibrary(hInst);
2236                 }
2237         }
2238 #endif
2239 }
2240
2241 int CALLBACK EnumMetaFileProc( HDC hdc, HANDLETABLE *ht, CONST ENHMETARECORD *mfr, int nobj, LPARAM /* user */ )
2242 {
2243         PlayEnhMetaFileRecord( hdc, ht, mfr, nobj );
2244
2245         //DBW("iType=%d",mfr->iType);
2246
2247         switch ( mfr->iType ){
2248                 case EMR_EXTTEXTOUTA:
2249                 case EMR_EXTTEXTOUTW:
2250                 {
2251                         EMREXTTEXTOUTW *emr = (EMREXTTEXTOUTW*)mfr;
2252
2253                         //DBW("(%d,%d) <%d=%d=%d=%d>", CursorPoint.x, CursorPoint.y, emr->rclBounds.left, emr->rclBounds.top,emr->rclBounds.right, emr->rclBounds.bottom);
2254 #if 1
2255                         if ( PtInRect( (RECT*)&emr->rclBounds, CursorPoint ) ){
2256                                 DBW("(%d,%d) <%d=%d>", CursorPoint.x, CursorPoint.y, emr->rclBounds.left, emr->emrtext.ptlReference.x);
2257 #if 0
2258                                 {
2259                                 SIZE sz1, sz2;
2260                                 GetWindowExtEx( hdc, &sz1 );
2261                                 GetViewportExtEx( hdc, &sz2 );
2262                                 DBW("%d-%d %d-%d", sz1.cx, sz1.cy, sz2.cx, sz2.cy);
2263                                 }
2264 #endif
2265                                 int loc;
2266                                 if ( mfr->iType == EMR_EXTTEXTOUTW ){
2267                                         //DBW("offString=%d nChars=%d left=%d top=%d offDx=%d", emr->emrtext.offString, emr->emrtext.nChars, emr->rclBounds.left, emr->rclBounds.top, emr->emrtext.offDx);
2268                                         //DBW("text=%ws", (wchar_t*) ( ((char*)emr) + emr->emrtext.offString ));
2269                                         loc = GetTextFromPoint( hdc, (wchar_t*) ( ((char*)emr) + emr->emrtext.offString ),
2270                                                 emr->emrtext.nChars,
2271                                                 CursorPoint.x - emr->rclBounds.left /* + emr->emrtext.ptlReference.x */,
2272                                                 CursorPoint.y - emr->rclBounds.top  /* + emr->emrtext.ptlReference.y */,
2273                                                 ((int*)(((char*)emr) + emr->emrtext.offDx)) );
2274                                 } else {
2275                                         loc = GetTextFromPoint( hdc, ((char*)emr) + emr->emrtext.offString,
2276                                                 emr->emrtext.nChars,
2277                                                 CursorPoint.x - emr->rclBounds.left /* + emr->emrtext.ptlReference.x */,
2278                                                 CursorPoint.y - emr->rclBounds.top  /* + emr->emrtext.ptlReference.y */,
2279                                                 ((int*)(((char*)emr) + emr->emrtext.offDx)) );
2280                                 }
2281                                 if ( loc != -1 ){
2282 //                                      char *buf = NULL;
2283                                         const char *text = ((char*)emr) + emr->emrtext.offString;
2284                                         int len = emr->emrtext.nChars;
2285                                         if ( mfr->iType == EMR_EXTTEXTOUTW ){
2286                                                 // WIDE
2287                                                 //DBW("len=%d loc=%d text=%ws", len, loc, text);
2288                                                 CallbackMain(DCH_HITTEXT2, text, len * sizeof(wchar_t), (HWND)loc);
2289 #if 0
2290                                                 // UNICODE->ANSI
2291                                                 // ANSI\8fã\82Å\82Ìloc\82ð\8b\81\82ß\82é\82½\82ß\81A\91O\94¼\82Æ\8cã\94¼\82ð\95ª\82¯\82Ä\95Ï\8a·
2292                                                 wchar_t *wp = (wchar_t*) ( ((char*)emr) + emr->emrtext.offString );
2293                                                 buf = new char[ emr->emrtext.nChars * 2 ];
2294                                                 memset( buf, 0, emr->emrtext.nChars*2 );
2295                                                 // \91O\94¼\95\94\95ª
2296                                                 len = 0;
2297                                                 if ( loc > 0 ){
2298                                                         len = WideCharToMultiByte( CP_ACP, 0, wp, loc,
2299                                                                 buf, emr->emrtext.nChars * 2, NULL, NULL );
2300                                                 }
2301                                                 int newloc = len;
2302                                                 // \8cã\94¼\95\94\95ª
2303                                                 if ( emr->emrtext.nChars > (unsigned int)loc ){
2304                                                         len += WideCharToMultiByte( CP_ACP, 0, wp+loc, emr->emrtext.nChars - loc,
2305                                                                 buf+len, emr->emrtext.nChars * 2 - len, NULL, NULL );
2306                                                 }
2307                                                 loc = newloc;
2308                                                 text = buf;
2309 #endif
2310
2311                                         } else {
2312                                                 // ANSI
2313                                                 CallbackMain(DCH_HITTEXT1, text, len, (HWND)loc);
2314                                         }
2315
2316                                         DBW("Found@Enum");
2317 #if 0
2318                                         CallbackMain(DCH_HITTEXT1, text, len, (HWND)loc);
2319                                         if ( buf )
2320                                                 delete buf;
2321 #endif
2322 #if 0
2323                                         {
2324                                         char b[100];
2325                                         sprintf(b,"exScale=%f eyScale=%f ptlReference=(%d,%d)",emr->exScale, emr->eyScale, emr->emrtext.ptlReference.x, emr->emrtext.ptlReference.y );
2326                                         DBW(b);
2327                                         DBW("iGraphicsMode=%d", emr->iGraphicsMode);
2328                                         }
2329 #endif
2330 #if 0
2331                                         {
2332                                                 for ( int i=0;i<(int)emr->emrtext.nChars;i++ ){
2333                                                         DBW(">%d", ((int*)(((char*)emr) + emr->emrtext.offDx))[i] );
2334                                                 }
2335                                         }
2336 #endif
2337 //                                      DBW("[%d %d][%d %d]text=(%s)", emr->rclBounds.left, emr->rclBounds.top, CursorPoint.x, CursorPoint.y, text);
2338 //                                      result = false; // stop enumration      // \8d\82\91¬\89»\82Ì\82½\82ß\93r\92\86\82Å\8fI\82í\82è\82É\82µ\82½\82¢\82ª\81E\81E\81E\82Ç\82¤\82µ\82æ\82¤\81H
2339 #if METAEXTTEXTOUT
2340                                         // prevent to get from ExtTextOut hook
2341                                         FoundLocA = -1;
2342                                         FoundLocW = -1;
2343 #endif
2344                                         HitFound = true;
2345                                 }
2346                         }
2347 #else   // for debug
2348                         if ( mfr->iType == EMR_EXTTEXTOUTW ){
2349                                 CallbackMain(DCH_EXTTEXTOUTW, emr, sizeof(EMREXTTEXTOUTW) + emr->emrtext.nChars * sizeof(wchar_t), (HWND)hdc);
2350                         } else {
2351                                 CallbackMain(DCH_EXTTEXTOUTA, emr, sizeof(EMREXTTEXTOUTA) + emr->emrtext.nChars, (HWND)hdc);
2352                         }
2353 #endif
2354                 }
2355                         break;
2356         }
2357         return true;
2358 }
2359
2360 }       // extern "C"
2361
2362 // text\82Ì\90æ\93ª\82ð(0,0)\82Æ\82µ\82½\8dÀ\95W\82Å\81Apos\82Ì\88Ê\92u\82É\82 \82étext\82Ì\95\8e\9a\88Ê\92u\82ð\95Ô\82·
2363 int GetTextFromPoint( HDC hdc, const char *text, int len, int pos_x, int pos_y, const int *dx )
2364 {
2365         if ( pos_x < 0 || pos_y < 0 ) return -1;
2366
2367         int count = 0;
2368         SIZE sz;
2369         int *rdx = NULL;
2370         if ( dx ){
2371                 rdx = new int[len];
2372                 memset( rdx, 0, len*sizeof(int) );
2373         }
2374         if ( !GetTextExtentExPointA( hdc, text, len, pos_x, &count, rdx, &sz ) ){
2375                 DBW("GetTextExtentExPointA Failure!!");
2376                 if ( rdx )
2377                         delete rdx;
2378                 return -1;
2379         }
2380 #if METAEXTTEXTOUT
2381         LastX += sz.cx; // update
2382 #endif
2383         // size over check
2384         if ( pos_y > sz.cy
2385                 || pos_x > sz.cx
2386                 ){
2387                 if ( rdx ) delete rdx;
2388                 return -1;
2389         }
2390         DBW("A:len=%d pos_x=%d sz.cx=%d", len, pos_x, sz.cx);
2391         if ( dx && count > 0 ){
2392                 // ex.
2393                 // Win98,Notepad\82Ì\93ú\96{\8cê\8fã\82Å
2394                 //  dx = 0, 8, 0, 8, 0, 8, ...
2395                 // rdx = 9,10, 9,10, 9,10, ...
2396 #if 0
2397                 {
2398                         int i;
2399                         for ( i=0;i<len;i++ ){
2400                                 DBW(" dx[%2d]=%d",i,dx[i]);
2401                         }
2402                         for ( i=0;i<count;i++ ){
2403                                 DBW("rdx[%2d]=%d",i,rdx[i+1]-rdx[i]);
2404                         }
2405                 }
2406 #endif
2407                 // spacing\82Ì\8cë\8d·\82ð\8cv\8eZ
2408                 // Times New Roman\82È\82Ç\82Å\92²\82×\82é\82Æ\82©\82È\82è\82Ì\8cë\8d·\82ª\82 \82é\81B\82È\82º\81H
2409
2410                 int i = 0;
2411                 int j = 0;
2412                 int sumdx = 0;
2413 //              DBW("rd(x)[0]=%d,%d",dx[0],rdx[0]);
2414                 if ( rdx[0] ){
2415                         if ( dx[0] ){
2416                                 sumdx = dx[0] - rdx[0];
2417                         } else {
2418                                 sumdx = dx[1] - rdx[0];
2419                         }
2420                         i++;
2421                         j++;
2422                 }
2423                 for ( ;i<count;i++,j++ ){
2424 #if 0
2425                         if ( rdx[i] == rdx[i-1] ){ j--; continue;}      // for multi-bytes font
2426                                                                                                                 //*++ \82 \82Æ\82Å ExtTextOut API manual\82ð\8eQ\8fÆ
2427                         sumdx += dx[j] - (rdx[i]-rdx[i-1]);
2428 //                      DBW("%3d <> %3d", dx[j], rdx[i]-rdx[i-1]);
2429 #else   // Win98\82Å\82Í\81Amulti-byte\82Å\82à\95ª\8eU\82³\82¹\82Ä\82¢\82é\8fê\8d\87\82ª\82 \82é\82½\82ß\81Adx\82Å\94»\92f
2430                         sumdx += (dx[j]?dx[j]:dx[j+1]) - (rdx[i]-rdx[i-1]);
2431 #endif
2432                 }
2433 //              DBW("sumdx=%d",sumdx);
2434                 if ( !GetTextExtentExPointA( hdc, text, len, pos_x - sumdx, &count, rdx, &sz ) ){
2435                         if ( rdx )
2436                                 delete rdx;
2437                         return -1;
2438                 }
2439         }
2440         if ( rdx )
2441                 delete rdx;
2442         return count;
2443 }
2444 int GetTextFromPoint( HDC hdc, const wchar_t *text, int len, int pos_x, int pos_y, const int *dx )
2445 {
2446 #if USE_VXD
2447         if (WindowsNT)
2448 #endif
2449         {
2450                 if ( pos_x < 0 || pos_y < 0 ) return -1;
2451
2452                 int count = 0;
2453                 SIZE sz;
2454                 int *rdx = NULL;
2455                 if ( dx ){
2456                         rdx = new int[ len ];
2457                         memset( rdx, 0, len );
2458                 }
2459                 if ( !GetTextExtentExPointW( hdc, text, len, pos_x, &count, rdx, &sz ) )
2460                 {
2461                         DBW("GetTextExtentExPointW Failure!!");
2462                         if ( rdx )
2463                                 delete[] rdx;
2464                         return -1;
2465                 }
2466 #if METAEXTTEXTOUT
2467                 LastX += sz.cx;
2468 #endif
2469                 // size over check
2470                 if ( pos_y > sz.cy
2471                         || pos_x > sz.cx
2472                         ){
2473                         if ( rdx ) delete[] rdx;
2474                         return -1;
2475                 }
2476                 DBW("W:len=%d pos_x=%d sz.cx=%d", len, pos_x, sz.cx);
2477                 if ( dx && count > 0 ){
2478                         // spacing\82Ì\8cë\8d·\82ð\8cv\8eZ
2479                         // Times New Roman\82È\82Ç\82Å\92²\82×\82é\82Æ\82©\82È\82è\82Ì\8cë\8d·\82ª\82 \82é\81B\82È\82º\81H
2480                         int i = 0;
2481                         int j = 0;
2482                         int sumdx = 0;
2483         //              DBW("rd(x)[0]=%d,%d",dx[0],rdx[0]);
2484                         if ( rdx[0] ){
2485                                 sumdx = dx[0] - rdx[0];
2486                                 i++;
2487                                 j++;
2488                         }
2489                         for ( ;i<count-1;i++,j++ ){
2490 #if 0
2491                                 if ( rdx[i] == rdx[i-1] ){ j--; continue;}      // for multi-bytes font
2492                                                                                                                 //*++ \82 \82Æ\82Å ExtTextOut API manual\82ð\8eQ\8fÆ
2493                                 sumdx += dx[j] - (rdx[i]-rdx[i-1]);
2494         //                      DBW("%3d <> %3d", dx[j], rdx[i]-rdx[i-1]);
2495 #else
2496                                 sumdx += (dx[j]?dx[j]:dx[j+1]) - (rdx[i]-rdx[i-1]);
2497 #endif
2498                         }
2499         //              DBW("sumdx=%d",sumdx);
2500                         if ( !GetTextExtentExPointW( hdc, text, len, pos_x - sumdx, &count, rdx, &sz ) ){
2501                                 if ( rdx )
2502                                         delete rdx;
2503                                 return -1;
2504                         }
2505                 }
2506                 if ( rdx )
2507                         delete rdx;
2508                 return (count == len && sz.cx < pos_x) ? -1 : count;
2509         }
2510 #if USE_VXD
2511         else {
2512                 char *buf = new char[ len * sizeof(wchar_t) ];
2513                 memset( buf, 0, len * sizeof(wchar_t) );
2514                 int ansilen = WideCharToMultiByte( CP_ACP, 0, text, len, buf, len*sizeof(wchar_t), NULL, NULL );
2515                 int r = GetTextFromPoint( hdc, buf, ansilen, pos_x, pos_y, dx );
2516                 delete buf;
2517                 return r;
2518         }
2519 #endif
2520 }
2521
2522 #define WMCD_EXISTCHECK         0x4000
2523 #define WMCD_SETPOINT           0x4001
2524
2525 class TDC {
2526         HDC hdc;
2527         HWND hwnd;
2528 public:
2529         TDC()
2530         :hwnd(NULL)
2531         {
2532                 hdc = GetDC(NULL);
2533         }
2534         TDC(HWND _hwnd)
2535         :hwnd(_hwnd)
2536         {
2537                 hdc = GetWindowDC(hwnd);
2538         }
2539         ~TDC()
2540         {
2541                 reset();
2542         }
2543         void reset()
2544         {
2545                 if (hdc){
2546                         ReleaseDC(hwnd, hdc);
2547                         hdc = NULL;
2548                 }
2549         }
2550         operator HDC() { return hdc; }
2551         bool operator !() { return hdc==NULL; }
2552 };
2553
2554 bool CaptureImage(HWND hwnd, bool movesend, bool non_block)
2555 {
2556         MoveSendMode = movesend;
2557         CaptureImageBlocking = false;
2558
2559         bool capture_page = false;
2560         if (hwndAMODI){
2561                 capture_page = SendMessage(hwndAMODI, WM_AMODI, AMODI_CMD_PAGE_CAPTURE, 0) ? true : false;
2562         }
2563
2564         // Get the rect of the target window.
2565         RECT rcTarget;
2566         if (!GetWindowRect(hwnd, &rcTarget)){
2567                 // window died?
2568                 return false;
2569         }
2570         if (!ExtAMODI){
2571                 if (!IsWindowEnabled(hwndAMODI)){
2572                         // AMODI died?
2573                         hwndAMODI = FindAMODI();
2574                         if (!hwndAMODI)
2575                                 return false;
2576                 }
2577         }
2578         int w = rcTarget.right - rcTarget.left;
2579         int h = rcTarget.bottom - rcTarget.top;
2580         if (w==0 || h==0){
2581                 return false;   // no area in the target.
2582         }
2583
2584         POINT ptCursor; // \89æ\91\9c\8fã\82Ì\83J\81[\83\\83\8b\88Ê\92u
2585         int x, y;
2586         if (capture_page){
2587                 x = rcTarget.left;
2588                 y = rcTarget.top;
2589                 ptCursor.x = ScreenPoint.x - rcTarget.left;
2590                 ptCursor.y = ScreenPoint.y - rcTarget.top;
2591         } else {
2592                 // x\95û\8cü : target rect\82Ì\8d\92[\82©\82ç
2593                 // y\95û\8cü : cursor point\82Ì\8fã\89º100 pixel
2594                 x = rcTarget.left;
2595                 int offs = 100;
2596                 if (ScreenPoint.y - rcTarget.top < offs){
2597                         if (ScreenPoint.y < rcTarget.top) return false; // click on out of rect?
2598                         y = rcTarget.top;
2599                         h = ScreenPoint.y - rcTarget.top + offs;
2600                 } else {
2601                         y = ScreenPoint.y - offs;
2602                         h = offs * 2;
2603                 }
2604                 if (y+h>rcTarget.bottom){
2605                         h = rcTarget.bottom - y;
2606                 }
2607                 ptCursor.x = ScreenPoint.x - rcTarget.left;
2608                 ptCursor.y = ScreenPoint.y - y;
2609         }
2610
2611         if (0){
2612                 HWND hwnd = GetDesktopWindow();
2613                 RECT rc;
2614                 GetWindowRect(hwnd, &rc);
2615                 x = 0;
2616                 y = 0;
2617                 w = rc.right - rc.left;
2618                 h = rc.bottom - rc.top;
2619         }
2620
2621         if (!capture_page){
2622                 // Notify start enumrate
2623                 CallbackMain(DCH_START, &CursorPoint, sizeof(CursorPoint), hwnd);
2624         }
2625
2626         bool ok = false;
2627
2628         TDC hdc;
2629
2630         if (!hdc){
2631                 goto jend;
2632         }
2633
2634 #if USE_SCALING
2635         POINT pts[3];
2636         pts[0].x = x;
2637         pts[0].y = y;
2638         pts[1].x = w;
2639         pts[1].y = h;
2640         pts[2].x = ptCursor.x;
2641         pts[2].y = ptCursor.y;
2642         DoScale(hdc, pts, 3);
2643         //DBW("%d,%d %d,%d,%d,%d -> %d,%d %d,%d,%d,%d", ptCursor.x, ptCursor.y, x, y, w, h, pts[2].x, pts[2].y, pts[0].x, pts[0].y, pts[1].x, pts[1].y);
2644         x = pts[0].x;
2645         y = pts[0].y;
2646         w = pts[1].x;
2647         h = pts[1].y;
2648         ptCursor.x = pts[2].x;
2649         ptCursor.y = pts[2].y;
2650 #endif
2651
2652         // capture image
2653
2654         int wlen = (w*3+3)&~3;
2655
2656         /* \8f\91\82«\8d\9e\82Ý\97p\83o\83b\83t\83@\82Ì\83T\83C\83Y\8cv\8eZ */
2657         DWORD dwFSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + wlen * h;
2658
2659         /* \83o\83b\83t\83@\8am\95Û\82Æ\83|\83C\83\93\83^\90Ý\92è */
2660         LPBYTE lpBuf = (LPBYTE)new char[dwFSize];
2661         if (!lpBuf){
2662                 goto jend;
2663         }
2664
2665         LPBITMAPFILEHEADER lpHead = (LPBITMAPFILEHEADER)lpBuf;
2666         LPBITMAPINFOHEADER lpInfo = (LPBITMAPINFOHEADER)(lpBuf+sizeof(BITMAPFILEHEADER));
2667         LPBYTE lpPixel = lpBuf+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
2668
2669         /* 24\83r\83b\83gBMP\83t\83@\83C\83\8b\82Ì\83w\83b\83_\8dì\90¬ */
2670         lpHead->bfType = ('M'<<8) +'B';
2671         lpHead->bfSize = dwFSize;
2672         lpHead->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
2673         lpInfo->biSize = sizeof(BITMAPINFOHEADER);
2674         lpInfo->biWidth = w;
2675         lpInfo->biHeight = h;
2676         lpInfo->biPlanes = 1;
2677         lpInfo->biBitCount = 24;
2678
2679         HBITMAP hBmp = CreateCompatibleBitmap(hdc, w, h);
2680         if (hBmp){
2681                 HDC hdcMem = CreateCompatibleDC(hdc);
2682                 if (hdcMem){
2683                         HDC hOld = (HDC)SelectObject(hdcMem, hBmp);
2684                         if (hOld!=(HDC)GDI_ERROR){
2685                                 BOOL r = BitBlt(hdcMem, 0, 0, w, h, hdc, x, y, SRCCOPY);
2686                                 SelectObject(hdcMem, hOld);
2687                                 if (r){
2688 //                                      int lines = GetDIBits(hdc, hBmp, 0, h, NULL, (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS);
2689                                         int lines = GetDIBits(hdc, hBmp, 0, h, lpPixel, (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS);
2690                                         if (lines!=0){
2691                                                 ok = true;
2692                                         } else {
2693                                                 dbw("GetDIBits error??? %d h=%d w=%d bfSize=%d", GetLastError(), h, w, dwFSize);
2694                                         }
2695                                 } else {
2696 //                                              dbw("BitBlt error??? %d", GetLastError());
2697                                 }
2698                         }
2699                         DeleteObject(hdcMem);
2700                 }
2701                 DeleteObject(hBmp);
2702         }
2703
2704         hdc.reset();
2705
2706         if (ok){
2707                 ok = false;
2708
2709                 //TCHAR path[sizeof(AMODIPath)+40];
2710                 TCHAR *path = ImageTextPath;
2711                 size_t path_size = sizeof(ImageTextPath);
2712                 size_t len;
2713                 if (ExtAMODI){
2714                         len = _tcslen(AMODIPath);
2715                         _tcscpy(path, AMODIPath);
2716                 } else {
2717                         memset(path, 0, path_size);
2718                         len = GetTempPath((DWORD)path_size, path);
2719                 }
2720                 if (len>0){
2721                         // send image to AMODI
2722                         SYSTEMTIME t;
2723                         GetLocalTime(&t);
2724                         if (ExtAMODI){
2725                                 wsprintf(path+len, /*path_size-len,*/ _T("\\%04d-%02d-%02d-%02d%02d%02d-(%d,%d)-n%d.bmp"),
2726                                         t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, ptCursor.x, ptCursor.y, NumPrevWords );
2727                         } else {
2728                                 wsprintf(path+len, /*path_size-len,*/ _T("\\amodi\\%04d-%02d-%02d-%02d%02d%02d-n%d.bmp"),
2729                                         t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, NumPrevWords );
2730                                 SendAMODI(WMCD_SETPOINT, (char*)&ptCursor, sizeof(ptCursor));
2731                         }
2732                         HANDLE fh = CreateFile(path,  GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2733                         if (fh!=INVALID_HANDLE_VALUE){
2734                                 DWORD dwSize;
2735                                 WriteFile(fh, lpBuf, dwFSize, &dwSize, NULL);
2736                                 CloseHandle(fh);
2737                                 SaveImageTime = GetTickCount();
2738
2739                                 if (capture_page){
2740                                         ok = true;
2741                                 } else {
2742                                         len = (int)_tcslen(path);
2743                                         _tcsncat(path+len, _T(".txt"), path_size-len);
2744                                         if (non_block){
2745                                                 CaptureImageBlocking = true;
2746                                         } else {
2747                                                 if (WaitAndGetResult(path, 3000))
2748                                                         ok = true;
2749                                         }
2750                                 }
2751                         }
2752                 }
2753         }
2754         delete[] lpBuf;
2755
2756 jend:
2757         if (!CaptureImageBlocking){
2758                 if (!capture_page){
2759                         CallbackMain(DCH_END | (MoveSendMode ? DCH_MOVESEND : 0), NULL, 0, hwnd );
2760                 }
2761         }
2762
2763         return ok;
2764 }
2765
2766 bool WaitAndGetResult(const TCHAR *path, unsigned waittime)
2767 {
2768         bool ok = false;
2769
2770         // wait and get text from AMODI
2771
2772         HANDLE fh = WaitForResult(path, waittime);
2773
2774         CaptureImageBlocking = false;
2775
2776         if (fh==INVALID_HANDLE_VALUE){
2777                 DBW("file open timeout");
2778                 CheckAMODIAlive();
2779         } else {
2780                 DWORD size = GetFileSize(fh, NULL);
2781                 if (size>0){
2782                         unsigned bufsize = size+sizeof(wchar_t);
2783                         char *text = new char[bufsize];
2784                         if (text){
2785                                 DWORD rbyte;
2786                                 if (ReadFile(fh, text, size, &rbyte, NULL)){
2787                                         if (rbyte==size){
2788                                                 *(wchar_t*)&text[size] = '\0';
2789                                                 // text\82Ì\82P\8ds\96Ú\82Í\89ð\90Í\8fî\95ñ
2790                                                 // format
2791                                                 // (\83}\83E\83X\83J\81[\83\\83\8b\82Ì\82 \82é\83e\83L\83X\83g\88Ê\92u[\95\8e\9a\96Ú zero-index])
2792                                                 int loc = 0;
2793                                                 int col = 0;
2794                                                 wchar_t *p = (wchar_t*)text;
2795                                                 while (*p){
2796                                                         wchar_t c = *p++;
2797                                                         if (c=='\n'){
2798                                                                 break;
2799                                                         }
2800                                                         if (col==0){
2801                                                                 loc = _wtoi(p);
2802                                                                 col++;
2803                                                                 while (iswdigit(*p)) p++;
2804                                                         }
2805                                                 }
2806
2807                                                 DBW("%d:%ws", loc, p);
2808                                                 CallbackMain(DCH_HITTEXT2, p, bufsize - (int)((char*)p-text), (HWND)loc);
2809
2810                                                 ok = true;
2811                                         }
2812                                 }
2813                                 delete[] text;
2814                         }
2815                 }
2816                 CloseHandle(fh);
2817                 DeleteFile(path);
2818         }
2819         CallbackMain(DCH_END | (MoveSendMode ? DCH_MOVESEND : 0), NULL, 0, NULL );
2820         return ok;
2821 }
2822
2823 HANDLE WaitForResult(const TCHAR *path, unsigned waittime)
2824 {
2825         HANDLE fh = INVALID_HANDLE_VALUE;
2826
2827         while (1){
2828                 fh = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2829                 if (fh!=INVALID_HANDLE_VALUE)
2830                         break;
2831
2832                 DWORD now = GetTickCount();
2833                 if (now-SaveImageTime > waittime)
2834                         break;
2835
2836                 Sleep(10);
2837         }
2838
2839         return fh;
2840 }
2841
2842 #define APPNAME _T("Auto MODI")
2843
2844 static HWND hwndFind;
2845 static BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
2846 {
2847         TCHAR wndname[80];
2848         if (GetWindowText(hwnd, wndname, tsizeof(wndname))<0){
2849                 return TRUE;
2850         }
2851         if (_tcscmp(wndname, APPNAME)){ return TRUE; }
2852
2853         COPYDATASTRUCT cd;
2854         cd.dwData = WMCD_EXISTCHECK;
2855         cd.lpData = (void*)APPNAME;
2856         cd.cbData = (DWORD)(_tcslen(APPNAME)+1)*sizeof(TCHAR);
2857         if ( SendMessage( hwnd, WM_COPYDATA, 0, (LPARAM)&cd ) )
2858         {
2859                 // found
2860                 hwndFind = hwnd;
2861                 return FALSE;
2862         }
2863         return TRUE;
2864 }
2865
2866 HWND FindAMODI()
2867 {
2868         hwndFind = NULL;
2869         EnumWindows(EnumWindowsProc, 0);
2870         return hwndFind;
2871 }
2872
2873 int SendAMODI(int cmd, const char *data, int len)
2874 {
2875         COPYDATASTRUCT cd;
2876         cd.dwData = cmd;
2877         cd.lpData = (void*)data;
2878         cd.cbData = len;
2879         return (int)SendMessage(hwndAMODI, WM_COPYDATA, 0, (LPARAM)&cd);
2880 }
2881
2882 void CheckAMODIAlive()
2883 {
2884         CallbackMain(DCH_LAUNCH_AMODI, NULL, 0, 0);
2885 }
2886
2887 void SendMoveMessage()
2888 {
2889 #if MOVESEND_POST
2890         PostMessage(hwndCallback, WM_MOVESEND, MouseMoving ? 0 : -1, 0);
2891 #else
2892 //      CallbackMain(DCH_MOVESEND, pt, sizeof(*pt), 0);
2893         MouseMoving = true;
2894         if (SendMoveEvent) SetEvent(SendMoveEvent);
2895 #endif
2896 }
2897 void SendCancelMove()
2898 {
2899 #if MOVESEND_POST
2900         PostMessage(hwndCallback, WM_MOVESEND, MouseMoving ? 0 : -1, 0);
2901 #else
2902 //      CallbackMain(DCH_MOVESEND, NULL, 0, (HWND)-1);
2903         MouseMoving = false;
2904         if (SendMoveEvent) SetEvent(SendMoveEvent);
2905 #endif
2906 }
2907
2908 #if !MOVESEND_POST
2909 // main program\82ÌWindows message\8f\88\97\9d\82ª\8fd\82¢\82Æ\81ACalblackMain\82à\8fd\82­\82È\82é\82½\82ß\81A
2910 // mouse move\82Í\95Êthread\82Å\8f\88\97\9d
2911 DWORD WINAPI SendMoveThread(LPVOID vdParam)
2912 {
2913         while(1){
2914                 if (WaitForSingleObject(SendMoveEvent, INFINITE) != WAIT_OBJECT_0){
2915                         break;
2916                 }
2917                 CallbackMain(DCH_MOVESEND, NULL, 0, (HWND)(MouseMoving ? 0 : -1));
2918         }
2919         return 0;
2920 }
2921 #endif
2922
2923 #if EXC_WOW64 && defined(_M_X64)
2924 void CheckWOW64()
2925 {
2926         typedef BOOL (WINAPI *FNIsWow64Process)(HANDLE hProcess, PBOOL Wow64Process);
2927
2928         FNIsWow64Process _IsWow64Process = (FNIsWow64Process)GetProcAddress(GetModuleHandle("kernel32"),"IsWow64Process");
2929         if (_IsWow64Process){
2930                 BOOL flag = FALSE;
2931                 if (_IsWow64Process(hProcess, &flag)){
2932                         fWow64 = int_bool(flag);
2933                 }
2934         }
2935 }
2936 #endif
2937
2938 bool EnablePrivilege(LPTSTR lpszPrivilege, bool bEnable)
2939 {
2940         BOOL             bResult;
2941         LUID             luid;
2942         HANDLE           hToken;
2943         TOKEN_PRIVILEGES tokenPrivileges;
2944
2945         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
2946                 return false;
2947         
2948         if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid)) {
2949                 CloseHandle(hToken);
2950                 return false;
2951         }
2952
2953         tokenPrivileges.PrivilegeCount           = 1;
2954         tokenPrivileges.Privileges[0].Luid       = luid;
2955         tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
2956         
2957         bResult = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
2958         
2959         CloseHandle(hToken);
2960
2961         return bResult && GetLastError() == ERROR_SUCCESS;
2962 }
2963
2964 /*======================================================================//
2965 //      DllMain
2966 //----------------------------------------------------------------------//
2967 // Description:
2968 //
2969 // Arguments:
2970 //
2971 // Return Value:
2972 //
2973 //======================================================================*/
2974 #ifdef _MSC_VER
2975 BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID )
2976 #else
2977 int WINAPI DllEntryPoint(HINSTANCE hInst, DWORD reason, LPVOID)
2978 #endif
2979 {
2980         switch ( reason ){
2981                 case DLL_PROCESS_ATTACH:
2982                         hInstance = hInst;
2983                         idProcess = GetCurrentProcessId();
2984                         for (int i=0;i<2;i++){
2985                                 hProcess = OpenProcess( PROCESS_ALL_ACCESS|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, TRUE, idProcess );
2986                                 if ( hProcess ){
2987 #if USE_DBW
2988                                         DBW("Attach %d(%08X)-%d : %08X", idProcess, hProcess, attach++,_ExtTextOutA);
2989 #endif
2990                                         break;
2991                                 } else {
2992                                         DBW("OpenProcess Error: %08X %d", idProcess, GetLastError());
2993                                         if (i==0){
2994                                                 if (!EnablePrivilege(SE_DEBUG_NAME, true)) {
2995                                                         break;  // failed
2996                                                 }
2997                                         }
2998                                 }
2999                         }
3000 #if EXC_WOW64 && defined(_M_X64)
3001                         CheckWOW64();
3002 #ifdef _WIN64
3003                         if (fWow64){
3004                                 DBW("WOW64 true");
3005                                 return FALSE;
3006                         }
3007 #else
3008                         if (!fWow64){
3009                                 DBW("WOW64 false");
3010                                 return FALSE;
3011                         }
3012 #endif
3013                         DBW("fWow64=%d", fWow64);
3014 #endif
3015                         if (siPageSize==0){
3016                                 SYSTEM_INFO si;
3017                                 GetSystemInfo( &si );
3018                                 siPageSize = si.dwPageSize;
3019                         }
3020                         hInstSHCore = LoadLibrary(_T("shcore.dll"));
3021 #if !MOVESEND_POST
3022                         SendMoveEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
3023                         CreateThread(NULL , 0 , SendMoveThread , NULL , 0 , &SendMoveThreadId);
3024 #endif
3025                         break;
3026                 case DLL_PROCESS_DETACH:
3027 //                      UNPROTECT_SHARE();
3028 #if !MOVESEND_POST
3029                         if (SendMoveEvent){
3030                                 CloseHandle(SendMoveEvent);
3031                                 SendMoveEvent = NULL;
3032                         }
3033 #endif
3034                         if (hInstSHCore){
3035                                 FreeLibrary(hInstSHCore);
3036                                 hInstSHCore = NULL;
3037                         }
3038 #if USE_DBW
3039                         DBW("Detach %d-%d", GetCurrentProcessId(),--attach);
3040 #endif
3041                         if ( hProcess ){
3042                                 CloseHandle( hProcess );
3043                         }
3044                         break;
3045         }
3046         return TRUE;
3047 }
3048 //---------------------------------------------------------------------------
3049 static HWND hWin = NULL;
3050 static const char *clsname = "TDbgMsgForm";
3051 static const char *winname = "Debug Messenger";
3052 void dbw( const char *format, ... )
3053 {
3054         if ( !hWin ){
3055                 hWin = FindWindowA( clsname, winname );
3056                 if ( !hWin ) return;
3057         }
3058         va_list ap;
3059         va_start( ap, format );
3060         char buf[ 2048 ];
3061 #ifdef _WIN64
3062         strcpy(buf, "x64:");
3063         wvsprintfA( buf+4, format, ap );
3064 #else
3065         wvsprintfA( buf, format, ap );
3066 #endif
3067         COPYDATASTRUCT cds;
3068         cds.dwData = 1; // Indicate String
3069         cds.cbData = (DWORD)strlen(buf);
3070         cds.lpData = buf;
3071         SendMessage( hWin, WM_COPYDATA, NULL, (LPARAM)&cds );
3072         va_end( ap );
3073 }