1 #define _WIN32_WINNT 0x0501
2
3 #include "GetWord.h"
4 #include "TextOutHook.h"
5
GetWindowType(HWND WND,const char * WNDClass)6 TKnownWndClass GetWindowType(HWND WND, const char* WNDClass)
7 {
8 const char* StrKnownClasses[] = {
9 "RICHEDIT20A",
10 "RICHEDIT20W",
11 "RICHEDIT",
12 "EDIT",
13 "INTERNET EXPLORER_SERVER",
14 "CONSOLEWINDOWCLASS", // NT
15 "TTYGRAB", // 9x
16 "VIRTUALCONSOLECLASS", // ConEmu
17 };
18 TKnownWndClass KnownClasses[] = {
19 kwcRichEdit,
20 kwcRichEdit,
21 kwcRichEdit,
22 kwcMultiLineEdit,
23 kwcInternetExplorer_Server,
24 kwcConsole,
25 kwcConsole,
26 kwcConEmu,
27 };
28 int i;
29 for (i=0; i<8; i++) {
30 if (_stricmp(WNDClass, StrKnownClasses[i])==0)
31 break;
32 }
33 if (i<8) {
34 if (KnownClasses[i] == kwcMultiLineEdit) {
35 if ((GetWindowLong(WND, GWL_STYLE) & ES_MULTILINE) == 0)
36 return kwcSingleLineEdit;
37 }
38 else if (KnownClasses[i] == kwcConEmu) {
39 HWND hConsole = (HWND)(DWORD_PTR)GetWindowLongPtr(WND, 0);
40 if (!hConsole || !IsWindow(hConsole))
41 return kwcUnknown;
42 }
43 return KnownClasses[i];
44 } else
45 return kwcUnknown;
46 }
47
Is_XP_And_Later()48 static BOOL Is_XP_And_Later()
49 {
50 OSVERSIONINFO stOSVI;
51 BOOL bRet;
52
53 memset(&stOSVI, 0, sizeof(OSVERSIONINFO));
54 stOSVI.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
55 bRet = GetVersionEx(&stOSVI);
56 if (FALSE == bRet) return FALSE;
57 return (VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId && (5 < stOSVI.dwMajorVersion || (5 == stOSVI.dwMajorVersion && 1 <= stOSVI.dwMinorVersion)));
58 }
59
ExtractWordFromRichEditPos(HWND WND,POINT Pt,DWORD * BeginPos)60 static char* ExtractWordFromRichEditPos(HWND WND, POINT Pt, DWORD *BeginPos)
61 {
62 return ExtractFromEverything(WND, Pt, BeginPos);
63 }
64
ExtractWordFromEditPos(HWND hEdit,POINT Pt,DWORD * BeginPos)65 static char* ExtractWordFromEditPos(HWND hEdit, POINT Pt, DWORD *BeginPos)
66 {
67 return ExtractFromEverything(hEdit, Pt, BeginPos);
68 }
69
ExtractWordFromIE(HWND WND,POINT Pt,DWORD * BeginPos)70 static char* ExtractWordFromIE(HWND WND, POINT Pt, DWORD *BeginPos)
71 {
72 return ExtractFromEverything(WND, Pt, BeginPos);
73 }
74
75 typedef struct TConsoleParams {
76 HWND WND;
77 POINT Pt;
78 RECT ClientRect;
79 WCHAR Buffer[256];
80 int BeginPos;
81 } TConsoleParams;
82
GetWordFromConsolePack(TConsoleParams * params,BOOL * pInvalidConsole)83 static int GetWordFromConsolePack(TConsoleParams *params, BOOL *pInvalidConsole)
84 {
85 int WordLen=0;
86
87 *pInvalidConsole = TRUE;
88
89 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
90 if (hStdOut != INVALID_HANDLE_VALUE && hStdOut != 0) {
91 CONSOLE_SCREEN_BUFFER_INFO csbi;
92 if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
93
94 *pInvalidConsole = FALSE;
95
96 COORD CurPos;
97 CurPos.X = csbi.srWindow.Left + (SHORT)(params->Pt.x * (csbi.srWindow.Right - csbi.srWindow.Left + 1) / params->ClientRect.right);
98 CurPos.Y = csbi.srWindow.Top + (SHORT)(params->Pt.y * (csbi.srWindow.Bottom - csbi.srWindow.Top + 1) / params->ClientRect.bottom);
99 if ((CurPos.X >= 0) && (CurPos.X <= csbi.dwSize.X - 1) && (CurPos.Y >= 0) && (CurPos.Y <= csbi.dwSize.Y - 1)) {
100 int BegPos;
101 WCHAR *Buf;
102
103 params->BeginPos = CurPos.X;
104 CurPos.X = 0;
105 Buf = GlobalAlloc(GMEM_FIXED, (csbi.dwSize.X + 1)*sizeof(WCHAR));
106 if (Buf) {
107 DWORD ActualRead;
108 if ((ReadConsoleOutputCharacterW(hStdOut, Buf, csbi.dwSize.X, CurPos, &ActualRead)) && (ActualRead == (DWORD)csbi.dwSize.X)) {
109 BegPos=0;
110 WordLen=ActualRead;
111 if(WordLen>85) {
112 while(params->BeginPos-BegPos>43 && WordLen>85) {
113 BegPos++; WordLen--;
114 }
115 if(WordLen>85) WordLen=85;
116 params->BeginPos -= BegPos;
117 }
118 if(WordLen) {
119 memset(params->Buffer, 0, sizeof(params->Buffer));
120 lstrcpynW(params->Buffer, Buf + BegPos, WordLen+1);
121 }
122 }
123 GlobalFree(Buf);
124 }
125 }
126 }
127 }
128 return WordLen;
129 }
130
GetWordFromConsole(HWND WND,POINT Pt,DWORD * BeginPos)131 static char* GetWordFromConsole(HWND WND, POINT Pt, DWORD *BeginPos)
132 {
133 TConsoleParams *TP;
134 DWORD pid;
135 DWORD WordSize;
136 char *Result;
137 BOOL invalidConsole;
138
139 *BeginPos=0;
140 if((TP = malloc(sizeof(TConsoleParams))) == NULL)
141 return(NULL);
142 ZeroMemory(TP,sizeof(TConsoleParams));
143 TP->WND = WND;
144 TP->Pt = Pt;
145 ScreenToClient(WND, &(TP->Pt));
146 GetClientRect(WND, &(TP->ClientRect));
147
148 // GetWindowThreadProcessId(GetParent(WND), &pid);
149 GetWindowThreadProcessId(WND, &pid);
150
151 if (pid != GetCurrentProcessId()) {
152 if(Is_XP_And_Later()) {
153 if(AttachConsole(pid)) {
154 WordSize = GetWordFromConsolePack(TP, &invalidConsole);
155 FreeConsole();
156 } else {
157 WordSize = 0;
158 }
159 } else {
160 WordSize = 0;
161 }
162 } else {
163 WordSize = GetWordFromConsolePack(TP, &invalidConsole);
164 if( invalidConsole ) {
165 /*
166 Under Win 8.1 GetWindowThreadProcessId return current "conhost" process ID
167 instead of target window process ID.
168 We try to attach console to parent process.
169 */
170
171 if(Is_XP_And_Later()) {
172 if(AttachConsole( (DWORD)-1 )) {
173 WordSize = GetWordFromConsolePack(TP, &invalidConsole);
174 FreeConsole();
175 } else {
176 WordSize = 0;
177 }
178 } else {
179 WordSize = 0;
180 }
181 }
182 }
183
184 if (WordSize > 0 && WordSize <= 255) {
185 TEverythingParams CParams;
186
187 ZeroMemory(&CParams, sizeof(CParams));
188 CParams.Unicode=1;
189 CParams.BeginPos=TP->BeginPos;
190 CParams.WordLen=WordSize;
191 CopyMemory(CParams.MatchedWordW, TP->Buffer, WordSize * sizeof(wchar_t));
192 ConvertToMatchedWordA(&CParams);
193 *BeginPos = CParams.BeginPos;
194 Result = _strdup(CParams.MatchedWordA);
195
196 } else {
197 Result = NULL;
198 }
199 free(TP);
200 return Result;
201 }
202
GetWordFromConEmu(HWND WND,POINT Pt,DWORD * BeginPos)203 static char* GetWordFromConEmu(HWND WND, POINT Pt, DWORD *BeginPos)
204 {
205 HWND hConsole = (HWND)(DWORD_PTR)GetWindowLongPtr(WND, 0);
206 if (!hConsole || !IsWindow(hConsole))
207 return NULL;
208
209 RECT rcConEmu;
210 if (!GetWindowRect(WND, &rcConEmu) || rcConEmu.right <= rcConEmu.left || rcConEmu.bottom <= rcConEmu.top)
211 return NULL;
212 RECT rcConsole;
213 if (!GetClientRect(hConsole, &rcConsole) || rcConsole.right <= rcConsole.left || rcConsole.bottom <= rcConsole.top)
214 return NULL;
215
216 POINT ptReal = { (Pt.x - rcConEmu.left) * (rcConsole.right - rcConsole.left + 1) / ( rcConEmu.right - rcConEmu.left + 1),
217 (Pt.y - rcConEmu.top) * (rcConsole.bottom - rcConsole.top + 1 ) / (rcConEmu.bottom - rcConEmu.top + 1) };
218 ClientToScreen(hConsole, &ptReal);
219
220 return GetWordFromConsole(hConsole, ptReal, BeginPos);
221 }
222
TryGetWordFromAnyWindow(TKnownWndClass WndType,HWND WND,POINT Pt,DWORD * BeginPos)223 char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, DWORD *BeginPos)
224 {
225 typedef char* (*GetWordFunction_t)(HWND, POINT, DWORD*);
226 const GetWordFunction_t GetWordFunction[]= {
227 ExtractFromEverything,
228 ExtractWordFromRichEditPos,
229 ExtractWordFromEditPos,
230 ExtractWordFromEditPos,
231 ExtractWordFromIE,
232 GetWordFromConsole,
233 GetWordFromConEmu,
234 };
235 return GetWordFunction[WndType](WND, Pt, BeginPos);
236 }
237