OSDN Git Service

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