示例#1
0
/*
 * 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;
}
示例#2
0
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;
}