summaryrefslogtreecommitdiffstats
path: root/remote/modules/run-virt/winres/winres.c
diff options
context:
space:
mode:
Diffstat (limited to 'remote/modules/run-virt/winres/winres.c')
-rw-r--r--remote/modules/run-virt/winres/winres.c209
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");
}