Windows API - PARTITION_STYLE

0

Witam, mam problem z pobraniem z windows API czy dysk (partycja) jest w MBR czy GPT lub RAW. Funkcja zwraca mi : DeviceIoControl failed with error : 0.

Kod funkcji :

QString windows_drive_identifiaction::device_partition_style(char partitions)
{

    HANDLE hDevice;

    QString partition_style;

    std::wstring logicalDrive = L"\\\\.\\";
    wchar_t drive[3];
    drive[0] = partitions;
    drive[1] = L':';
    drive[2] = L'\0';
    logicalDrive.append(drive);

    hDevice = CreateFile(
                logicalDrive.c_str(),
                0,
                0,
                NULL,
                OPEN_EXISTING,
                0,
                NULL);

    DWORD bytesRet;
    DRIVE_LAYOUT_INFORMATION_EX* dlix = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(5120);

    if(dlix == NULL)
    {
        qDebug() << "Memory Allocation failed";
        CloseHandle(hDevice);
    }

    bool ioctlSucceed = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, (LPVOID)&dlix, 5120, (LPDWORD)&bytesRet, NULL);

    if(ioctlSucceed)
    {
        qDebug() << "Success";
        qDebug() << "Number of partitions : " << dlix->PartitionCount;

        switch(dlix->PartitionStyle){
        case PARTITION_STYLE_MBR:
            qDebug() << "Partition style is MBR";
            partition_style = "MBR";
            break;

        case PARTITION_STYLE_GPT:
            qDebug() << "Partition style is GPT";
            partition_style = "GPT";
            break;

        case PARTITION_STYLE_RAW:
            qDebug() << "Partition style is RAW";
            partition_style = "RAW";
            break;
        }
    }else{
        qDebug() << "DeviceIoControl failed with error : " << GetLastError();
    }

    free((void*) dlix);
    CloseHandle(hDevice);

    return partition_style;
}
0

Gdy uda mi się aby DeviceIoControl połączył się prawidłowo, to wartość dlix->PartitionStyle wynosi : 14593 zamiast 0 , 1 lub 2

0

Cześć

Być może powodem jest mieszanie IOCTL_DISK_GET_DRIVE_LAYOUT_EX z DISK_GEOMETRY_EX. Poniżej zamieszczam kod, który u mnie odpala się bez błędów i wartości na oko mają sens, choć nie sprawdzałem wszystkich dokładnie.

 
wstring lastErrorToString(DWORD err)
{
	LPWSTR messageBuffer = nullptr;
	size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, err, MAKELANGID(LANG_NEUTRAL,  SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL);

	std::wstring message(messageBuffer, size);
	LocalFree(messageBuffer);

	return message;
}

struct handle_deleter 
{
	void operator()(HANDLE h)
	{
		CloseHandle(h);
	}
};

void check_disk_partition_info()
{
	// "\\\\.\\PhysicalDrive0"
	// L"\\\\.\\C:"

	HANDLE hDevice = CreateFile(L"\\\\.\\C:", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, 0);
	if (hDevice != INVALID_HANDLE_VALUE)
	{
		unique_ptr<std::remove_pointer<HANDLE>::type, handle_deleter> uhDevice(hDevice);
		DWORD bytesRet;
		BOOL result;

		DISK_GEOMETRY_EX dgx;
		result = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &dgx, sizeof(dgx), &bytesRet, NULL);

		if (result)
		{
			cout << "BytesPerSector" << dgx.Geometry.BytesPerSector;
			cout << ", Cylinders: " << dgx.Geometry.Cylinders.QuadPart;
			cout << ", MediaType: " << dgx.Geometry.MediaType;
			cout << ", SectorsPerTrack: " << dgx.Geometry.SectorsPerTrack;
			cout << ", TracksPerCylinder: " << dgx.Geometry.TracksPerCylinder << endl <<endl;
		}
		else
		{
			DWORD err = GetLastError();
			wcout << L"Error: " << err << L", " << lastErrorToString(err) << endl;
		}
		

		//DRIVE_LAYOUT_INFORMATION_EX dlix;
		//result = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, &dlix, sizeof(dlix), &bytesRet, NULL); - such call does't work. Error 122 ERROR_INSUFFICIENT_BUFFER
		unique_ptr<unsigned char[]> buffer(new unsigned char[1024]);
		DRIVE_LAYOUT_INFORMATION_EX* dlix = (DRIVE_LAYOUT_INFORMATION_EX*) buffer.get();
		
		result = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, dlix, 1024, &bytesRet, NULL);

		if (result)
		{			
			cout << "PartitionLength: " << dlix->PartitionEntry[0].PartitionLength.QuadPart;
			cout << ", PartitionNumber: " << dlix->PartitionEntry[0].PartitionNumber;
			cout << ", PartitionStyle: " << dlix->PartitionEntry[0].PartitionStyle << endl;
			cout << ", RewritePartition: " << dlix->PartitionEntry[0].RewritePartition;
			cout << ", StartingOffset: " << dlix->PartitionEntry[0].StartingOffset.QuadPart;
		}
		else
		{
			DWORD err = GetLastError();
			wcout << L"Error: " << err << L", " << lastErrorToString(err) << endl;
		}
	}
}

Program wyświetla u mnie to (mam zwykły dysk magnetyczny 512 GB):

BytesPerSector512, Cylinders: 64601, MediaType: 12, SectorsPerTrack: 63, TracksPerCylinder: 240

PartitionLength: 524288000, PartitionNumber: 1, PartitionStyle: 0, RewritePartition: , StartingOffset: 1048576

0

@Tomek2 dzięki, działa :D Muszę przyznać, że te API Microsoftu jest trudne w ogarnięciu :P zwłaszcza jak ktoś nie zna j.Angielskiego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1