diff options
Diffstat (limited to 'remote/modules/run-virt/winres/winres.c')
-rw-r--r-- | remote/modules/run-virt/winres/winres.c | 209 |
1 files changed, 179 insertions, 30 deletions
diff --git a/remote/modules/run-virt/winres/winres.c b/remote/modules/run-virt/winres/winres.c index 1c5650b8..44654161 100644 --- a/remote/modules/run-virt/winres/winres.c +++ b/remote/modules/run-virt/winres/winres.c @@ -4,6 +4,7 @@ #define WIN32_LEAN_AND_MEAN #define _UNICODE #define UNICODE +#define NO_SHLWAPI_STRFCNS #include <windows.h> #include <winsock2.h> #include <winnetwk.h> @@ -21,6 +22,8 @@ #include <shlguid.h> #include <strsafe.h> #include <tlhelp32.h> +#include <shlwapi.h> +#include <shellapi.h> DEFINE_GUID(ID_IAudioEndpointVolume, 0x5CDF2C82, 0x841E, 0x4546, 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A); DEFINE_GUID(ID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6); @@ -30,6 +33,7 @@ DEFINE_GUID(ID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, typedef struct { const char* path; + const char* pathIp; const char* letter; const char* shortcut; const char* user; @@ -43,6 +47,9 @@ static const ssize_t KEYLEN = 16; #define SETTINGS_FILE "B:\\OPENSLX.INI" #define SETTINGS_FILE_W L"B:\\OPENSLX.INI" +static BOOL _debug = FALSE; + +static HINSTANCE hKernel32, hShell32; static OSVERSIONINFO winVer; static BOOL bGetShares = FALSE; static netdrive_t drives[DRIVEMAX]; @@ -60,6 +67,9 @@ static int _folderStatus = FS_UNKNOWN; // -1 = Not handled yet, 0 = patching fai static int _remapMode = RM_NONE; static const char* _remapHomeDrive = NULL; +#define SCRIPTFILELEN (50) +char _scriptFile[SCRIPTFILELEN]; + struct { BOOL documents; BOOL downloads; @@ -69,6 +79,7 @@ struct { } remap; static BOOL _createMissingRemap = FALSE; +static void setPowerState(); static int setResolution(); static int muteSound(); static int setShutdownText(); @@ -186,27 +197,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) { @@ -238,16 +291,28 @@ static void loadPaths() buffer[1] = ':'; buffer[2] = '\0'; _remapHomeDrive = strdup(buffer); + // Get extension for autorun script + GetPrivateProfileStringA("openslx", "scriptExt", "", buffer, sizeof(buffer), SETTINGS_FILE); + StringCchPrintfA(_scriptFile, SCRIPTFILELEN, "B:\\runscript%s", buffer); } 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); + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); _startTime = GetTickCount(); loadPaths(); if (lpCmdLine != NULL && strstr(lpCmdLine, "debug") != NULL) { + _debug = TRUE; alog("Windows Version %d.%d", (int)winVer.dwMajorVersion, (int)winVer.dwMinorVersion); } // Mute sound by default @@ -255,12 +320,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) { @@ -285,12 +346,18 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine alog("Could not create timer for resolution setting: %d", (int)GetLastError()); } } + // Runscript (if any) + if (PathFileExistsA(_scriptFile)) { + ShellExecuteA(NULL, "open", _scriptFile, NULL, "B:\\", SW_SHOWNORMAL); + } // Message pump MSG Msg; while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } + FreeLibrary(hKernel32); + FreeLibrary(hShell32); return 0; } @@ -333,6 +400,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; @@ -482,6 +568,37 @@ static char* getToken(char **ptr, BOOL doDup) return dest; } +const char* uncReplaceFqdnByIp(const char* path) +{ + if (path == NULL || path[0] != '\\' || path[1] != '\\') + return NULL; + const char *host = path + 2; + const char *rest = strchr(host, '\\'); + if (rest == NULL || rest - host >= 200) + return NULL; + char name[201]; + strncpy(name, host, rest - host); + name[rest-host] = '\0'; + if (_debug) { + alog("Trying to resolve '%s'...", name); + } + struct hostent *remote = gethostbyname(name); + if (remote == NULL || remote->h_addrtype != AF_INET || remote->h_addr_list[0] == 0) + return NULL; + struct in_addr addr; + addr.s_addr = *(u_long*)remote->h_addr_list[0]; + char *ip = inet_ntoa(addr); + if (ip == NULL) + return NULL; + size_t len = 2 /* \\ */ + strlen(ip) /* 1.2.3.4 */ + strlen(rest) /* \path\to\share */ + 1 /* nullchar */; + char *retval = malloc(len); + snprintf(retval, len, "\\\\%s%s", ip, rest); + if (_debug) { + alog("Turned '%s' into '%s'", path, retval); + } + return retval; +} + #define FREENULL(x) do { free((void*)(x)); (x) = NULL; } while (0) static void readShareFile() @@ -513,6 +630,9 @@ static void readShareFile() if (d->path == NULL || d->path[0] == '\0') goto drive_fail; d->success = FALSE; + // Hack: For unknown reasons, with some servers mounting fails using a fqdn, but using the ip address instead succeeds. + d->pathIp = uncReplaceFqdnByIp(d->path); + // idx++; continue; drive_fail: @@ -667,11 +787,14 @@ static void postSuccessfulMount(const netdrive_t *d, wchar_t *letter) } } -static BOOL mountNetworkShare(const netdrive_t *d) +static BOOL mountNetworkShare(const netdrive_t *d, BOOL useIp) { wchar_t path[BUFLEN] = L"", user[BUFLEN] = L"", pass[BUFLEN] = L"", letter[10] = L"", shortcut[BUFLEN] = L""; int ok = -1; - ok &= MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)d->path, -1, (LPWSTR)path, BUFLEN) > 0; + if (useIp && d->pathIp[0] == '\0') + return FALSE; + const char *uncPath = useIp ? d->pathIp : d->path; + ok &= MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)uncPath, -1, (LPWSTR)path, BUFLEN) > 0; if (d->letter != NULL) { ok &= MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)d->letter, -1, (LPWSTR)letter, 10) > 0; } @@ -685,7 +808,7 @@ static BOOL mountNetworkShare(const netdrive_t *d) ok &= MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)d->shortcut, -1, (LPWSTR)shortcut, BUFLEN) > 0; } if (!ok || path[0] == 0) { // Convert failed/no path - return true anyways since retrying wouldn't change anything - alog("mountNetworkShare: utf8 to utf16 failed, or path empty (src: '%s')", d->path); + alog("mountNetworkShare: utf8 to utf16 failed, or path empty (src: '%s')", uncPath); return TRUE; } DWORD retval; @@ -744,7 +867,9 @@ static BOOL mountNetworkShares() break; if (drives[i].success) continue; - if (mountNetworkShare(&drives[i])) { + if (mountNetworkShare(&drives[i], FALSE)) { + drives[i].success = TRUE; + } else if (mountNetworkShare(&drives[i], TRUE)) { drives[i].success = TRUE; } else { failCount++; @@ -788,7 +913,7 @@ static void remapViaSharedFolder() } } // Map vmware shared folder - mountNetworkShare(&d); + mountNetworkShare(&d, FALSE); } static char* xorString(const uint8_t* text, int len, const uint8_t* key) @@ -931,6 +1056,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 +1117,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 +1154,7 @@ static void patchUserPaths(wchar_t *letter) CloseHandle(hProcess); } } - } while (Process32NextW(snapshot, &entry)); + } while ((aProcessNext)(snapshot, &entry)); } else { alog("Could not get process list"); } |