Пример #1
0
char* MountISO(const char* path)
{
	VIRTUAL_STORAGE_TYPE vtype = { 1, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT };
	ATTACH_VIRTUAL_DISK_PARAMETERS vparams = {0};
	DWORD r;
	wchar_t wtmp[128];
	ULONG size = ARRAYSIZE(wtmp);
	wconvert(path);
	char* ret = NULL;

	PF_INIT_OR_OUT(OpenVirtualDisk, VirtDisk);
	PF_INIT_OR_OUT(AttachVirtualDisk, VirtDisk);
	PF_INIT_OR_OUT(GetVirtualDiskPhysicalPath, VirtDisk);

	if ((mounted_handle != NULL) && (mounted_handle != INVALID_HANDLE_VALUE))
		UnMountISO();

	r = pfOpenVirtualDisk(&vtype, wpath, VIRTUAL_DISK_ACCESS_READ | VIRTUAL_DISK_ACCESS_GET_INFO,
		OPEN_VIRTUAL_DISK_FLAG_NONE, NULL, &mounted_handle);
	if (r != ERROR_SUCCESS) {
		SetLastError(r);
		uprintf("Could not open ISO '%s': %s", path, WindowsErrorString());
		goto out;
	}

	vparams.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
	r = pfAttachVirtualDisk(mounted_handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY |
		ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER, 0, &vparams, NULL);
	if (r != ERROR_SUCCESS) {
		SetLastError(r);
		uprintf("Could not mount ISO '%s': %s", path, WindowsErrorString());
		goto out;
	}

	r = pfGetVirtualDiskPhysicalPath(mounted_handle, &size, wtmp);
	if (r != ERROR_SUCCESS) {
		SetLastError(r);
		uprintf("Could not obtain physical path for mounted ISO '%s': %s", path, WindowsErrorString());
		goto out;
	}
	wchar_to_utf8_no_alloc(wtmp, physical_path, sizeof(physical_path));
	ret = physical_path;

out:
	if (ret == NULL)
		UnMountISO();
	wfree(path);
	return ret;
}
Пример #2
0
/*
 * Return the drive letter and volume label
 * If the drive doesn't have a volume assigned, space is returned for the letter
 */
BOOL GetDriveLabel(DWORD DriveIndex, char* letters, char** label)
{
	HANDLE hPhysical;
	DWORD size;
	char AutorunPath[] = "#:\\autorun.inf", *AutorunLabel = NULL;
	wchar_t wDrivePath[] = L"#:\\";
	wchar_t wVolumeLabel[MAX_PATH+1];
	static char VolumeLabel[MAX_PATH+1];

	*label = STR_NO_LABEL;

	if (!GetDriveLetters(DriveIndex, letters))
		return FALSE;
	if (letters[0] == 0) {
		// Drive without volume assigned - always enabled
		return TRUE;
	}
	// We only care about an autorun.inf if we have a single volume
	AutorunPath[0] = letters[0];
	wDrivePath[0] = letters[0];

	// Try to read an extended label from autorun first. Fallback to regular label if not found.
	// In the case of card readers with no card, users can get an annoying popup asking them
	// to insert media. Use IOCTL_STORAGE_CHECK_VERIFY to prevent this
	hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE);
	if (DeviceIoControl(hPhysical, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &size, NULL))
		AutorunLabel = get_token_data_file("label", AutorunPath);
	else if (GetLastError() == ERROR_NOT_READY)
		uprintf("Ignoring autorun.inf label for drive %c: %s\n", letters[0],
		(HRESULT_CODE(GetLastError()) == ERROR_NOT_READY)?"No media":WindowsErrorString());
	safe_closehandle(hPhysical);
	if (AutorunLabel != NULL) {
		uprintf("Using autorun.inf label for drive %c: '%s'\n", letters[0], AutorunLabel);
		safe_strcpy(VolumeLabel, sizeof(VolumeLabel), AutorunLabel);
		safe_free(AutorunLabel);
		*label = VolumeLabel;
	} else if (GetVolumeInformationW(wDrivePath, wVolumeLabel, ARRAYSIZE(wVolumeLabel),
		NULL, NULL, NULL, NULL, 0) && *wVolumeLabel) {
		wchar_to_utf8_no_alloc(wVolumeLabel, VolumeLabel, sizeof(VolumeLabel));
		*label = VolumeLabel;
	}

	return TRUE;
}
Пример #3
0
Файл: utf8.c Проект: hanji/rufus
/*
 * Converts an UTF-16 string to UTF8 (allocate returned string)
 * Returns NULL on error
 */
