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