OSDN Git Service

prototype of UpdatePerUserSystemParameters differ by vista or earlier
[yamy/yamy.git] / fixscancodemap.cpp
index c7ae958..df4665f 100755 (executable)
@@ -5,11 +5,13 @@
 #include <tlhelp32.h>\r
 \r
 #pragma runtime_checks( "", off )\r
-static DWORD invokeFunc(InjectInfo *info)\r
+static DWORD WINAPI invokeFunc(InjectInfo *info)\r
 {\r
        BOOL ret;\r
        HANDLE hToken;\r
        HMODULE hAdvapi32;\r
+       DWORD result = 0;\r
+\r
        FpImpersonateLoggedOnUser pImpersonateLoggedOnUser;\r
        FpRevertToSelf pRevertToSelf;\r
        FpOpenProcessToken pOpenProcessToken;\r
@@ -22,29 +24,44 @@ static DWORD invokeFunc(InjectInfo *info)
 \r
        HANDLE hProcess = info->pOpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info->pid_);\r
        if (hProcess == NULL) {\r
-               return 1;\r
+               result = 1;\r
+               goto exit;\r
        }\r
 \r
        ret = pOpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE , &hToken);\r
        if (ret == FALSE) {\r
-               return 2;\r
+               result = 2;\r
+               goto exit;\r
        }\r
 \r
        ret = pImpersonateLoggedOnUser(hToken);\r
        if (ret == FALSE) {\r
-               return 3;\r
+               result = 3;\r
+               goto exit;\r
        }\r
 \r
-       info->pUpdate(0, 1);\r
+       if (info->isVistaOrLater_) {\r
+               info->pUpdate4(1);\r
+       } else {\r
+               info->pUpdate8(0, 1);\r
+       }\r
 \r
        ret = pRevertToSelf();\r
        if (ret == FALSE) {\r
-               return 4;\r
+               result = 4;\r
+               goto exit;\r
+       }\r
+\r
+exit:\r
+       if (hToken != NULL) {\r
+               info->pCloseHandle(hToken);\r
+       }\r
+\r
+       if (hProcess != NULL) {\r
+               info->pCloseHandle(hProcess);\r
        }\r
 \r
