1 #include "fixscancodemap.h"
\r
3 #include "windowstool.h"
\r
5 #include <tlhelp32.h>
\r
8 #pragma runtime_checks( "", off )
\r
9 static DWORD WINAPI invokeFunc(InjectInfo *info)
\r
16 FpImpersonateLoggedOnUser pImpersonateLoggedOnUser;
\r
17 FpRevertToSelf pRevertToSelf;
\r
18 FpOpenProcessToken pOpenProcessToken;
\r
20 hAdvapi32 = info->pGetModuleHandle(info->advapi32_);
\r
22 pImpersonateLoggedOnUser = (FpImpersonateLoggedOnUser)info->pGetProcAddress(hAdvapi32, info->impersonateLoggedOnUser_);
\r
23 pRevertToSelf = (FpRevertToSelf)info->pGetProcAddress(hAdvapi32, info->revertToSelf_);
\r
24 pOpenProcessToken = (FpOpenProcessToken)info->pGetProcAddress(hAdvapi32, info->openProcessToken_);
\r
26 HANDLE hProcess = info->pOpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info->pid_);
\r
27 if (hProcess == NULL) {
\r
28 result = YAMY_ERROR_ON_OPEN_YAMY_PROCESS;
\r
32 ret = pOpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE , &hToken);
\r
34 result = YAMY_ERROR_ON_OPEN_YAMY_TOKEN;
\r
38 ret = pImpersonateLoggedOnUser(hToken);
\r
40 result = YAMY_ERROR_ON_IMPERSONATE;
\r
44 if (info->isVistaOrLater_) {
\r
47 info->pUpdate8(0, 1);
\r
50 ret = pRevertToSelf();
\r
52 result = YAMY_ERROR_ON_REVERT_TO_SELF;
\r
57 if (hToken != NULL) {
\r
58 info->pCloseHandle(hToken);
\r
61 if (hProcess != NULL) {
\r
62 info->pCloseHandle(hProcess);
\r
67 static int afterFunc(int arg)
\r
70 // if this function empty, optimizer unify this with other empty functions.
\r
71 // following code avoid it.
\r
72 arg *= 710810; // non-sense operation
\r
75 #pragma runtime_checks( "", restore )
\r
77 const DWORD FixScancodeMap::s_fixEntryNum = 4;
\r
78 const DWORD FixScancodeMap::s_fixEntry[] = {
\r
85 int FixScancodeMap::acquirePrivileges()
\r
88 HANDLE hToken = NULL;
\r
90 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
\r
91 ret = YAMY_ERROR_ON_OPEN_CURRENT_PROCESS;
\r
96 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
\r
97 ret = YAMY_ERROR_ON_LOOKUP_PRIVILEGE;
\r
101 TOKEN_PRIVILEGES tk_priv;
\r
102 tk_priv.PrivilegeCount = 1;
\r
103 tk_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
\r
104 tk_priv.Privileges[0].Luid = luid;
\r
106 if (!AdjustTokenPrivileges(hToken, FALSE, &tk_priv, 0, NULL, NULL)) {
\r
107 ret = YAMY_ERROR_ON_ADJUST_PRIVILEGE;
\r
112 if (hToken != NULL) {
\r
113 CloseHandle(hToken);
\r
119 DWORD FixScancodeMap::getWinLogonPid()
\r
122 DWORD mySessionId = 0;
\r
124 if (ProcessIdToSessionId(GetCurrentProcessId(), &mySessionId) == FALSE) {
\r
128 HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
\r
129 if (hSnap == INVALID_HANDLE_VALUE) {
\r
134 pe.dwSize = sizeof(pe);
\r
136 BOOL bResult = Process32First(hSnap, &pe);
\r
138 if (!_tcsicmp(pe.szExeFile, _T("winlogon.exe"))) {
\r
141 if (ProcessIdToSessionId(pe.th32ProcessID, &sessionId) != FALSE) {
\r
142 if (sessionId == mySessionId) {
\r
143 pid = pe.th32ProcessID;
\r
148 bResult = Process32Next(hSnap, &pe);
\r
151 CloseHandle(hSnap);
\r
156 bool FixScancodeMap::clean(WlInfo wl)
\r
160 if (wl.m_hThread != NULL) {
\r
163 if (WaitForSingleObject(wl.m_hThread, 5000) == WAIT_TIMEOUT) {
\r
167 GetExitCodeThread(wl.m_hThread, &result);
\r
168 CloseHandle(wl.m_hThread);
\r
170 if (wl.m_remoteMem != NULL && wl.m_hProcess != NULL) {
\r
171 VirtualFreeEx(wl.m_hProcess, wl.m_remoteMem, 0, MEM_RELEASE);
\r
174 if (wl.m_remoteInfo != NULL && wl.m_hProcess != NULL) {
\r
175 VirtualFreeEx(wl.m_hProcess, wl.m_remoteInfo, 0, MEM_RELEASE);
\r
178 if (wl.m_hProcess != NULL) {
\r
179 CloseHandle(wl.m_hProcess);
\r
187 int FixScancodeMap::injectThread(DWORD dwPID)
\r
194 wi.m_hProcess = NULL;
\r
195 wi.m_remoteMem = NULL;
\r
196 wi.m_remoteInfo = NULL;
\r
197 wi.m_hThread = NULL;
\r
199 ULONG_PTR invokeFuncAddr = (ULONG_PTR)invokeFunc;
\r
200 ULONG_PTR afterFuncAddr = (ULONG_PTR)afterFunc;
\r
201 SIZE_T memSize = afterFuncAddr - invokeFuncAddr;
\r
203 if ((wi.m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) {
\r
204 ret = YAMY_ERROR_ON_OPEN_WINLOGON_PROCESS;
\r
208 wi.m_remoteMem = VirtualAllocEx(wi.m_hProcess, NULL, memSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
\r
209 if (wi.m_remoteMem == NULL) {
\r
210 ret = YAMY_ERROR_ON_VIRTUALALLOCEX;
\r
211 err = GetLastError();
\r
215 wFlag = WriteProcessMemory(wi.m_hProcess, wi.m_remoteMem, (char*)invokeFunc, memSize, (SIZE_T*)0);
\r
216 if (wFlag == FALSE) {
\r
217 ret = YAMY_ERROR_ON_WRITEPROCESSMEMORY;
\r
221 wi.m_remoteInfo = VirtualAllocEx(wi.m_hProcess, NULL, sizeof(m_info), MEM_COMMIT, PAGE_READWRITE);
\r
222 if (wi.m_remoteInfo == NULL) {
\r
223 ret = YAMY_ERROR_ON_VIRTUALALLOCEX;
\r
224 err = GetLastError();
\r
228 wFlag = WriteProcessMemory(wi.m_hProcess, wi.m_remoteInfo, (char*)&m_info, sizeof(m_info), (SIZE_T*)0);
\r
229 if (wFlag == FALSE) {
\r
230 ret = YAMY_ERROR_ON_WRITEPROCESSMEMORY;
\r
234 wi.m_hThread = CreateRemoteThread(wi.m_hProcess, NULL, 0,
\r
235 (LPTHREAD_START_ROUTINE)wi.m_remoteMem, wi.m_remoteInfo, 0, NULL);
\r
236 if (wi.m_hThread == NULL) {
\r
237 ret = YAMY_ERROR_ON_CREATEREMOTETHREAD;
\r
241 if (WaitForSingleObject(wi.m_hThread, 5000) == WAIT_TIMEOUT) {
\r
242 ret = YAMY_ERROR_TIMEOUT_INJECTION;
\r
243 m_wlTrash.push_back(wi);
\r
247 GetExitCodeThread(wi.m_hThread, &result);
\r
249 CloseHandle(wi.m_hThread);
\r
250 wi.m_hThread = NULL;
\r
253 if (wi.m_remoteMem != NULL && wi.m_hProcess != NULL) {
\r
254 VirtualFreeEx(wi.m_hProcess, wi.m_remoteMem, 0, MEM_RELEASE);
\r
255 wi.m_remoteMem = NULL;
\r
258 if (wi.m_remoteInfo != NULL && wi.m_hProcess != NULL) {
\r
259 VirtualFreeEx(wi.m_hProcess, wi.m_remoteInfo, 0, MEM_RELEASE);
\r
260 wi.m_remoteInfo = NULL;
\r
263 if (wi.m_hProcess != NULL) {
\r
264 CloseHandle(wi.m_hProcess);
\r
265 wi.m_hProcess = NULL;
\r
272 int FixScancodeMap::update()
\r
274 MINIMIZEDMETRICS mm;
\r
277 if (m_errorOnConstruct) {
\r
278 result = m_errorOnConstruct;
\r
282 m_wlTrash.erase(remove_if(m_wlTrash.begin(), m_wlTrash.end(), FixScancodeMap::clean), m_wlTrash.end());
\r
284 memset(&mm, 0, sizeof(mm));
\r
285 mm.cbSize = sizeof(mm);
\r
286 SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);
\r
288 result = injectThread(m_winlogonPid);
\r
289 if (result == YAMY_ERROR_TIMEOUT_INJECTION) {
\r
291 result = injectThread(m_winlogonPid);
\r
292 if (result == YAMY_SUCCESS) {
\r
293 result = YAMY_ERROR_RETRY_INJECTION_SUCCESS;
\r
297 mm.iArrange = ARW_HIDE;
\r
298 SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);
\r
304 int FixScancodeMap::fix()
\r
306 ScancodeMap *origMap, *fixMap;
\r
307 DWORD origSize, fixSize;
\r
311 // save original Scancode Map
\r
312 ret = m_pReg->read(_T("Scancode Map"), NULL, &origSize, NULL, 0);
\r
314 origMap = reinterpret_cast<ScancodeMap*>(malloc(origSize));
\r
315 if (origMap == NULL) {
\r
316 result = YAMY_ERROR_NO_MEMORY;
\r
320 ret = m_pReg->read(_T("Scancode Map"), reinterpret_cast<BYTE*>(origMap), &origSize, NULL, 0);
\r
321 if (ret == false) {
\r
322 result = YAMY_ERROR_ON_READ_SCANCODE_MAP;
\r
326 fixSize = origSize;
\r
327 fixMap = reinterpret_cast<ScancodeMap*>(malloc(origSize + s_fixEntryNum * sizeof(s_fixEntry[0])));
\r
328 if (fixMap == NULL) {
\r
329 result = YAMY_ERROR_NO_MEMORY;
\r
333 memcpy_s(fixMap, origSize + s_fixEntryNum, origMap, origSize);
\r
338 fixSize = sizeof(ScancodeMap);
\r
339 fixMap = reinterpret_cast<ScancodeMap*>(malloc(sizeof(ScancodeMap) + s_fixEntryNum * sizeof(s_fixEntry[0])));
\r
340 if (fixMap == NULL) {
\r
341 result = YAMY_ERROR_NO_MEMORY;
\r
345 fixMap->header1 = 0;
\r
346 fixMap->header2 = 0;
\r
348 fixMap->entry[0] = 0;
\r
351 for (DWORD i = 0; i < s_fixEntryNum; i++) {
\r
355 for (DWORD j = 0; j < origMap->count; j++) {
\r
356 if (HIWORD(s_fixEntry[i]) == HIWORD(origMap->entry[j])) {
\r
363 // s_fixEntry[i] found in original Scancode Map, so don't fix it
\r
367 // add fix entry to fixMap
\r
368 fixMap->entry[fixMap->count - 1] = s_fixEntry[i];
\r
369 fixMap->entry[fixMap->count] = 0;
\r
374 ret = m_pReg->write(_T("Scancode Map"), reinterpret_cast<BYTE*>(fixMap), fixSize);
\r
375 if (ret == false) {
\r
376 result = YAMY_ERROR_ON_WRITE_SCANCODE_MAP;
\r
383 ret = m_pReg->write(_T("Scancode Map"), reinterpret_cast<BYTE*>(origMap), origSize);
\r
385 ret = m_pReg->remove(_T("Scancode Map"));
\r
387 if (ret == false) {
\r
388 result = YAMY_ERROR_ON_WRITE_SCANCODE_MAP;
\r
402 int FixScancodeMap::restore()
\r
407 int FixScancodeMap::escape(bool i_escape)
\r
410 SetEvent(m_hFixEvent);
\r
412 SetEvent(m_hRestoreEvent);
\r
417 unsigned int WINAPI FixScancodeMap::threadLoop(void *i_this)
\r
421 FixScancodeMap *This = reinterpret_cast<FixScancodeMap*>(i_this);
\r
422 HANDLE handles[] = {This->m_hFixEvent, This->m_hRestoreEvent, This->m_hQuitEvent};
\r
423 while ((ret = MsgWaitForMultipleObjects(NUMBER_OF(handles), &handles[0],
\r
424 FALSE, INFINITE, QS_POSTMESSAGE)) != WAIT_FAILED) {
\r
426 case WAIT_OBJECT_0: // m_hFixEvent
\r
427 ResetEvent(This->m_hFixEvent);
\r
429 PostMessage(This->m_hwnd, This->m_messageOnFail, err, 1);
\r
431 case WAIT_OBJECT_0 + 1: // m_hRestoreEvent
\r
432 ResetEvent(This->m_hRestoreEvent);
\r
433 err = This->restore();
\r
434 PostMessage(This->m_hwnd, This->m_messageOnFail, err, 0);
\r
436 case WAIT_OBJECT_0 + 2: // m_hQuiteEvent
\r
437 ResetEvent(This->m_hQuitEvent);
\r
447 int FixScancodeMap::init(HWND i_hwnd, UINT i_messageOnFail)
\r
450 m_messageOnFail = i_messageOnFail;
\r
454 FixScancodeMap::FixScancodeMap() :
\r
456 m_messageOnFail(WM_NULL),
\r
457 m_errorOnConstruct(0),
\r
459 m_regHKCU(HKEY_CURRENT_USER, _T("Keyboard Layout")),
\r
460 m_regHKLM(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout")),
\r
465 m_info.pid_ = GetCurrentProcessId();
\r
467 memcpy(&m_info.advapi32_, _T("advapi32.dll"), sizeof(m_info.advapi32_));
\r
468 memcpy(&m_info.impersonateLoggedOnUser_, "ImpersonateLoggedOnUser", sizeof(m_info.impersonateLoggedOnUser_));
\r
469 memcpy(&m_info.revertToSelf_, "RevertToSelf", sizeof(m_info.revertToSelf_));
\r
470 memcpy(&m_info.openProcessToken_, "OpenProcessToken", sizeof(m_info.openProcessToken_));
\r
472 m_hFixEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
\r
473 ASSERT(m_hFixEvent);
\r
474 m_hRestoreEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
\r
475 ASSERT(m_hRestoreEvent);
\r
476 m_hQuitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
\r
477 ASSERT(m_hQuitEvent);
\r
479 m_hThread = (HANDLE)_beginthreadex(NULL, 0, threadLoop, this, 0, &m_threadId);
\r
481 hMod = GetModuleHandle(_T("user32.dll"));
\r
482 if (hMod != NULL) {
\r
483 m_info.pUpdate4 = (FpUpdatePerUserSystemParameters4)GetProcAddress(hMod, "UpdatePerUserSystemParameters");
\r
484 m_info.pUpdate8 = (FpUpdatePerUserSystemParameters8)m_info.pUpdate4;
\r
485 if (m_info.pUpdate4 == NULL) {
\r
490 hMod = GetModuleHandle(_T("kernel32.dll"));
\r
491 if (hMod != NULL) {
\r
492 m_info.pGetModuleHandle = (FpGetModuleHandleW)GetProcAddress(hMod, "GetModuleHandleW");
\r
493 if (m_info.pGetModuleHandle == NULL) {
\r
497 m_info.pGetProcAddress = (FpGetProcAddress)GetProcAddress(hMod, "GetProcAddress");
\r
498 if (m_info.pGetProcAddress == NULL) {
\r
502 m_info.pOpenProcess = (FpOpenProcess)GetProcAddress(hMod, "OpenProcess");
\r
503 if (m_info.pOpenProcess == NULL) {
\r
507 m_info.pCloseHandle = (FpCloseHandle)GetProcAddress(hMod, "CloseHandle");
\r
508 if (m_info.pCloseHandle == NULL) {
\r
513 // Windows7 RC not support Scancode Map on HKCU?
\r
514 if (checkWindowsVersion(6, 1) == FALSE) {
\r
515 m_pReg = &m_regHKCU; // Vista or earlier
\r
517 m_pReg = &m_regHKLM; // Windows7 or later
\r
520 // prototype of UpdatePerUserSystemParameters() differ vista or earlier
\r
521 if (checkWindowsVersion(6, 0) == FALSE) {
\r
522 m_info.isVistaOrLater_ = 0; // before Vista
\r
524 m_info.isVistaOrLater_ = 1; // Vista or later
\r
527 m_errorOnConstruct = acquirePrivileges();
\r
528 if (m_errorOnConstruct) {
\r
532 if ((m_winlogonPid = getWinLogonPid()) == 0) {
\r
533 m_errorOnConstruct = YAMY_ERROR_ON_GET_WINLOGON_PID;
\r
541 FixScancodeMap::~FixScancodeMap()
\r
543 SetEvent(m_hQuitEvent);
\r
544 WaitForSingleObject(m_hThread, INFINITE);
\r