From 89e1f7912959ec9338022057dc8ee58c200c91c2 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 4 Mar 2016 16:25:59 +0100 Subject: [run-virt/vmware] Mount home directory in windows (first working version) --- remote/modules/run-virt/compile | 8 +- .../data/opt/openslx/scripts/includes/TEST.sh | 6 ++ .../includes/set_runvirt_hardware_variables.inc | 2 - .../set_runvirt_hardware_variables_legacy.inc | 2 - .../scripts/includes/setup_virtual_floppy.inc | 46 ++++++--- .../pam_script_auth.d/99-run_virt_credentials | 39 ++++++++ .../data/opt/openslx/vmchooser/data/SHARELWS.BAT | 40 -------- .../data/opt/openslx/vmchooser/data/openslx.exe | Bin 15360 -> 52224 bytes remote/modules/run-virt/module.build | 3 + remote/modules/run-virt/module.conf | 2 + remote/modules/run-virt/module.conf.ubuntu | 2 + remote/modules/run-virt/pw_daemon.c | 14 +-- remote/modules/run-virt/winres.c | 111 +++++++++++++++++++-- 13 files changed, 200 insertions(+), 75 deletions(-) create mode 100755 remote/modules/run-virt/data/opt/openslx/scripts/includes/TEST.sh create mode 100644 remote/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials delete mode 100644 remote/modules/run-virt/data/opt/openslx/vmchooser/data/SHARELWS.BAT (limited to 'remote/modules/run-virt') diff --git a/remote/modules/run-virt/compile b/remote/modules/run-virt/compile index 0e388e46..8c950d7b 100755 --- a/remote/modules/run-virt/compile +++ b/remote/modules/run-virt/compile @@ -2,4 +2,10 @@ rm -- winres.exe i686-w64-mingw32-gcc -Wall -Wextra -pedantic -Wno-unused-parameter -std=c99 -Os -Wl,--subsystem,windows -o winres.exe winres.c -lole32 -luuid -lgdi32 -lws2_32 -lshell32 -lmpr -strip winres.exe && echo "Successfully created winres.exe" +if strip winres.exe; then + echo "Successfully created winres.exe" + echo "It has NOT been moved to data/.../openslx.exe" +else + echo "FAIL FAIL FAIL no EXE generated!" +fi + diff --git a/remote/modules/run-virt/data/opt/openslx/scripts/includes/TEST.sh b/remote/modules/run-virt/data/opt/openslx/scripts/includes/TEST.sh new file mode 100755 index 00000000..fd5f755d --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/scripts/includes/TEST.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +. usb_detector.inc + +get_usb_devices "bla=%VENDOR% kacke=%PRODUCT%" 0:6 0:7 0:e 0:10 + diff --git a/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables.inc b/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables.inc index 400c1bf4..a93bf62c 100644 --- a/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables.inc +++ b/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables.inc @@ -51,8 +51,6 @@ fi fdtest=${floppy_0:+"TRUE"} # if $fdtest not set floppy0="FALSE", else "TRUE" floppy0=${fdtest:-"FALSE"} -floppy1="TRUE" -floppy1name="$VMCHOOSER_DIR/data/loopimg/fd.img" # if $cdrom_0 from virtualization.conf set then cdtest="TRUE" cdtest=${cdrom_0:+"TRUE"} # if $cdtest not set cdrom0="FALSE", else "TRUE" diff --git a/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables_legacy.inc b/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables_legacy.inc index 0da5e2be..05d55f00 100644 --- a/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables_legacy.inc +++ b/remote/modules/run-virt/data/opt/openslx/scripts/includes/set_runvirt_hardware_variables_legacy.inc @@ -51,8 +51,6 @@ fi fdtest=${floppy_0:+"TRUE"} # if $fdtest not set floppy0="FALSE", else "TRUE" floppy0=${fdtest:-"FALSE"} -floppy1="TRUE" -floppy1name="$VMCHOOSER_DIR/data/loopimg/fd.img" # if $cdrom_0 from virtualization.conf set then cdtest="TRUE" cdtest=${cdrom_0:+"TRUE"} # if $cdtest not set cdrom0="FALSE", else "TRUE" diff --git a/remote/modules/run-virt/data/opt/openslx/scripts/includes/setup_virtual_floppy.inc b/remote/modules/run-virt/data/opt/openslx/scripts/includes/setup_virtual_floppy.inc index 4b8e10aa..d1343700 100644 --- a/remote/modules/run-virt/data/opt/openslx/scripts/includes/setup_virtual_floppy.inc +++ b/remote/modules/run-virt/data/opt/openslx/scripts/includes/setup_virtual_floppy.inc @@ -1,21 +1,43 @@ +#!/bin/bash ############################################## # Include: Setup virtual floppy for drive b: # ############################################## +declare -rg FLOPPYIMG="${TMPDIR}/floppy.img" +declare -rg TMPHOME="${HOME}" + +dd "if=/dev/zero" "of=${FLOPPYIMG}" count=1440 bs=1024 +chmod 0600 "${FLOPPYIMG}" +mkfs.fat "${FLOPPYIMG}" || mkfs.vfat "${FLOPPYIMG}" || mkdosfs "${FLOPPYIMG}" + # Copy guest configuration (with added information) config.xml to be accessed # via virtual floppy -cp "$xmlfile" "$VMCHOOSER_DIR/fd-loop/config.xml" +#mcopy -i "${FLOPPYIMG}" "$xmlfile" "::/config.xml" + +# Create file with resolution information +xrandr | grep -o -E 'connected\s*(primary)?\s*[0-9]+x[0-9]+\+0\+0' \ + | grep -o -E -m1 '[0-9]+x[0-9]+' > "${TMPDIR}/hostres.txt" -# Add another file with resolution information -xrandr | grep -o -E 'connected\s*(primary)?\s*[0-9]+x[0-9]+\+0\+0' | grep -o -E '[0-9]+x[0-9]+' | head -n 1 > "$VMCHOOSER_DIR/fd-loop/hostres.txt" +# Create file for network shares to mount +SHARES="${TMPDIR}/shares.dat" +touch "${SHARES}" +chmod 0600 "${SHARES}" +if pwdaemon --query "${TMPHOME}/.pwsocket" > "${SHARES}"; then + sed -i 's/^/192.168.101.1\t/' "${SHARES}" # TODO: Depending on nettype (in case we have != nat some day) + if [ -e "${TMPHOME}/.home" ]; then + NETHOME=$(cat "${TMPHOME}/.home") + [ -z "$SLX_HOME_DRIVE" ] && SLX_HOME_DRIVE="H:" + # Tab between items, so spaces can be used! + echo "${NETHOME} ${SLX_HOME_DRIVE} Home-Verzeichnis" >> "${SHARES}" + fi + for VAR in ${!SLX_SHARE_*}; do + echo "${!VAR}" >> "${SHARES}" + done +fi -# Add our magic openslx binary that sets the correct guest resolution -cp "$VMCHOOSER_DIR/data/openslx.exe" "$VMCHOOSER_DIR/fd-loop/" -cp "$VMCHOOSER_DIR/data/SHARELWS.BAT" "$VMCHOOSER_DIR/fd-loop/" -rm "$VMCHOOSER_DIR/fd-loop/SHARELW.CFG" +# Copy all them files into floppy image +mcopy -i "${FLOPPYIMG}" "${TMPDIR}/hostres.txt" "::/" +mcopy -i "${FLOPPYIMG}" "$VMCHOOSER_DIR/data/openslx.exe" "::/" +mcopy -i "${FLOPPYIMG}" "${SHARES}" "::/" +unset SHARES VAR NETHOME -for SHARE in $(grep -o -E '^SLX_SHARE_.*_PATH' /opt/openslx/config); do - eval "echo -n \$${SHARE} | /opt/openslx/bin/tr '/' '\' " >> "$VMCHOOSER_DIR/fd-loop/SHARELW.CFG" - #eval echo -n " \$${SHARE%PATH}AUTH_PASS /user:\$${SHARE%PATH}AUTH_USER" >> "$VMCHOOSER_DIR/fd-loop/SHARELW.CFG" - echo -e '\r\n' >> "$VMCHOOSER_DIR/fd-loop/SHARELW.CFG" -done diff --git a/remote/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials b/remote/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials new file mode 100644 index 00000000..1e2c18e7 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials @@ -0,0 +1,39 @@ +#!/bin/ash +# This is being sourced and running in ash + +if [ -n "$TEMP_HOME_DIR" ]; then + if [ -z "$PAM_TTY" ] || [ "x$PAM_TTY" = "x:0" ]; then + # Pass on network path to home directory + if [ -z "$PERSISTENT_NETPATH" ]; then + PERSISTENT_NETPATH=$(grep -m1 -F " ${PERSISTENT_HOME_DIR} " "/proc/mounts" | awk '{print $1}') + fi + if [ -n "$PERSISTENT_NETPATH" ]; then + [ "x${PERSISTENT_NETPATH:0:2}" = "x//" ] && PERSISTENT_NETPATH=$(echo "$PERSISTENT_NETPATH" | tr '/' '\') + echo "${PERSISTENT_NETPATH}" > "${TEMP_HOME_DIR}/.home" + chmod 0644 "${TEMP_HOME_DIR}/.home" + fi + # pwdaemon + # Figure out username + XUSER="${REAL_ACCOUNT}" + [ -z "$XUSER" ] && XUSER="${PAM_USER}" + # Guess domain + XDOMAIN= + if [ -n "$PERSISTENT_OK" ]; then + XDOMAIN=$(grep -F " ${PERSISTENT_HOME_DIR} " "/proc/mounts" | grep -m1 -F 'domain=' | sed -r 's/^.*[ ,]domain=([^ ,]+)[ ,].*$/\1/g') + fi + if [ -z "$XDOMAIN" ]; then + XDOMAIN=$(grep -m1 -i '^BASE\s*DC=' "/etc/ldap.conf" | sed -r 's/^BASE\s*DC=([^,;]+)[,;].*$/\1/I') + fi + if [ -z "$XDOMAIN" ]; then + XDOMAIN=$(grep -m1 -i '^ldap_search_base\s*=' "/etc/sssd/sssd.conf" | sed -r 's/^ldap_search_base\s*=\s*DC=([^,;]+)[,;].*$/\1/I') + fi + if [ -n "$XDOMAIN" ]; then + XDOMAIN=$(echo "$XDOMAIN" | tr '[a-z]' '[A-Z]') + fi + USERNAME="$XDOMAIN\\$XUSER" PASSWORD="$PAM_AUTHTOK" PWSOCKET="${TEMP_HOME_DIR}/.pwsocket" su -c 'pwdaemon --daemon &' "${PAM_USER}" & + unset XUSER XDOMAIN + fi +fi + +true + diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/data/SHARELWS.BAT b/remote/modules/run-virt/data/opt/openslx/vmchooser/data/SHARELWS.BAT deleted file mode 100644 index 01838705..00000000 --- a/remote/modules/run-virt/data/opt/openslx/vmchooser/data/SHARELWS.BAT +++ /dev/null @@ -1,40 +0,0 @@ -@echo off - -setlocal EnableDelayedExpansion - -rem Kein sleep oder timeout bis Win7, also einen -rem haesslichen Hack (Zeitverz. ca. 5 sec) -rem Sinn der Verzoegerung: Mitunter (1/3) wird -rem sonst das erste Netzlaufwerk nicht eingehaengt - -@ping -n 5 localhost> nul - -rem Konfigdatei auslesen und erstmal in Feld: -set n=0 -for /f %%i in (b:\sharelw.cfg) do ( - set array[!n!]=%%i - set /A n+=1 -) - -rem Aufruf für net use erzeugen: -set "i=0" -for %%b in (K L M N O P Q R S T U V W X Y Z) do ( - if defined array[!i!] ( - call set aufruf[!i!]=%%b: %%array[!i!]%% - set /A "i+=1" - ) else ( - goto :Schleifenende - ) -) -:Schleifenende - -rem net use-Aufrufe -set "i=0" -:Ausdrucken -if defined aufruf[!i!] ( - call net use %%aufruf[!i!]%% - set /a "i+=1" - GOTO :Ausdrucken -) - -exit /B diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/data/openslx.exe b/remote/modules/run-virt/data/opt/openslx/vmchooser/data/openslx.exe index 114a0dc0..387f420b 100755 Binary files a/remote/modules/run-virt/data/opt/openslx/vmchooser/data/openslx.exe and b/remote/modules/run-virt/data/opt/openslx/vmchooser/data/openslx.exe differ diff --git a/remote/modules/run-virt/module.build b/remote/modules/run-virt/module.build index 26762bca..e9b0d581 100644 --- a/remote/modules/run-virt/module.build +++ b/remote/modules/run-virt/module.build @@ -8,6 +8,9 @@ build () { rm -f -- "$COPYLIST" list_packet_files > "$COPYLIST" tarcopy "$(cat "$COPYLIST" | sort -u)" "${MODULE_BUILD_DIR}" + # Compile pwdaemon + mkdir -p "${MODULE_BUILD_DIR}/opt/openslx/bin" + gcc -std=gnu99 -o "${MODULE_BUILD_DIR}/opt/openslx/bin/pwdaemon" -Os "${MODULE_DIR}/pw_daemon.c" || perror "Could not compile the pwdaemon" } post_copy() { diff --git a/remote/modules/run-virt/module.conf b/remote/modules/run-virt/module.conf index bd24ba58..b52fae0e 100644 --- a/remote/modules/run-virt/module.conf +++ b/remote/modules/run-virt/module.conf @@ -1,4 +1,6 @@ REQUIRED_BINARIES=" lsusb + mcopy + pwdaemon " diff --git a/remote/modules/run-virt/module.conf.ubuntu b/remote/modules/run-virt/module.conf.ubuntu index b285210b..b06efa7a 100644 --- a/remote/modules/run-virt/module.conf.ubuntu +++ b/remote/modules/run-virt/module.conf.ubuntu @@ -1,7 +1,9 @@ REQUIRED_INSTALLED_PACKAGES=" usbutils + mtools " REQUIRED_CONTENT_PACKAGES=" usbutils + mtools " diff --git a/remote/modules/run-virt/pw_daemon.c b/remote/modules/run-virt/pw_daemon.c index 3316a0e3..768a5b00 100644 --- a/remote/modules/run-virt/pw_daemon.c +++ b/remote/modules/run-virt/pw_daemon.c @@ -64,7 +64,7 @@ static int mode_query(const char *socketPath) tv.tv_usec = 0; setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - if (connect(fd, &remote, sizeof(remote)) == -1) { + if (connect(fd, (struct sockaddr*)&remote, sizeof(remote)) == -1) { perror("Cannot connect to pw daemon"); return 1; } @@ -86,7 +86,7 @@ static int mode_query(const char *socketPath) return 1; } buffer[ret] = '\0'; - fprintf(stderr, "%s", buffer); + printf("%s", buffer); return 0; } @@ -144,7 +144,7 @@ static int mode_daemon() for (;;) { struct sockaddr_un remote; socklen_t len = sizeof(remote); - int fd = accept(listenFd, &remote, &len); + int fd = accept(listenFd, (struct sockaddr*)&remote, &len); if (fd != -1) { if (udpPort == -1) { udpPort = init_udp(); @@ -158,7 +158,7 @@ static int mode_daemon() ret = read(fd, buffer, sizeof(buffer)); if (ret >= 3 && strncmp(buffer, "GET", 3) == 0) { snprintf(buffer, sizeof(buffer), "%d\t%s\t%s\t%s\n", udpPort, key1s, key2s, username); - write(fd, buffer, strlen(buffer)); + ret = write(fd, buffer, strlen(buffer)); } close(fd); return 0; @@ -278,7 +278,7 @@ static int init_udp() local.sin_family = AF_INET; local.sin_port = htons((uint16_t)port); local.sin_addr.s_addr = INADDR_ANY; - if (bind(fd, &local, sizeof(local)) == -1) { + if (bind(fd, (struct sockaddr*)&local, sizeof(local)) == -1) { if (++tries > 100) { perror("Cannot bind udp socket"); close(fd); @@ -304,9 +304,9 @@ static int init_udp() struct sockaddr_in remote; socklen_t remoteLen = sizeof(remote); uint8_t buffer[KEYLEN]; - ssize_t ret = recvfrom(fd, buffer, KEYLEN, 0, &remote, &remoteLen); + ssize_t ret = recvfrom(fd, buffer, KEYLEN, 0, (struct sockaddr*)&remote, &remoteLen); if (ret == KEYLEN && memcmp(key1, buffer, KEYLEN) == 0) { - if (sendto(fd, passwordEnc, passwordLen, 0, &remote, sizeof(remote)) == -1) { + if (sendto(fd, passwordEnc, passwordLen, 0, (struct sockaddr*)&remote, sizeof(remote)) == -1) { perror("Could not send password to remote peer"); } } diff --git a/remote/modules/run-virt/winres.c b/remote/modules/run-virt/winres.c index 1a6c6a6b..0cc3963b 100644 --- a/remote/modules/run-virt/winres.c +++ b/remote/modules/run-virt/winres.c @@ -2,6 +2,8 @@ #define WINVER 0x0602 #define _WIN32_WINNT 0x0602 #define WIN32_LEAN_AND_MEAN +#define _UNICODE +#define UNICODE #include #include #include @@ -16,6 +18,7 @@ #include #include #include +#include #include DEFINE_GUID(ID_IAudioEndpointVolume, 0x5CDF2C82, 0x841E, 0x4546, 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A); @@ -39,7 +42,7 @@ static const ssize_t KEYLEN = 16; static BOOL bGetShares = FALSE; static netdrive_t drives[DRIVEMAX]; -static wchar_t desktopPath[MAX_PATH+1], tempPath[MAX_PATH+1], programsPath[MAX_PATH+1]; +static wchar_t desktopPath[MAX_PATH+1], tempPath[MAX_PATH+1], programsPath[MAX_PATH+1], windowsPath[MAX_PATH+1]; static wchar_t logFile[LOGFILELEN]; static int setResolution(); @@ -50,6 +53,8 @@ static BOOL mountNetworkShares(); static int queryPasswordDaemon(); static BOOL fileExists(wchar_t* szPath); +static HRESULT createFolderShortcut(wchar_t* sTargetfile, wchar_t* sLinkfile); + static void alog(const char *fmt, ...) { FILE *f = _wfopen(logFile, L"a+"); @@ -131,6 +136,12 @@ static void loadPaths() StringCchPrintfW(programsPath, MAX_PATH+1, L"C:\\Program Files"); } } + 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"); + } + } if (SHGetFolderPathW(HWND_DESKTOP, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, desktopPath) != S_OK) { desktopPath[0] = 0; } @@ -158,6 +169,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine OSVERSIONINFO version; version.dwOSVersionInfoSize = sizeof(version); BOOL retVer = GetVersionEx(&version); + CoInitialize(NULL); loadPaths(); // Mute sound by default if (retVer && version.dwMajorVersion >= 6) @@ -310,7 +322,6 @@ static int setResolution() static int muteSound() { - CoInitialize(NULL); IMMDeviceEnumerator *deviceEnumerator = NULL; HRESULT hr = CoCreateInstance(&ID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &ID_IMMDeviceEnumerator, (LPVOID *)&deviceEnumerator); if (hr != S_OK) { @@ -385,7 +396,7 @@ static void readShareFile() if (bGetShares) return; memset(drives, 0, sizeof(drives)); - FILE *h = fopen(".\\shares.dat", "r"); + FILE *h = fopen("B:\\shares.dat", "r"); if (h == NULL) return; char creds[300] = "", buffer[500] = ""; char *skey1 = NULL, *skey2 = NULL; @@ -514,12 +525,17 @@ static void udpReceived(SOCKET sock) static DWORD mount(LPNETRESOURCEW share, LPWSTR pass, LPWSTR user) { DWORD retval; + // Remove remembered drive if it's not connected + //GetDriveType() DRIVE_NO_ROOT_DIR + //WNetCancelConnection2W(share->lpLocalName, CONNECT_UPDATE_PROFILE, TRUE); + // Now try to mount retval = WNetAddConnection2W(share, pass, user, CONNECT_TEMPORARY | CONNECT_CURRENT_MEDIA); if (retval == NO_ERROR) { return retval; } if (retval != ERROR_INVALID_PASSWORD && retval != ERROR_LOGON_FAILURE - && retval != ERROR_BAD_USERNAME && ERROR_ACCESS_DENIED) { + && retval != ERROR_BAD_USERNAME && retval != ERROR_ACCESS_DENIED + && retval != ERROR_SESSION_CREDENTIAL_CONFLICT) { return retval; } static wchar_t nuser[BUFLEN] = L"", npass[BUFLEN] = L""; @@ -534,6 +550,19 @@ static DWORD mount(LPNETRESOURCEW share, LPWSTR pass, LPWSTR user) return retval; } +static void mkshortcut(const netdrive_t *d) +{ + if (d->shortcut == NULL || strlen(d->shortcut) == 0) + return; + wchar_t tmp[MAX_PATH], wShortcut[MAX_PATH], wTarget[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, d->shortcut, -1, tmp, MAX_PATH); + StringCchPrintfW(wShortcut, MAX_PATH, L"%s\\%s.lnk", desktopPath, tmp); + MultiByteToWideChar(CP_UTF8, 0, d->path, -1, tmp, MAX_PATH); + StringCchPrintfW(wTarget, MAX_PATH, L"\"%s\"", tmp); + DeleteFileW(wShortcut); + createFolderShortcut(wTarget, wShortcut); +} + static BOOL mountNetworkShare(const netdrive_t *d) { wchar_t path[BUFLEN] = L"", user[BUFLEN] = L"", pass[BUFLEN] = L"", letter[10] = L"", shortcut[BUFLEN] = L""; @@ -565,21 +594,39 @@ static BOOL mountNetworkShare(const netdrive_t *d) letter[2] = 0; // TODO d->shortcut if (letter[0] != 0) { // Try with specific letter + // Get anything there might be out of the way + WNetCancelConnection2W(letter, CONNECT_UPDATE_PROFILE, TRUE); + // Connect defined share retval = mount(&share, pass, user); - if (retval == NO_ERROR) + if (retval == NO_ERROR) { + mkshortcut(d); return TRUE; - if (retval != ERROR_ALREADY_ASSIGNED) { + } + if (retval != ERROR_ALREADY_ASSIGNED && retval != ERROR_DEVICE_ALREADY_REMEMBERED + && retval != ERROR_CONNECTION_UNAVAIL) { alog("mountNetworkShare: with letter failed: %d", (int)retval); return FALSE; } } - // Let Window assign a letter - share.lpLocalName = NULL; - retval = mount(&share, pass, user); - if (retval != NO_ERROR) { + // Try to find free drive letter + for (letter[0] = 'Z'; letter[0] > 'C'; --letter[0]) { + retval = mount(&share, pass, user); + if (retval == ERROR_ALREADY_ASSIGNED || retval == ERROR_DEVICE_ALREADY_REMEMBERED + || retval == ERROR_CONNECTION_UNAVAIL) + continue; + if (retval == NO_ERROR) { + mkshortcut(d); + return TRUE; + } alog("mountNetworkShare: without letter failed: %d", (int)retval); + if (retval == ERROR_INVALID_PASSWORD || retval == ERROR_LOGON_FAILURE + || retval == ERROR_BAD_USERNAME || retval == ERROR_ACCESS_DENIED + || retval == ERROR_SESSION_CREDENTIAL_CONFLICT) { + return TRUE; + } + return FALSE; } - return retval == NO_ERROR; + return FALSE; } static BOOL mountNetworkShares() @@ -639,3 +686,45 @@ static uint8_t* hex2bin(char *szHexString) return pBinary; } +// Stuff for creating a simple shortcut (.lnk) + +static HRESULT createFolderShortcut(wchar_t* targetDir, wchar_t* linkFile) +{ + HRESULT hRes; /* Returned COM result code */ + IShellLink* pShellLink; /* IShellLink object pointer */ + IPersistFile* pPersistFile; /* IPersistFile object pointer */ + + hRes = E_INVALIDARG; + if ( + (targetDir != NULL) && (wcslen(targetDir) > 0) && + (linkFile != NULL) && (wcslen(linkFile) > 0) + ) { + hRes = CoCreateInstance( + &CLSID_ShellLink, /* pre-defined CLSID of the IShellLink object */ + NULL, /* pointer to parent interface if part of aggregate */ + CLSCTX_INPROC_SERVER, /* caller and called code are in same process */ + &IID_IShellLink, /* pre-defined interface of the IShellLink object */ + (void**)&pShellLink); /* Returns a pointer to the IShellLink object */ + if (SUCCEEDED(hRes)) { + wchar_t explorer[MAX_PATH]; + StringCchPrintfW(explorer, MAX_PATH, L"\"%s\\explorer.exe\"", windowsPath); + /* Set the fields in the IShellLink object */ + //hRes = pShellLink->lpVtbl->SetPath(pShellLink, targetDir); + hRes = pShellLink->lpVtbl->SetArguments(pShellLink, targetDir); + + /* Use the IPersistFile object to save the shell link */ + hRes = pShellLink->lpVtbl->QueryInterface( + pShellLink, /* existing IShellLink object */ + &IID_IPersistFile, /* pre-defined interface of the IPersistFile object */ + (void**)&pPersistFile); /* returns a pointer to the IPersistFile object */ + if (SUCCEEDED(hRes)) { + hRes = pPersistFile->lpVtbl->Save(pPersistFile, linkFile, TRUE); + pPersistFile->lpVtbl->Release(pPersistFile); + } + pShellLink->lpVtbl->Release(pShellLink); + } + + } + return (hRes); +} + -- cgit v1.2.3-55-g7522