From a73e54f5d98c74914fc8cd3ef0419cf3df409477 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 14 Sep 2016 22:04:54 +0200 Subject: [run-virt] openslx.exe: Windows NT4.0/2000 compatibility --- remote/modules/run-virt/winres/winres.c | 141 ++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 24 deletions(-) diff --git a/remote/modules/run-virt/winres/winres.c b/remote/modules/run-virt/winres/winres.c index 1c5650b8..dc4d2858 100644 --- a/remote/modules/run-virt/winres/winres.c +++ b/remote/modules/run-virt/winres/winres.c @@ -43,6 +43,7 @@ static const ssize_t KEYLEN = 16; #define SETTINGS_FILE "B:\\OPENSLX.INI" #define SETTINGS_FILE_W L"B:\\OPENSLX.INI" +static HINSTANCE hKernel32, hShell32; static OSVERSIONINFO winVer; static BOOL bGetShares = FALSE; static netdrive_t drives[DRIVEMAX]; @@ -69,6 +70,7 @@ struct { } remap; static BOOL _createMissingRemap = FALSE; +static void setPowerState(); static int setResolution(); static int muteSound(); static int setShutdownText(); @@ -186,27 +188,69 @@ exit_func: bInProc = FALSE; } -static void loadPaths() +typedef HRESULT (*GFPTYPE)(HWND, int, HANDLE, DWORD, wchar_t*); +typedef HRESULT (*GSFTYPE)(HWND, int, ITEMIDLIST**); +typedef BOOL (*ID2PTYPE)(const ITEMIDLIST*, wchar_t*); + +/** + * Load given path (CSIDL). Store in default (must be allocated to hold at least MAX_PATH+1 chars). + * If it could not be retrieved by CSIDL and envName is not NULL, it will be read from the + * environment if possible. + * fallback will be used if everything else fails. + * fallback can be NULL, in which case the fallback is empty. + */ +static void loadPath(wchar_t *dest, int csidl, wchar_t *envName, wchar_t *fallback) { - // Determine a couple of default directories - if (SHGetFolderPathW(HWND_DESKTOP, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, programsPath) != S_OK) { - DWORD ret = GetEnvironmentVariableW(L"ProgramFiles", programsPath, MAX_PATH+1); - if (ret == 0 || ret > MAX_PATH) { - StringCchPrintfW(programsPath, MAX_PATH+1, L"C:\\Program Files"); + if (hShell32 != NULL) { + GFPTYPE aGetFolderPath = (GFPTYPE)GetProcAddress(hShell32, "SHGetFolderPathW"); + if (aGetFolderPath != NULL) { + if ((aGetFolderPath)(HWND_DESKTOP, csidl, NULL, SHGFP_TYPE_CURRENT, dest) == S_OK) + return; } - } - if (SHGetFolderPathW(HWND_DESKTOP, CSIDL_WINDOWS, NULL, SHGFP_TYPE_CURRENT, windowsPath) != S_OK) { - DWORD ret = GetEnvironmentVariableW(L"windir", windowsPath, MAX_PATH+1); - if (ret == 0 || ret > MAX_PATH) { - StringCchPrintfW(windowsPath, MAX_PATH+1, L"C:\\WINDOWS"); + // Fallback + GSFTYPE aGetSpecialFolder = (GSFTYPE)GetProcAddress(hShell32, "SHGetSpecialFolderLocation"); + ID2PTYPE aPathToId = (ID2PTYPE)GetProcAddress(hShell32, "SHGetPathFromIDListW"); + if (aGetSpecialFolder != NULL && aPathToId != NULL) { + ITEMIDLIST *list = NULL; + HRESULT ret1 = (aGetSpecialFolder)(HWND_DESKTOP, csidl, &list); + BOOL ret2 = FALSE; + if (ret1 == 0) { + ret2 = (aPathToId)(list, dest); + } + if (list != NULL) { + CoTaskMemFree(list); + } + if (ret2) + return; } } - if (SHGetFolderPathW(HWND_DESKTOP, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, desktopPath) != S_OK) { - desktopPath[0] = 0; + if (envName != NULL) { + // Fallback + DWORD ret = GetEnvironmentVariableW(envName, dest, MAX_PATH+1); + if (ret > 0 && ret <= MAX_PATH) + return; + } + if (fallback != NULL) { + StringCchPrintfW(programsPath, MAX_PATH+1, fallback); + return; } + *dest = '\0'; +} + +static void loadPaths() +{ + // Determine a couple of default directories + // dest, id, env, fallback + loadPath(programsPath, CSIDL_PROGRAM_FILES, L"ProgramFiles", L"C:\\Program Files"); + loadPath(windowsPath, CSIDL_WINDOWS, L"windir", L"C:\\WINDOWS"); + loadPath(desktopPath, CSIDL_DESKTOPDIRECTORY, NULL, NULL); if (GetTempPathW(MAX_PATH+1, tempPath) == 0) { - tempPath[0] = 0; + DWORD ret = GetEnvironmentVariableW(L"TEMP", tempPath, MAX_PATH+1); + if (ret == 0 || ret > MAX_PATH) { + tempPath[0] = 0; + } } + //wlog(L"Programs: %s, Windows: %s, Desktop: %s, Temp: %s", programsPath, windowsPath, desktopPath, tempPath); StringCchPrintfW(logFile, LOGFILELEN, L"%s\\%s", desktopPath, L"openslx.log"); FILE *tfh = _wfopen(logFile, L"a+"); if (tfh == NULL) { @@ -242,11 +286,20 @@ static void loadPaths() int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { + hKernel32 = LoadLibraryW(L"kernel32.dll"); + if (hKernel32 == NULL) { + alog("Cannot load kernel32.dll"); + } + hShell32 = LoadLibraryW(L"shell32.dll"); + if (hShell32 == NULL) { + alog("Cannot load shell32.dll"); + } winVer.dwOSVersionInfoSize = sizeof(winVer); BOOL retVer = GetVersionEx(&winVer); CoInitialize(NULL); _startTime = GetTickCount(); loadPaths(); + loadPaths(); if (lpCmdLine != NULL && strstr(lpCmdLine, "debug") != NULL) { alog("Windows Version %d.%d", (int)winVer.dwMajorVersion, (int)winVer.dwMinorVersion); } @@ -255,12 +308,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine muteSound(); // Disable screen saver as it might give the false impression that the session is securely locked SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0); - // Disable standby and idle-mode (this is a VM!) - if (winVer.dwMajorVersion >= 6) { // Vista+ - SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_AWAYMODE_REQUIRED); - } else { // XP/2003 - SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); - } + // Same with standby + setPowerState(); // Any network shares to mount? readShareFile(); if (bGetShares || _remapMode != RM_NONE) { @@ -291,6 +340,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine TranslateMessage(&Msg); DispatchMessage(&Msg); } + FreeLibrary(hKernel32); return 0; } @@ -333,6 +383,25 @@ static int execute(wchar_t *path, wchar_t *arguments) return (int)exitCode; } +typedef EXECUTION_STATE (WINAPI *TETYPE)(EXECUTION_STATE); + +static void setPowerState() +{ + // Disable standby and idle-mode (this is a VM!) + if (hKernel32 == NULL || winVer.dwMajorVersion < 5 || (winVer.dwMajorVersion == 5 && winVer.dwMinorVersion < 1)) + return; + TETYPE aExecState = (TETYPE)GetProcAddress(hKernel32, "SetThreadExecutionState"); + if (aExecState == NULL) { + alog("Cannot get SetThreadExecutionState from kernel32.dll"); + return; + } + if (winVer.dwMajorVersion >= 6) { // Vista+ + (aExecState)(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_AWAYMODE_REQUIRED); + } else { // XP/2003 + (aExecState)(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); + } +} + static int setResolution() { int ret; @@ -931,6 +1000,9 @@ static BOOL patchRegPath(BOOL *patchOk, BOOL *anyMapped, HKEY hKey, wchar_t *let return FALSE; } +typedef HANDLE (WINAPI *SNTYPE)(DWORD, DWORD); +typedef BOOL (WINAPI *P32TYPE)(HANDLE, PROCESSENTRY32W*); + static void patchUserPaths(wchar_t *letter) { LONG ret; @@ -989,15 +1061,36 @@ static void patchUserPaths(wchar_t *letter) return; } // Kill explorer + // Late binding + if (hKernel32 == NULL || winVer.dwMajorVersion < 5 || (winVer.dwMajorVersion == 5 && winVer.dwMinorVersion < 1)) { + return; + } + SNTYPE aCreateSnapshot; + P32TYPE aProcessFirst, aProcessNext; + aCreateSnapshot = (SNTYPE)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); + if (aCreateSnapshot == NULL) { + alog("No CreateToolhelp32Snapshot in kernel.dll"); + return; + } + aProcessFirst = (P32TYPE)GetProcAddress(hKernel32, "Process32FirstW"); + if (aProcessFirst == NULL) { + alog("No Process32FirstW in kernel.dll"); + return; + } + aProcessNext = (P32TYPE)GetProcAddress(hKernel32, "Process32NextW"); + if (aProcessNext == NULL) { + alog("No Process32NextW in kernel.dll"); + return; + } PROCESSENTRY32W entry; entry.dwSize = sizeof(PROCESSENTRY32W); - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot != INVALID_HANDLE_VALUE && Process32FirstW(snapshot, &entry)) { + HANDLE snapshot = (aCreateSnapshot)(TH32CS_SNAPPROCESS, 0); + if (snapshot != INVALID_HANDLE_VALUE && (aProcessFirst)(snapshot, &entry)) { do { if (_wcsicmp(entry.szExeFile, L"explorer.exe") == 0) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); if (hProcess == NULL) { - alog("Opening explorer.exe failed"); + alog("Cannot OpenProcess explorer.exe: Remapped paths will not work properly (GetLastError=%d)", (int)GetLastError()); } else { if (TerminateProcess(hProcess, 23)) { killOk = TRUE; @@ -1005,7 +1098,7 @@ static void patchUserPaths(wchar_t *letter) CloseHandle(hProcess); } } - } while (Process32NextW(snapshot, &entry)); + } while ((aProcessNext)(snapshot, &entry)); } else { alog("Could not get process list"); } -- cgit v1.2.3-55-g7522