OSDN Git Service

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