OSDN Git Service

use boost_1_56_0 and build by VS2013
[yamy/yamy.git] / fixscancodemap.cpp.bak
1 #include "fixscancodemap.h"\r
2 #include "registry.h"\r
3 #include "misc.h"\r
4 #include <tchar.h>\r
5 #include <tlhelp32.h>\r
6 \r
7 typedef HMODULE (WINAPI *FpGetModuleHandleW)(LPCWSTR);\r
8 typedef FARPROC (WINAPI *FpGetProcAddress)(HMODULE, LPCSTR);\r
9 typedef BOOL (WINAPI *FpUpdatePerUserSystemParameters)(DWORD, BOOL);\r
10 typedef HANDLE (WINAPI *FpOpenProcess)(DWORD, BOOL, DWORD);\r
11 typedef BOOL (WINAPI *FpOpenProcessToken)(HANDLE, DWORD, PHANDLE);\r
12 typedef BOOL (WINAPI *FpImpersonateLoggedOnUser)(HANDLE);\r
13 typedef BOOL (WINAPI *FpRevertToSelf)(VOID);\r
14 typedef BOOL (WINAPI *FpCloseHandle)(HANDLE);\r
15 \r
16 typedef struct {\r
17         DWORD header1;\r
18         DWORD header2;\r
19         DWORD count;\r
20         DWORD entry[1];\r
21 } ScancodeMap;\r
22 \r
23 typedef struct {\r
24         DWORD pid_;\r
25         TCHAR advapi32_[64];\r
26         CHAR impersonateLoggedOnUser_[32];\r
27         CHAR revertToSelf_[32];\r
28         CHAR openProcessToken_[32];\r
29         FpGetModuleHandleW pGetModuleHandle;\r
30         FpGetProcAddress pGetProcAddress;\r
31         FpUpdatePerUserSystemParameters pUpdate;\r
32         FpOpenProcess pOpenProcess;\r
33         FpCloseHandle pCloseHandle;\r
34 } InjectInfo;\r
35 \r
36 \r
37 static const DWORD s_fixEntryNum = 4;\r
38 static const DWORD s_fixEntry[] = {\r
39         0x003ae03a,\r
40         0x0029e029,\r
41         0x0070e070,\r
42         0x003b001e,\r
43 };\r
44 \r
45 #pragma runtime_checks( "", off )\r
46 static DWORD invokeFunc(InjectInfo *info)\r
47 {\r
48         BOOL ret;\r
49         HANDLE hToken;\r
50         HMODULE hAdvapi32;\r
51         FpImpersonateLoggedOnUser pImpersonateLoggedOnUser;\r
52         FpRevertToSelf pRevertToSelf;\r
53         FpOpenProcessToken pOpenProcessToken;\r
54 \r
55         hAdvapi32 = info->pGetModuleHandle(info->advapi32_);\r
56 \r
57         pImpersonateLoggedOnUser = (FpImpersonateLoggedOnUser)info->pGetProcAddress(hAdvapi32, info->impersonateLoggedOnUser_);\r
58         pRevertToSelf = (FpRevertToSelf)info->pGetProcAddress(hAdvapi32, info->revertToSelf_);\r
59         pOpenProcessToken = (FpOpenProcessToken)info->pGetProcAddress(hAdvapi32, info->openProcessToken_);\r
60 \r
61         HANDLE hProcess = info->pOpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info->pid_);\r
62         if (hProcess == NULL) {\r
63                 return 1;\r
64         }\r
65 \r
66         ret = pOpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE , &hToken);\r
67         if (ret == FALSE) {\r
68                 return 2;\r
69         }\r
70 \r
71         ret = pImpersonateLoggedOnUser(hToken);\r
72         if (ret == FALSE) {\r
73                 return 3;\r
74         }\r
75 \r
76         info->pUpdate(0, 1);\r
77 \r
78         ret = pRevertToSelf();\r
79         if (ret == FALSE) {\r
80                 return 4;\r
81         }\r
82 \r
83         info->pCloseHandle(hToken);\r
84         info->pCloseHandle(hProcess);\r
85         return 0;\r
86 }\r
87 static void afterFunc(void){}\r
88 #pragma runtime_checks( "", restore )\r
89 \r
90 static int acquirePrivileges()\r
91 {\r
92         int ret = 0;\r
93         HANDLE hToken = NULL;\r
94 \r
95         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {\r
96                 ret = 1;\r
97                 goto exit;\r
98         }\r
99 \r
100         LUID luid;\r
101         if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {\r
102                 ret = 2;\r
103                 goto exit;\r
104         }\r
105 \r
106         TOKEN_PRIVILEGES tk_priv;\r
107         tk_priv.PrivilegeCount = 1;\r
108         tk_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
109         tk_priv.Privileges[0].Luid = luid;\r
110 \r
111         if (!AdjustTokenPrivileges(hToken, FALSE, &tk_priv, 0, NULL, NULL)) {\r
112                 ret = 3;\r
113                 goto exit;\r
114         }\r
115 \r
116 exit:\r
117         if (hToken != NULL) {\r
118             CloseHandle(hToken);\r
119         }\r
120         return ret;\r
121 }\r
122 \r
123 \r
124 static DWORD getWinLogonPid()\r
125 {\r
126     DWORD pid = 0;\r
127         DWORD mySessionId = 0;\r
128 \r
129         if (ProcessIdToSessionId(GetCurrentProcessId(), &mySessionId) == FALSE) {\r
130                 return 0;\r
131         }\r
132 \r
133         HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\r
134         if (hSnap == INVALID_HANDLE_VALUE) {\r
135                 return 0;\r
136         }\r
137 \r
138         PROCESSENTRY32 pe;\r
139         pe.dwSize = sizeof(pe);\r
140 \r
141     BOOL bResult = Process32First(hSnap, &pe);\r
142         while (bResult){\r
143                 if (!_tcscmp(pe.szExeFile, _T("winlogon.exe"))) {\r
144                         DWORD sessionId;\r
145 \r
146                         if (ProcessIdToSessionId(pe.th32ProcessID, &sessionId) != FALSE) {\r
147                                 if (sessionId == mySessionId) {\r
148                                         pid = pe.th32ProcessID;\r
149                                         break;\r
150                                 }\r
151                         }\r
152                 }\r
153                 bResult = Process32Next(hSnap, &pe);\r
154         }\r
155 \r
156         CloseHandle(hSnap);\r
157         return pid;\r
158 }\r
159 \r
160 \r
161 static int injectThread(DWORD dwPID)\r
162 {\r
163         int ret = 0;\r
164         DWORD err = 0;\r
165         BOOL wFlag;\r
166 \r
167         HANDLE hProcess = NULL;\r
168         LPVOID remoteMem = NULL;\r
169         LPVOID remoteInfo = NULL;\r
170         DWORD invokeFuncAddr = (DWORD)invokeFunc;\r
171         DWORD afterFuncAddr = (DWORD)afterFunc;\r
172         DWORD memSize =  afterFuncAddr - invokeFuncAddr;\r
173         InjectInfo info;\r
174         HMODULE hMod;\r
175 \r
176         info.pid_ = GetCurrentProcessId();\r
177 \r
178         memcpy(&info.advapi32_, _T("advapi32.dll"), sizeof(info.advapi32_));\r
179         memcpy(&info.impersonateLoggedOnUser_, "ImpersonateLoggedOnUser", sizeof(info.impersonateLoggedOnUser_));\r
180         memcpy(&info.revertToSelf_, "RevertToSelf", sizeof(info.revertToSelf_));\r
181         memcpy(&info.openProcessToken_, "OpenProcessToken", sizeof(info.openProcessToken_));\r
182 \r
183         hMod = GetModuleHandle(_T("user32.dll"));\r
184         if (hMod != NULL) {\r
185                 info.pUpdate = (FpUpdatePerUserSystemParameters)GetProcAddress(hMod, "UpdatePerUserSystemParameters");\r
186                 if (info.pUpdate == NULL) {\r
187                         return 1;\r
188                 }\r
189         }\r
190 \r
191         hMod = GetModuleHandle(_T("kernel32.dll"));\r
192         if (hMod != NULL) {\r
193                 info.pGetModuleHandle = (FpGetModuleHandleW)GetProcAddress(hMod, "GetModuleHandleW");\r
194                 if (info.pGetModuleHandle == NULL) {\r
195                         return 1;\r
196                 }\r
197 \r
198                 info.pGetProcAddress = (FpGetProcAddress)GetProcAddress(hMod, "GetProcAddress");\r
199                 if (info.pGetProcAddress == NULL) {\r
200                         return 1;\r
201                 }\r
202 \r
203                 info.pOpenProcess = (FpOpenProcess)GetProcAddress(hMod, "OpenProcess");\r
204                 if (info.pOpenProcess == NULL) {\r
205                         return 1;\r
206                 }\r
207 \r
208                 info.pCloseHandle = (FpCloseHandle)GetProcAddress(hMod, "CloseHandle");\r
209                 if (info.pCloseHandle == NULL) {\r
210                         return 1;\r
211                 }\r
212         }\r
213 \r
214         if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) {\r
215                 ret = 1;\r
216                 goto exit;\r
217         }\r
218 \r
219         remoteMem = VirtualAllocEx(hProcess, NULL, memSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
220         if (remoteMem == NULL) {\r
221                 ret = 2;\r
222                 err = GetLastError();\r
223                 goto exit;\r
224         }\r
225 \r
226         wFlag = WriteProcessMemory(hProcess, remoteMem, (char*)invokeFunc, memSize, (SIZE_T*)0);\r
227         if (wFlag == FALSE) {\r
228                 ret = 3;\r
229                 goto exit;\r
230         }\r
231 \r
232         remoteInfo = VirtualAllocEx(hProcess, NULL, sizeof(info), MEM_COMMIT, PAGE_READWRITE);\r
233         if (remoteInfo == NULL) {\r
234                 ret = 2;\r
235                 err = GetLastError();\r
236                 goto exit;\r
237         }\r
238 \r
239         wFlag = WriteProcessMemory(hProcess, remoteInfo, (char*)&info, sizeof(info), (SIZE_T*)0);\r
240         if (wFlag == FALSE) {\r
241                 ret = 3;\r
242                 goto exit;\r
243         }\r
244 \r
245 #if 0\r
246         TCHAR buf[1024];\r
247 \r
248         _stprintf_s(buf, sizeof(buf)/sizeof(buf[0]),\r
249                 _T("execute UpdatePerUserSystemParameters(), inject code to winlogon.exe?\r\n")\r
250                 _T("invokeFunc=0x%p\r\n")\r
251                 _T("afterFunc=0x%p\r\n")\r
252                 _T("afterFunc - invokeFunc=%d\r\n")\r
253                 _T("remoteMem=0x%p\r\n")\r
254                 _T("remoteInfo=0x%p(size: %d)\r\n"),\r
255                 invokeFunc, afterFunc, memSize, remoteMem, remoteInfo, sizeof(info));\r
256         if (MessageBox((HWND)NULL, buf, _T("upusp"), MB_OKCANCEL | MB_ICONSTOP) == IDCANCEL) {\r
257                 (info.pUpdate)(0, 1);\r
258                 goto exit;\r
259         }\r
260 #endif\r
261 \r
262         HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, \r
263                 (LPTHREAD_START_ROUTINE)remoteMem, remoteInfo, 0, NULL);\r
264         if (hThread == NULL) {\r
265                 ret = 4;\r
266                 goto exit;\r
267         }\r
268 \r
269         if (WaitForSingleObject(hThread, 5000) == WAIT_TIMEOUT) {\r
270                 ret = 5;\r
271                 goto exit;\r
272         }\r
273         DWORD result = -1;\r
274         GetExitCodeThread(hThread, &result);\r
275         ret = result;\r
276         CloseHandle(hThread);\r
277 \r
278 exit:\r
279         if (remoteMem != NULL) {\r
280                 VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);\r
281         }\r
282 \r
283         if (remoteInfo != NULL) {\r
284                 VirtualFreeEx(hProcess, remoteInfo, 0, MEM_RELEASE);\r
285         }\r
286 \r
287         if (hProcess != NULL) {\r
288                 CloseHandle(hProcess);\r
289         }\r
290 \r
291         return ret;\r
292 }\r
293 \r
294 static int update()\r
295 {\r
296         MINIMIZEDMETRICS mm;\r
297         int result = 0;\r
298 \r
299         if (acquirePrivileges()) {\r
300                 result = 1;\r
301                 goto exit;\r
302         }\r
303 \r
304         DWORD dwPID;\r
305         if ((dwPID = getWinLogonPid()) == 0) {\r
306                 result = 1;\r
307                 goto exit;\r
308         }\r
309 \r
310         memset(&mm, 0, sizeof(mm));\r
311         mm.cbSize = sizeof(mm);\r
312         SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);\r
313 \r
314         if (injectThread(dwPID)) {\r
315                 result = 1;\r
316                 goto exit;\r
317         }\r
318 \r
319         SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);\r
320 \r
321 exit:\r
322         return result;\r
323 }\r
324 \r
325 int FixScancodeMap_fix()\r
326 {\r
327         ScancodeMap *origMap, *fixMap;\r
328         Registry reg(HKEY_CURRENT_USER, _T("Keyboard Layout"));\r
329         // Windows7 RC not support Scancode Map on HKCU?\r
330         //Registry reg(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout"));\r
331         DWORD origSize, fixSize;\r
332         bool ret;\r
333         int result = 0;\r
334 \r
335         // save original Scancode Map\r
336         ret = reg.read(_T("Scancode Map"), NULL, &origSize, NULL, 0);\r
337         if (ret) {\r
338                 origMap = reinterpret_cast<ScancodeMap*>(malloc(origSize));\r
339                 if (origMap == NULL) {\r
340                         result = 1;\r
341                         goto exit;\r
342                 }\r
343 \r
344                 ret = reg.read(_T("Scancode Map"), reinterpret_cast<BYTE*>(origMap), &origSize, NULL, 0);\r
345                 if (ret == false) {\r
346                         result = 1;\r
347                         goto exit;\r
348                 }\r
349 \r
350                 fixSize = origSize;\r
351                 fixMap = reinterpret_cast<ScancodeMap*>(malloc(origSize + s_fixEntryNum * sizeof(s_fixEntry[0])));\r
352                 if (fixMap == NULL) {\r
353                         result = 1;\r
354                         goto exit;\r
355                 }\r
356 \r
357                 memcpy_s(fixMap, origSize + s_fixEntryNum, origMap, origSize);\r
358         } else {\r
359                 origSize = 0;\r
360                 origMap = NULL;\r
361 \r
362                 fixSize = sizeof(ScancodeMap);\r
363                 fixMap = reinterpret_cast<ScancodeMap*>(malloc(sizeof(ScancodeMap) + s_fixEntryNum * sizeof(s_fixEntry[0])));\r
364                 if (fixMap == NULL) {\r
365                         result = 1;\r
366                         goto exit;\r
367                 }\r
368 \r
369                 fixMap->header1 = 0;\r
370                 fixMap->header2 = 0;\r
371                 fixMap->count = 1;\r
372                 fixMap->entry[0] = 0;\r
373         }\r
374 \r
375         for (DWORD i = 0; i < s_fixEntryNum; i++) {\r
376                 bool skip = false;\r
377 \r
378                 if (origMap) {\r
379                         for (DWORD j = 0; j < origMap->count; j++) {\r
380                                 if (HIWORD(s_fixEntry[i]) == HIWORD(origMap->entry[j])) {\r
381                                         skip = true;\r
382                                 }\r
383                         }\r
384                 }\r
385 \r
386                 if (skip) {\r
387                         // s_fixEntry[i] found in original Scancode Map, so don't fix it\r
388                         continue;\r
389                 }\r
390 \r
391                 // add fix entry to fixMap\r
392                 fixMap->entry[fixMap->count - 1] = s_fixEntry[i];\r
393                 fixMap->entry[fixMap->count] = 0;\r
394                 fixMap->count++;\r
395                 fixSize += 4;\r
396         }\r
397 \r
398         ret = reg.write(_T("Scancode Map"), reinterpret_cast<BYTE*>(fixMap), fixSize);\r
399         if (ret == false) {\r
400                 result = 1;\r
401                 goto exit;\r
402         }\r
403 \r
404         result = update();\r
405 \r
406         if (origMap) {\r
407                 ret = reg.write(_T("Scancode Map"), reinterpret_cast<BYTE*>(origMap), origSize);\r
408         } else {\r
409                 ret = reg.remove(_T("Scancode Map"));\r
410         }\r
411         if (ret == false) {\r
412                 result = 1;\r
413                 goto exit;\r
414         }\r
415 \r
416 exit:\r
417         free(origMap);\r
418         origMap = NULL;\r
419 \r
420         free(fixMap);\r
421         fixMap = NULL;\r
422 \r
423         return result;\r
424 }\r
425 \r
426 int FixScancodeMap_restore()\r
427 {\r
428         return update();\r
429 }\r