/* * Mount partition #part_nr, residing on the same disk as drive_name to an available * drive letter. Returns the newly allocated drive string. * We need to do this because, for instance, EFI System partitions are not assigned * Volume GUIDs by the OS, and we need to have a letter assigned, for when we invoke * bcdtool for Windows To Go. All in all, the process looks like this: * 1. F: = \Device\HarddiskVolume9 (SINGLE LOOKUP) * 2. Harddisk5Partition1 = \Device\HarddiskVolume9 (FULL LOOKUP) * 3. Harddisk5Partition2 = \Device\HarddiskVolume10 (SINGLE LOOKUP) * 4. DefineDosDevice(letter, \Device\HarddiskVolume10) */ char* AltMountVolume(const char* drive_name, uint8_t part_nr) { static char mounted_drive[] = "?:"; const DWORD bufsize = 65536; char *buffer = NULL, *p, target[2][MAX_PATH], *ret = NULL; size_t i; mounted_drive[0] = GetUnusedDriveLetter(); if (mounted_drive[0] == 0) { uprintf("Could not find an unused drive letter"); goto out; } target[0][0] = 0; // Convert our drive letter to something like "\Device\HarddiskVolume9" if (!QueryDosDeviceA(drive_name, target[0], MAX_PATH) || (strlen(target[0]) == 0)) { uprintf("Could not get the DOS volume name for '%s': %s", drive_name, WindowsErrorString()); goto out; } // Now parse the whole DOS device list to find the 'Harddisk#Partition#' that matches the above // TODO: realloc if someone ever manages to burst through 64K of DOS devices buffer = malloc(bufsize); if (buffer == NULL) goto out; buffer[0] = 0; if (!QueryDosDeviceA(NULL, buffer, bufsize)) { uprintf("Could not get the DOS device list: %s", WindowsErrorString()); goto out; } p = buffer; while (strlen(p) != 0) { if ((strncmp("Harddisk", p, 8) == 0) && (strstr(&p[9], "Partition") != NULL)) { target[1][0] = 0; if (QueryDosDeviceA(p, target[1], MAX_PATH) && (strlen(target[1]) != 0)) if ((strcmp(target[1], target[0]) == 0) && (p[1] != ':')) break; } p += strlen(p) + 1; } i = strlen(p); if (i == 0) { uprintf("Could not find partition mapping for %s", target[0]); goto out; } while ((--i > 0) && (isdigit(p[i]))); p[++i] = '0' + part_nr; p[++i] = 0; target[0][0] = 0; if (!QueryDosDeviceA(p, target[0], MAX_PATH) || (strlen(target[0]) == 0)) { uprintf("Could not find the DOS volume name for partition '%s': %s", p, WindowsErrorString()); goto out; } if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH | DDD_NO_BROADCAST_SYSTEM, mounted_drive, target[0])) { uprintf("Could not mount '%s' to '%s': %s", target[0], mounted_drive, WindowsErrorString()); goto out; } uprintf("Successfully mounted '%s' (USB partition %d) as '%s'", target[0], part_nr, mounted_drive); ret = mounted_drive; out: safe_free(buffer); return ret; }
bool ShareFinder::BindUploadShareToLocalDrive(char* szServer, int nBufferSize, char** lplpPhysicalPath, char* pAssignedDrive) { // Returns the drive letter if successful, otherwise 0 PSHARE_INFO_502 BufPtr, p; NET_API_STATUS res; DWORD er = 0, tr = 0, resume = 0, i; wchar_t server[MAX_PATH]; char szTemp[MAX_PATH]; bool bBound = false; char szServerWithSlashes[MAX_PATH]; char lpszLocalDrive[3]; ::ZeroMemory(server, MAX_PATH); ::ZeroMemory(szServerWithSlashes, MAX_PATH); ::ZeroMemory(*lplpPhysicalPath, nBufferSize); _snprintf_s(szServerWithSlashes, MAX_PATH, 2+strlen(szServer), "\\\\%s", szServer); size_t requiredSize = 0; mbstowcs_s(&requiredSize, server, MAX_PATH, szServerWithSlashes, strlen(szServerWithSlashes)); memset(lpszLocalDrive, 0, 3); // This needs to be protected with a critical section, since multiple threads may try to get a free // drive letter at the same time! That's a bad thing WaitForSingleObject(hMutex, INFINITE); char cDriveLetter = GetUnusedDriveLetter(); memset(lpszLocalDrive, 0, 3); lpszLocalDrive[0] = cDriveLetter; lpszLocalDrive[1] = ':'; if (cDriveLetter == 0) { ReleaseMutex(hMutex); return false; } memcpy(pAssignedDrive, &cDriveLetter, 1); do { // F**k Microsoft and it's lame-ass unicode crap res = NetShareEnum((LPWSTR)server, 502, (LPBYTE*)&BufPtr, -1, &er, &tr, &resume); if(res == ERROR_SUCCESS || res == ERROR_MORE_DATA) { p = BufPtr; for(i = 1; i <= er; i++) { ::ZeroMemory(szTemp, MAX_PATH); size_t requiredSize2 = 0; wcstombs_s(&requiredSize2, szTemp, MAX_PATH, (LPWSTR)(p->shi502_netname), MAX_PATH); // Look for shares that are not SYSVOL or NETLOGON, and that have a physical path if (_stricmp(szTemp, "SYSVOL") != 0 && _stricmp(szTemp, "NETLOGON") != 0 && wcslen((LPWSTR)(p->shi502_path)) > 0) { // If this is a potentially workable share, bind the drive and try uploading something if (BindDrive(lpszLocalDrive, szServerWithSlashes, szTemp)) { // Success! // Copy the physical path to the out variable size_t requiredSize3 = 0; wcstombs_s(&requiredSize3, szTemp, MAX_PATH, (LPWSTR)(p->shi502_path), MAX_PATH); strncpy_s(*lplpPhysicalPath, MAX_PATH, szTemp, nBufferSize); bBound = true; break; } // Otherwise continue and try another share } p++; } NetApiBufferFree(BufPtr); } else Log.CachedReportError(m_nCacheID, CRITICAL, "BindUploadShareToLocalDrive returned an error of %ld\n",res); } while (res == ERROR_MORE_DATA); // end do ReleaseMutex(hMutex); return true; }