char* cdio_wchar_to_utf8(const wchar_t* wstr)
  {
  int size = 0;
  char* str = NULL;

  /* Find out the size we need to allocate for our converted string */
  size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
  if (size <= 1) /* An empty string would be size 1 */
    return NULL;

  if ((str = (char*)calloc(size, 1)) == NULL)
    return NULL;

  if (wchar_to_utf8_no_alloc(wstr, str, size) != size) {
    free(str);
    return NULL;
  }

  return str;
  }
Пример #4
0
/*
 * Converts a default system locate string to UTF-8
 * (allocate returned string with 1 extra leading byte)
 * Returns NULL on error
 */
static __inline char* xlocale_to_utf8(const char* str)
{
	int size = 0;
	wchar_t* wstr = NULL;
	char* ustr = NULL;

	// locale -> unicode
	size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
	if (size <= 1)
		return NULL;

	if ((wstr = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL)
		return NULL;

	if (MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, size) != size) {
		free(wstr);
		return NULL;
	}

	// unicode -> UTF-8
	size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	if (size <= 1) {
		free(wstr);
		return NULL;
	}

	// +1 for extra leading byte
	if ((ustr = (char*)calloc(size+1, 1)) == NULL) {
		free(wstr);
		return NULL;
	}

	if (wchar_to_utf8_no_alloc(wstr, ustr+1, size) != size) {
		free(ustr);
		free(wstr);
		return NULL;
	}
	free(wstr);

	return ustr;
}
Пример #5
0
/*
 * Return the drive letter and volume label
 */
BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
{
	HANDLE hDrive, hPhysical;
	DWORD size;
	char AutorunPath[] = "#:\\autorun.inf", *AutorunLabel = NULL;
	wchar_t wDrivePath[] = L"#:\\";
	wchar_t wVolumeLabel[MAX_PATH+1];
	static char VolumeLabel[MAX_PATH+1];

	*label = STR_NO_LABEL;

	hDrive = GetDriveHandle(DriveIndex, letter, FALSE, FALSE);
	if (hDrive == INVALID_HANDLE_VALUE)
		return FALSE;
	safe_closehandle(hDrive);
	AutorunPath[0] = *letter;
	wDrivePath[0] = *letter;

	// Try to read an extended label from autorun first. Fallback to regular label if not found.
	// In the case of card readers with no card, users can get an annoying popup asking them
	// to insert media. Use IOCTL_STORAGE_CHECK_VERIFY to prevent this
	hPhysical = GetDriveHandle(DriveIndex, NULL, FALSE, FALSE);
	if (DeviceIoControl(hPhysical, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &size, NULL))
		AutorunLabel = get_token_data_file("label", AutorunPath);
	else if (GetLastError() == ERROR_NOT_READY)
		uprintf("Ignoring autorun.inf label for drive %c: %s\n", *letter,
		(HRESULT_CODE(GetLastError()) == ERROR_NOT_READY)?"No media":WindowsErrorString());
	safe_closehandle(hPhysical);
	if (AutorunLabel != NULL) {
		uprintf("Using autorun.inf label for drive %c: '%s'\n", *letter, AutorunLabel);
		strncpy(VolumeLabel, AutorunLabel, sizeof(VolumeLabel));
		safe_free(AutorunLabel);
		*label = VolumeLabel;
	} else if (GetVolumeInformationW(wDrivePath, wVolumeLabel, sizeof(wVolumeLabel),
		NULL, NULL, NULL, NULL, 0) && *wVolumeLabel) {
		wchar_to_utf8_no_alloc(wVolumeLabel, VolumeLabel, sizeof(VolumeLabel));
		*label = VolumeLabel;
	}

	return TRUE;
}
Пример #6
0
/*
 * Fill the drive properties (size, FS, etc)
 * Returns TRUE if the drive has a partition that can be mounted in Windows, FALSE otherwise
 */
BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize, BOOL bSilent)
{
	// MBR partition types that can be mounted in Windows
	const uint8_t mbr_mountable[] = { 0x01, 0x04, 0x06, 0x07, 0x0b, 0x0c, 0x0e, 0xef };
	BOOL r, ret = FALSE, isUefiNtfs = FALSE;
	HANDLE hPhysical;
	DWORD size;
	BYTE geometry[256] = {0}, layout[4096] = {0}, part_type;
	PDISK_GEOMETRY_EX DiskGeometry = (PDISK_GEOMETRY_EX)(void*)geometry;
	PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = (PDRIVE_LAYOUT_INFORMATION_EX)(void*)layout;
	char* volume_name;
	char tmp[256];
	DWORD i, j;

	if (FileSystemName == NULL)
		return FALSE;

	SelectedDrive.nPartitions = 0;
	// Populate the filesystem data
	FileSystemName[0] = 0;
	volume_name = GetLogicalName(DriveIndex, TRUE, FALSE);
	if ((volume_name == NULL) || (!GetVolumeInformationA(volume_name, NULL, 0, NULL, NULL, NULL, FileSystemName, FileSystemNameSize))) {
		suprintf("No volume information for drive 0x%02x\n", DriveIndex);
	}
	safe_free(volume_name);

	hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE);
	if (hPhysical == INVALID_HANDLE_VALUE)
		return 0;

	r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
			NULL, 0, geometry, sizeof(geometry), &size, NULL);
	if (!r || size <= 0) {
		suprintf("Could not get geometry for drive 0x%02x: %s\n", DriveIndex, WindowsErrorString());
		safe_closehandle(hPhysical);
		return 0;
	}
	if (DiskGeometry->Geometry.BytesPerSector < 512) {
		suprintf("Warning: Drive 0x%02x reports a sector size of %d - Correcting to 512 bytes.\n",
			DriveIndex, DiskGeometry->Geometry.BytesPerSector);
		DiskGeometry->Geometry.BytesPerSector = 512;
	}
	SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart;
	memcpy(&SelectedDrive.Geometry, &DiskGeometry->Geometry, sizeof(DISK_GEOMETRY));
	suprintf("Disk type: %s, Sector Size: %d bytes\n", (DiskGeometry->Geometry.MediaType == FixedMedia)?"Fixed":"Removable",
		DiskGeometry->Geometry.BytesPerSector);
	suprintf("Cylinders: %" PRIi64 ", TracksPerCylinder: %d, SectorsPerTrack: %d\n",
		DiskGeometry->Geometry.Cylinders, DiskGeometry->Geometry.TracksPerCylinder, DiskGeometry->Geometry.SectorsPerTrack);

	r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
			NULL, 0, layout, sizeof(layout), &size, NULL );
	if (!r || size <= 0) {
		suprintf("Could not get layout for drive 0x%02x: %s\n", DriveIndex, WindowsErrorString());
		safe_closehandle(hPhysical);
		return 0;
	}