-       info->pCloseHandle(hToken);\r
-       info->pCloseHandle(hProcess);\r
-       return 0;\r
+       return result;\r
 }\r
 static int afterFunc(int arg)\r
 {\r
@@ -61,7 +78,7 @@ const DWORD FixScancodeMap::s_fixEntry[] = {
        0x003ae03a,\r
        0x0029e029,\r
        0x0070e070,\r
-       0x003b001e,\r
+       0x007be07b,\r
 };\r
 \r
 int FixScancodeMap::acquirePrivileges()\r
@@ -117,7 +134,7 @@ DWORD FixScancodeMap::getWinLogonPid()
 \r
     BOOL bResult = Process32First(hSnap, &pe);\r
        while (bResult){\r
-               if (!_tcscmp(pe.szExeFile, _T("winlogon.exe"))) {\r
+               if (!_tcsicmp(pe.szExeFile, _T("winlogon.exe"))) {\r
                        DWORD sessionId;\r
 \r
                        if (ProcessIdToSessionId(pe.th32ProcessID, &sessionId) != FALSE) {\r
@@ -135,37 +152,34 @@ DWORD FixScancodeMap::getWinLogonPid()
 }\r
 \r
 \r
-int FixScancodeMap::clean()\r
+bool FixScancodeMap::clean(WlInfo wl)\r
 {\r
        int ret = 0;\r
 \r
-       if (WaitForSingleObject(m_hThread, 5000) == WAIT_TIMEOUT) {\r
-               ret = 15;\r
-               goto dirty_exit;\r
-       }\r
-       DWORD result = -1;\r
-       GetExitCodeThread(m_hThread, &result);\r
-       ret = result;\r
-       CloseHandle(m_hThread);\r
-       m_hThread = NULL;\r
+       if (wl.m_hThread != NULL) {\r
+               DWORD result;\r
 \r
-       if (m_remoteMem != NULL && m_hProcess != NULL) {\r
-               VirtualFreeEx(m_hProcess, m_remoteMem, 0, MEM_RELEASE);\r
-               m_remoteMem = NULL;\r
-       }\r
+               if (WaitForSingleObject(wl.m_hThread, 5000) == WAIT_TIMEOUT) {\r
+                       return false;\r
+               }\r
 \r
-       if (m_remoteInfo != NULL && m_hProcess != NULL) {\r
-               VirtualFreeEx(m_hProcess, m_remoteInfo, 0, MEM_RELEASE);\r
-               m_remoteInfo = NULL;\r
-       }\r
+               GetExitCodeThread(wl.m_hThread, &result);\r
+               CloseHandle(wl.m_hThread);\r
 \r
-       if (m_hProcess != NULL) {\r
-               CloseHandle(m_hProcess);\r
-               m_hProcess = NULL;\r
+               if (wl.m_remoteMem != NULL && wl.m_hProcess != NULL) {\r
+                       VirtualFreeEx(wl.m_hProcess, wl.m_remoteMem, 0, MEM_RELEASE);\r
+               }\r
+\r
+               if (wl.m_remoteInfo != NULL && wl.m_hProcess != NULL) {\r
+                       VirtualFreeEx(wl.m_hProcess, wl.m_remoteInfo, 0, MEM_RELEASE);\r
+               }\r
+\r
+               if (wl.m_hProcess != NULL) {\r
+                       CloseHandle(wl.m_hProcess);\r
+               }\r
        }\r
 \r
-dirty_exit:\r
-       return ret;\r
+       return true;\r
 }\r
 \r
 \r
@@ -174,44 +188,43 @@ int FixScancodeMap::injectThread(DWORD dwPID)
        int ret = 0;\r
        DWORD err = 0;\r
        BOOL wFlag;\r
+       WlInfo wi;\r
+\r
+       wi.m_hProcess = NULL;\r
+       wi.m_remoteMem = NULL;\r
+       wi.m_remoteInfo = NULL;\r
+       wi.m_hThread = NULL;\r
 \r
        DWORD invokeFuncAddr = (DWORD)invokeFunc;\r
        DWORD afterFuncAddr = (DWORD)afterFunc;\r
        DWORD memSize =  afterFuncAddr - invokeFuncAddr;\r
 \r
-       if (m_hThread != NULL) {\r
-               ret = clean();\r
-               if (ret) {\r
-                       return ret;\r
-               }\r
-       }\r
-\r
-       if ((m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) {\r
+       if ((wi.m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) {\r
                ret = 8;\r
                goto exit;\r
        }\r
 \r
-       m_remoteMem = VirtualAllocEx(m_hProcess, NULL, memSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
-       if (m_remoteMem == NULL) {\r
+       wi.m_remoteMem = VirtualAllocEx(wi.m_hProcess, NULL, memSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
+       if (wi.m_remoteMem == NULL) {\r
                ret = 9;\r
                err = GetLastError();\r
                goto exit;\r
        }\r
 \r
-       wFlag = WriteProcessMemory(m_hProcess, m_remoteMem, (char*)invokeFunc, memSize, (SIZE_T*)0);\r
+       wFlag = WriteProcessMemory(wi.m_hProcess, wi.m_remoteMem, (char*)invokeFunc, memSize, (SIZE_T*)0);\r
        if (wFlag == FALSE) {\r
                ret = 10;\r
                goto exit;\r
        }\r
 \r
-       m_remoteInfo = VirtualAllocEx(m_hProcess, NULL, sizeof(m_info), MEM_COMMIT, PAGE_READWRITE);\r
-       if (m_remoteInfo == NULL) {\r
+       wi.m_remoteInfo = VirtualAllocEx(wi.m_hProcess, NULL, sizeof(m_info), MEM_COMMIT, PAGE_READWRITE);\r
+       if (wi.m_remoteInfo == NULL) {\r
                ret = 11;\r
                err = GetLastError();\r
                goto exit;\r
        }\r
 \r
-       wFlag = WriteProcessMemory(m_hProcess, m_remoteInfo, (char*)&m_info, sizeof(m_info), (SIZE_T*)0);\r
+       wFlag = WriteProcessMemory(wi.m_hProcess, wi.m_remoteInfo, (char*)&m_info, sizeof(m_info), (SIZE_T*)0);\r
        if (wFlag == FALSE) {\r
                ret = 12;\r
                goto exit;\r
@@ -234,37 +247,38 @@ int FixScancodeMap::injectThread(DWORD dwPID)
        }\r
 #endif\r
 \r
-       m_hThread = CreateRemoteThread(m_hProcess, NULL, 0, \r
-               (LPTHREAD_START_ROUTINE)m_remoteMem, m_remoteInfo, 0, NULL);\r
-       if (m_hThread == NULL) {\r
+       wi.m_hThread = CreateRemoteThread(wi.m_hProcess, NULL, 0, \r
+               (LPTHREAD_START_ROUTINE)wi.m_remoteMem, wi.m_remoteInfo, 0, NULL);\r
+       if (wi.m_hThread == NULL) {\r
                ret = 13;\r
                goto exit;\r
        }\r
 \r
-       if (WaitForSingleObject(m_hThread, 5000) == WAIT_TIMEOUT) {\r
+       if (WaitForSingleObject(wi.m_hThread, 5000) == WAIT_TIMEOUT) {\r
                ret = 14;\r
+               m_wlTrash.push_back(wi);\r
                goto dirty_exit;\r
        }\r
        DWORD result = -1;\r
-       GetExitCodeThread(m_hThread, &result);\r
+       GetExitCodeThread(wi.m_hThread, &result);\r
        ret = result;\r
-       CloseHandle(m_hThread);\r
-       m_hThread = NULL;\r
+       CloseHandle(wi.m_hThread);\r
+       wi.m_hThread = NULL;\r
 \r
 exit:\r
-       if (m_remoteMem != NULL && m_hProcess != NULL) {\r
-               VirtualFreeEx(m_hProcess, m_remoteMem, 0, MEM_RELEASE);\r
-               m_remoteMem = NULL;\r
+       if (wi.m_remoteMem != NULL && wi.m_hProcess != NULL) {\r
+               VirtualFreeEx(wi.m_hProcess, wi.m_remoteMem, 0, MEM_RELEASE);\r
+               wi.m_remoteMem = NULL;\r
        }\r
 \r
-       if (m_remoteInfo != NULL && m_hProcess != NULL) {\r
-               VirtualFreeEx(m_hProcess, m_remoteInfo, 0, MEM_RELEASE);\r
-               m_remoteInfo = NULL;\r
+       if (wi.m_remoteInfo != NULL && wi.m_hProcess != NULL) {\r
+               VirtualFreeEx(wi.m_hProcess, wi.m_remoteInfo, 0, MEM_RELEASE);\r
+               wi.m_remoteInfo = NULL;\r
        }\r
 \r
-       if (m_hProcess != NULL) {\r
-               CloseHandle(m_hProcess);\r
-               m_hProcess = NULL;\r
+       if (wi.m_hProcess != NULL) {\r
+               CloseHandle(wi.m_hProcess);\r
+               wi.m_hProcess = NULL;\r
        }\r
 \r
 dirty_exit:\r
@@ -276,24 +290,24 @@ int FixScancodeMap::update()
        MINIMIZEDMETRICS mm;\r
        int result = 0;\r
 \r
-       result = acquirePrivileges();\r
-       if (result) {\r
+       if (m_errorOnConstruct) {\r
+               result = m_errorOnConstruct;\r
                goto exit;\r
        }\r
 \r
-       DWORD dwPID;\r
-       if ((dwPID = getWinLogonPid()) == 0) {\r
-               result = 15;\r
-               goto exit;\r
-       }\r
+       m_wlTrash.erase(remove_if(m_wlTrash.begin(), m_wlTrash.end(), FixScancodeMap::clean), m_wlTrash.end());\r
 \r
        memset(&mm, 0, sizeof(mm));\r
        mm.cbSize = sizeof(mm);\r
        SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);\r
 \r
-       result = injectThread(dwPID);\r
-       if (result && m_hThread == NULL) {\r
-               goto exit;\r
+       result = injectThread(m_winlogonPid);\r
+       if (result == 14) {\r
+               // retry once\r
+               result = injectThread(m_winlogonPid);\r
+               if (result == 0) {\r
+                       result = 22;\r
+               }\r
        }\r
 \r
        SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0);\r
@@ -406,10 +420,8 @@ int FixScancodeMap::restore()
 }\r
 \r
 FixScancodeMap::FixScancodeMap() :\r
-       m_hProcess(NULL),\r
-       m_remoteMem(NULL),\r
-       m_remoteInfo(NULL),\r
-       m_hThread(NULL),\r
+       m_errorOnConstruct(0),\r
+       m_winlogonPid(0),\r
        m_regHKCU(HKEY_CURRENT_USER, _T("Keyboard Layout")),\r
        m_regHKLM(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout")),\r
        m_pReg(NULL)\r
@@ -425,8 +437,9 @@ FixScancodeMap::FixScancodeMap() :
 \r
        hMod = GetModuleHandle(_T("user32.dll"));\r
        if (hMod != NULL) {\r
-               m_info.pUpdate = (FpUpdatePerUserSystemParameters)GetProcAddress(hMod, "UpdatePerUserSystemParameters");\r
-               if (m_info.pUpdate == NULL) {\r
+               m_info.pUpdate4 = (FpUpdatePerUserSystemParameters4)GetProcAddress(hMod, "UpdatePerUserSystemParameters");\r
+               m_info.pUpdate8 = (FpUpdatePerUserSystemParameters8)m_info.pUpdate4;\r
+               if (m_info.pUpdate4 == NULL) {\r
                        return;\r
                }\r
        }\r
@@ -460,6 +473,26 @@ FixScancodeMap::FixScancodeMap() :
        } else {\r
                m_pReg = &m_regHKLM; // Windows7 or later\r
        }\r
+\r
+       // prototype of UpdatePerUserSystemParameters() differ vista or earlier\r
+       if (checkWindowsVersion(6, 0) == FALSE) {\r
+               m_info.isVistaOrLater_ = 0; // before Vista\r
+       } else {\r
+               m_info.isVistaOrLater_ = 1; // Vista or later\r
+       }\r
+\r
+       m_errorOnConstruct = acquirePrivileges();\r
+       if (m_errorOnConstruct) {\r
+               goto exit;\r
+       }\r
+\r
+       if ((m_winlogonPid = getWinLogonPid()) == 0) {\r
+               m_errorOnConstruct = 15;\r
+               goto exit;\r
+       }\r
+\r
+exit:\r
+       ;\r
 }\r
 \r
 FixScancodeMap::~FixScancodeMap()\r