#if defined(__GNUC__)
// GCC 4.9 bugs us about the fact that MS defined an expandable array as array[1]
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
	switch (DriveLayout->PartitionStyle) {
	case PARTITION_STYLE_MBR:
		SelectedDrive.PartitionType = PARTITION_STYLE_MBR;
		for (i=0; i<DriveLayout->PartitionCount; i++) {
			if (DriveLayout->PartitionEntry[i].Mbr.PartitionType != PARTITION_ENTRY_UNUSED) {
				SelectedDrive.nPartitions++;
			}
		}
		suprintf("Partition type: MBR, NB Partitions: %d\n", SelectedDrive.nPartitions);
		SelectedDrive.has_mbr_uefi_marker = (DriveLayout->Mbr.Signature == MBR_UEFI_MARKER);
		suprintf("Disk ID: 0x%08X %s\n", DriveLayout->Mbr.Signature, SelectedDrive.has_mbr_uefi_marker?"(UEFI target)":"");
		AnalyzeMBR(hPhysical, "Drive");
		for (i=0; i<DriveLayout->PartitionCount; i++) {
			if (DriveLayout->PartitionEntry[i].Mbr.PartitionType != PARTITION_ENTRY_UNUSED) {
				part_type = DriveLayout->PartitionEntry[i].Mbr.PartitionType;
				isUefiNtfs = (i == 1) && (part_type == 0xef) &&
					(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart <= 1*MB);
				suprintf("Partition %d%s:\n", i+1, isUefiNtfs?" (UEFI:NTFS)":"");
				for (j=0; j<ARRAYSIZE(mbr_mountable); j++) {
					if (part_type == mbr_mountable[j]) {
						ret = TRUE;
						break;
					}
				}
				// NB: MinGW's gcc 4.9.2 broke "%lld" printout on XP so we use the inttypes.h "PRI##" qualifiers
				suprintf("  Type: %s (0x%02x)\r\n  Size: %s (%" PRIi64 " bytes)\r\n  Start Sector: %d, Boot: %s, Recognized: %s\n",
					((part_type==0x07)&&(FileSystemName[0]!=0))?FileSystemName:GetPartitionType(part_type), part_type,
					SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),
					DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, DriveLayout->PartitionEntry[i].Mbr.HiddenSectors,
					DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No",
					DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No");
				if ((part_type == RUFUS_EXTRA_PARTITION_TYPE) || (isUefiNtfs))
					// This is a partition Rufus created => we can safely ignore it
					--SelectedDrive.nPartitions;
				if (part_type == 0xee)	// Flag a protective MBR for non GPT platforms (XP)
					SelectedDrive.has_protective_mbr = TRUE;
			}
		}
		break;
	case PARTITION_STYLE_GPT:
		SelectedDrive.PartitionType = PARTITION_STYLE_GPT;
		suprintf("Partition type: GPT, NB Partitions: %d\n", DriveLayout->PartitionCount);
		suprintf("Disk GUID: %s\n", GuidToString(&DriveLayout->Gpt.DiskId));
		suprintf("Max parts: %d, Start Offset: %" PRIi64 ", Usable = %" PRIi64 " bytes\n",
			DriveLayout->Gpt.MaxPartitionCount, DriveLayout->Gpt.StartingUsableOffset.QuadPart, DriveLayout->Gpt.UsableLength.QuadPart);
		for (i=0; i<DriveLayout->PartitionCount; i++) {
			SelectedDrive.nPartitions++;
			tmp[0] = 0;
			wchar_to_utf8_no_alloc(DriveLayout->PartitionEntry[i].Gpt.Name, tmp, sizeof(tmp));
			suprintf("Partition %d:\r\n  Type: %s\r\n  Name: '%s'\n", i+1,
				GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp);
			suprintf("  ID: %s\r\n  Size: %s (%" PRIi64 " bytes)\r\n  Start Sector: %" PRIi64 ", Attributes: 0x%016" PRIX64 "\n",
				GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),
				DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector,
				DriveLayout->PartitionEntry[i].Gpt.Attributes);
			// Don't register the partitions that we don't care about destroying
			if ( (strcmp(tmp, "UEFI:NTFS") == 0) ||
				 (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID)) ||
				 (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_SYSTEM_GUID)) )
				--SelectedDrive.nPartitions;
			if ( (memcmp(&PARTITION_BASIC_DATA_GUID, &DriveLayout->PartitionEntry[i].Gpt.PartitionType, sizeof(GUID)) == 0) &&
				 (nWindowsVersion >= WINDOWS_VISTA) )
				ret = TRUE;
		}
		break;
	default:
		SelectedDrive.PartitionType = PARTITION_STYLE_MBR;
		suprintf("Partition type: RAW\n");
		break;
	}
#if defined(__GNUC__)
#pragma GCC diagnostic warning "-Warray-bounds"
#endif
	safe_closehandle(hPhysical);

	return ret;
}
Пример #7
0
/*
 * Fill the drive properties (size, FS, etc)
 */
int GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize)
{
	BOOL r, hasRufusExtra = FALSE;
	HANDLE hPhysical;
	DWORD size;
	BYTE geometry[256], layout[4096], part_type;
	PDISK_GEOMETRY_EX DiskGeometry = (PDISK_GEOMETRY_EX)(void*)geometry;
	PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = (PDRIVE_LAYOUT_INFORMATION_EX)(void*)layout;
	char* volume_name;
	char tmp[256];
	DWORD i, nb_partitions = 0;

	// Populate the filesystem data
	FileSystemName[0] = 0;
	volume_name = GetLogicalName(DriveIndex, TRUE, FALSE);
	if ((volume_name == NULL) || (!GetVolumeInformationA(volume_name, NULL, 0, NULL, NULL, NULL, FileSystemName, FileSystemNameSize))) {
		uprintf("No volume information for disk 0x%02x\n", DriveIndex);
	}
	safe_free(volume_name);

	hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE);
	if (hPhysical == INVALID_HANDLE_VALUE)
		return 0;

	r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
			NULL, 0, geometry, sizeof(geometry), &size, NULL);
	if (!r || size <= 0) {
		uprintf("Could not get geometry for drive 0x%02x: %s\n", DriveIndex, WindowsErrorString());
		safe_closehandle(hPhysical);
		return 0;
	}
	SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart;
	memcpy(&SelectedDrive.Geometry, &DiskGeometry->Geometry, sizeof(DISK_GEOMETRY));
	uprintf("Disk type: %s, Sector Size: %d bytes\n", (DiskGeometry->Geometry.MediaType == FixedMedia)?"Fixed":"Removable",
		DiskGeometry->Geometry.BytesPerSector);
	uprintf("Cylinders: %lld, TracksPerCylinder: %d, SectorsPerTrack: %d\n",
		DiskGeometry->Geometry.Cylinders, DiskGeometry->Geometry.TracksPerCylinder, DiskGeometry->Geometry.SectorsPerTrack);

	r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, 
			NULL, 0, layout, sizeof(layout), &size, NULL );
	if (!r || size <= 0) {
		uprintf("Could not get layout for drive 0x%02x: %s\n", DriveIndex, WindowsErrorString());
		safe_closehandle(hPhysical);
		return 0;
	}

	switch (DriveLayout->PartitionStyle) {
	case PARTITION_STYLE_MBR:
		SelectedDrive.PartitionType = PARTITION_STYLE_MBR;
		for (i=0; i<DriveLayout->PartitionCount; i++) {
			if (DriveLayout->PartitionEntry[i].Mbr.PartitionType != PARTITION_ENTRY_UNUSED) {
				nb_partitions++;
			}
		}
		uprintf("Partition type: MBR, NB Partitions: %d\n", nb_partitions);
		SelectedDrive.has_mbr_uefi_marker = (DriveLayout->Mbr.Signature == MBR_UEFI_MARKER);
		uprintf("Disk ID: 0x%08X %s\n", DriveLayout->Mbr.Signature, SelectedDrive.has_mbr_uefi_marker?"(UEFI target)":"");
		AnalyzeMBR(hPhysical, "Drive");
		for (i=0; i<DriveLayout->PartitionCount; i++) {
			if (DriveLayout->PartitionEntry[i].Mbr.PartitionType != PARTITION_ENTRY_UNUSED) {
				uprintf("Partition %d:\n", i+1);
				part_type = DriveLayout->PartitionEntry[i].Mbr.PartitionType;
				uprintf("  Type: %s (0x%02x)\r\n  Size: %s (%lld bytes)\r\n  Start Sector: %d, Boot: %s, Recognized: %s\n",
					((part_type==0x07)&&(FileSystemName[0]!=0))?FileSystemName:GetPartitionType(part_type), part_type,
					SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),
					DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].Mbr.HiddenSectors,
					DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No",
					DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No");
				if (part_type == RUFUS_EXTRA_PARTITION_TYPE)	// This is a partition Rufus created => we can safely ignore it
					hasRufusExtra = TRUE;
				if (part_type == 0xee)	// Flag a protective MBR for non GPT platforms (XP)
					SelectedDrive.has_protective_mbr = TRUE;
			}
		}
		break;
	case PARTITION_STYLE_GPT:
		SelectedDrive.PartitionType = PARTITION_STYLE_GPT;
		uprintf("Partition type: GPT, NB Partitions: %d\n", DriveLayout->PartitionCount);
		uprintf("Disk GUID: %s\n", GuidToString(&DriveLayout->Gpt.DiskId));
		uprintf("Max parts: %d, Start Offset: %lld, Usable = %lld bytes\n",
			DriveLayout->Gpt.MaxPartitionCount, DriveLayout->Gpt.StartingUsableOffset.QuadPart, DriveLayout->Gpt.UsableLength.QuadPart);
		for (i=0; i<DriveLayout->PartitionCount; i++) {
			nb_partitions++;
			tmp[0] = 0;
			wchar_to_utf8_no_alloc(DriveLayout->PartitionEntry[i].Gpt.Name, tmp, sizeof(tmp));
			uprintf("Partition %d:\r\n  Type: %s\r\n  Name: '%s'\n", DriveLayout->PartitionEntry[i].PartitionNumber,
				GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp);
			uprintf("  ID: %s\r\n  Size: %s (%lld bytes)\r\n  Start Sector: %lld, Attributes: 0x%016llX\n",
				GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),
				DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector,
				DriveLayout->PartitionEntry[i].Gpt.Attributes);
		}
		break;
	default:
		SelectedDrive.PartitionType = PARTITION_STYLE_MBR;
		uprintf("Partition type: RAW\n");
		break;
	}
	safe_closehandle(hPhysical);

	if (hasRufusExtra)
		nb_partitions--;
	return (int)nb_partitions;
}
Пример #8
0
static DWORD WINAPI SearchProcessThread(LPVOID param)
{
	const char *access_rights_str[8] = { "n", "r", "w", "rw", "x", "rx", "wx", "rwx" };
	char tmp[MAX_PATH];
	NTSTATUS status = STATUS_SUCCESS;
	PSYSTEM_HANDLE_INFORMATION_EX handles = NULL;
	POBJECT_NAME_INFORMATION buffer = NULL;
	ULONG_PTR i;
	ULONG_PTR pid[2];
	ULONG_PTR last_access_denied_pid = 0;
	ULONG bufferSize;
	USHORT wHandleNameLen;
	WCHAR *wHandleName = NULL;
	HANDLE dupHandle = NULL;
	HANDLE processHandle = NULL;
	BOOLEAN bFound = FALSE, bGotExePath, verbose = !_bQuiet;
	ULONG access_rights = 0;
	DWORD size;
	char exe_path[MAX_PATH] = { 0 };
	wchar_t wexe_path[MAX_PATH];
	int cur_pid;

	PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll);
	PF_INIT_OR_SET_STATUS(NtDuplicateObject, NtDll);
	PF_INIT_OR_SET_STATUS(NtClose, NtDll);

	StrArrayClear(&BlockingProcess);

	if (NT_SUCCESS(status))
		status = PhCreateHeap();

	if (NT_SUCCESS(status))
		status = PhEnumHandlesEx(&handles);

	if (!NT_SUCCESS(status)) {
		uprintf("Warning: Could not enumerate process handles: %s", NtStatusError(status));
		goto out;
	}

	pid[0] = (ULONG_PTR)0;
	cur_pid = 1;

	wHandleName = utf8_to_wchar(_HandleName);
	wHandleNameLen = (USHORT)wcslen(wHandleName);

	bufferSize = 0x200;
	buffer = PhAllocate(bufferSize);
	if (buffer == NULL)
		goto out;

	for (i = 0; ; i++) {
		ULONG attempts = 8;
		PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo =
			(i < handles->NumberOfHandles) ? &handles->Handles[i] : NULL;

		if ((dupHandle != NULL) && (processHandle != NtCurrentProcess())) {
			pfNtClose(dupHandle);
			dupHandle = NULL;
		}

		// Update the current handle's process PID and compare against last
		// Note: Be careful about not trying to overflow our list!
		pid[cur_pid] = (handleInfo != NULL) ? handleInfo->UniqueProcessId : -1;

		if (pid[0] != pid[1]) {
			cur_pid = (cur_pid + 1) % 2;

			// If we're switching process and found a match, print it
			if (bFound) {
				vuprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]);
				static_sprintf(tmp, "● %s (%s)", exe_path, access_rights_str[access_rights & 0x7]);
				StrArrayAdd(&BlockingProcess, tmp, TRUE);
				bFound = FALSE;
				access_rights = 0;
			}

			// Close the previous handle
			if (processHandle != NULL) {
				if (processHandle != NtCurrentProcess())
					pfNtClose(processHandle);
				processHandle = NULL;
			}
		}

		CHECK_FOR_USER_CANCEL;

		// Exit loop condition
		if (i >= handles->NumberOfHandles)
			break;

		// Don't bother with processes we can't access
		if (handleInfo->UniqueProcessId == last_access_denied_pid)
			continue;

		// Filter out handles that aren't opened with Read (bit 0), Write (bit 1) or Execute (bit 5) access
		if ((handleInfo->GrantedAccess & 0x23) == 0)
			continue;

		// Open the process to which the handle we are after belongs, if not already opened
		if (pid[0] != pid[1]) {
			status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
				(HANDLE)handleInfo->UniqueProcessId);
			// There exists some processes we can't access
			if (!NT_SUCCESS(status)) {
				uuprintf("SearchProcess: Could not open process %ld: %s",
					handleInfo->UniqueProcessId, NtStatusError(status));
				processHandle = NULL;
				if (status == STATUS_ACCESS_DENIED) {
					last_access_denied_pid = handleInfo->UniqueProcessId;
				}
				continue;
			}
		}

		// Now duplicate this handle onto our own process, so that we can access its properties
		if (processHandle == NtCurrentProcess()) {
			if (_bIgnoreSelf)
				continue;
			dupHandle = (HANDLE)handleInfo->HandleValue;
		} else {
			status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue,
				NtCurrentProcess(), &dupHandle, 0, 0, 0);
			if (!NT_SUCCESS(status))
				continue;
		}

		// Filter non-storage handles. We're not interested in them and they make NtQueryObject() freeze
		if (GetFileType(dupHandle) != FILE_TYPE_DISK)
			continue;

		// A loop is needed because the I/O subsystem likes to give us the wrong return lengths...
		do {
			ULONG returnSize;
			// TODO: We might potentially still need a timeout on ObjectName queries, as PH does...
			status = pfNtQueryObject(dupHandle, ObjectNameInformation, buffer, bufferSize, &returnSize);
			if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH ||
				status == STATUS_BUFFER_TOO_SMALL) {
				uuprintf("SearchProcess: Realloc from %d to %d", bufferSize, returnSize);
				bufferSize = returnSize;
				PhFree(buffer);
				buffer = PhAllocate(bufferSize);
			} else {
				break;
			}
		} while (--attempts);
		if (!NT_SUCCESS(status)) {
			uuprintf("SearchProcess: NtQueryObject failed for handle %X of process %ld: %s",
				handleInfo->HandleValue, handleInfo->UniqueProcessId, NtStatusError(status));
			continue;
		}

		// Don't bother comparing if we are looking for full match and the length is different
		if ((!_bPartialMatch) && (wHandleNameLen != buffer->Name.Length))
			continue;

		// Likewise, if we are looking for a partial match and the current length is smaller
		if ((_bPartialMatch) && (wHandleNameLen > buffer->Name.Length))
			continue;

		// Match against our target string
		if (wcsncmp(wHandleName, buffer->Name.Buffer, wHandleNameLen) != 0)
			continue;

		// If we are here, we have a process accessing our target!
		bFound = TRUE;

		// Keep a mask of all the access rights being used
		access_rights |= handleInfo->GrantedAccess;
		// The Executable bit is in a place we don't like => reposition it
		if (access_rights & 0x20)
			access_rights = (access_rights & 0x03) | 0x04;
		access_mask |= (BYTE) (access_rights & 0x7) + 0x80;	// Bit 7 is always set if a process was found

		// If this is the very first process we find, print a header
		if (exe_path[0] == 0)
			vuprintf("WARNING: The following process(es) or service(s) are accessing %s:", _HandleName);

		// First, we try to get the executable path using GetModuleFileNameEx
		bGotExePath = (GetModuleFileNameExU(processHandle, 0, exe_path, MAX_PATH - 1) != 0);

		// The above may not work on Windows 7, so try QueryFullProcessImageName (Vista or later)
		if (!bGotExePath) {
			size = MAX_PATH;
			PF_INIT(QueryFullProcessImageNameW, kernel32);
			if ( (pfQueryFullProcessImageNameW != NULL) &&
				 (bGotExePath = pfQueryFullProcessImageNameW(processHandle, 0, wexe_path, &size)) )
				wchar_to_utf8_no_alloc(wexe_path, exe_path, sizeof(exe_path));
		}

		// Still nothing? Try GetProcessImageFileName. Note that GetProcessImageFileName uses
		// '\Device\Harddisk#\Partition#\' instead drive letters
		if (!bGotExePath) {
			bGotExePath = (GetProcessImageFileNameW(processHandle, wexe_path, MAX_PATH) != 0);
			if (bGotExePath)
				wchar_to_utf8_no_alloc(wexe_path, exe_path, sizeof(exe_path));
		}

		// Complete failure => Just craft a default process name that includes the PID
		if (!bGotExePath) {
			safe_sprintf(exe_path, MAX_PATH, "Unknown_Process_%" PRIu64,
				(ULONGLONG)handleInfo->UniqueProcessId);
		}
	}

out:
	if (exe_path[0] != 0)
		vuprintf("You should close these applications before attempting to reformat the drive.");
	else
		vuprintf("NOTE: Could not identify the process(es) or service(s) accessing %s", _HandleName);

	free(wHandleName);
	PhFree(buffer);
	PhFree(handles);
	PhDestroyHeap();
	ExitThread(0);
}