winapi — Ошибка разбиения и форматирования флешки в Stack Overflow

Я застрял, пытаясь переразметить и отформатировать флешку с помощью C ++, любая помощь будет отличной!

Цель состоит в том, чтобы переразбить любой произвольный флеш-накопитель одним разделом, занимающим все пространство и отформатированным FAT32 (более поздние варианты NTFS и EXFAT). Это будет сделано в пакетном режиме, надеюсь, с 50+ устройствами одновременно, поэтому доступ к букве диска не вариант. Я могу создать раздел, но когда я пытаюсь IOCTL_DISK_SET_PARTITION_INFO_EX для установки типа формата, происходит сбой с 0x32, ERROR_NOT_SUPPORTED. Но не понятно, что именно не поддерживается. Я могу вручную разбить устройство на разделы с помощью таких утилит, как diskpart, поэтому я знаю, что устройство поддерживает типы разделов и файловых систем. Кто-нибудь может помочь? Мой полный исходный код приведен ниже, он не срабатывает при вызове DeviceIoControl () с IOCTL_DISK_SET_PARTITION_INFO_EX.

#include "stdafx.h"#include <random>
#include <Windows.h>
#include <atlstr.h>
#include <iostream>
#include <assert.h>using namespace std;

#define THROW_CSTRING(a, b) { CString csE; csE.Format(a, b); throw csE; }
#define RANDOM_DWORD {DWORD(rand()) | DWORD(rand() << 8) | DWORD(rand() << 16) | DWORD(rand() << 24)}int main()
{
DRIVE_LAYOUT_INFORMATION_EX* pdg = NULL;
HANDLE hDevice = INVALID_HANDLE_VALUE;

try
{

hDevice = CreateFile(L"\\\\.\\PhysicalDrive2",
GENERIC_READ | GENERIC_WRITE,
0,              // Only we can access
NULL,           // Default security
OPEN_EXISTING,  // For hardware, open existing
0,              // File attributes
NULL);          //Do not copy attributes
if (hDevice == INVALID_HANDLE_VALUE)
{
THROW_CSTRING(L"ERROR: CreateFile() failed: 0x%x", GetLastError());
}

CREATE_DISK dsk;
memset(&dsk, 0, sizeof(dsk));
CREATE_DISK_MBR dskmbr = { 0 };
dskmbr.Signature = 1;
dsk.PartitionStyle = PARTITION_STYLE_MBR;
dsk.Mbr = dskmbr;

// DRIVE_LAYOUT_INFORMAITON_EX has an array of partition info at the end, need enough for 4 partitions minimum
int iDriveLayoutBytesRequired = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX) * 3;
pdg = (DRIVE_LAYOUT_INFORMATION_EX*)new BYTE[iDriveLayoutBytesRequired];
memset(pdg, 0, iDriveLayoutBytesRequired);

DRIVE_LAYOUT_INFORMATION_MBR mbrlayout = { 0 };
mbrlayout.Signature = RANDOM_DWORD;
pdg->PartitionStyle = PARTITION_STYLE_MBR;
pdg->Mbr = mbrlayout;
pdg->PartitionCount = 1;

DWORD dwBytesReturned = 0;if (!DeviceIoControl(hDevice, IOCTL_DISK_CREATE_DISK, &dsk, sizeof(dsk), NULL, 0, &dwBytesReturned, NULL))
{
THROW_CSTRING(L"ERROR: IOCTL_DISK_CREATE_DISK failed: 0x%x", GetLastError());
}// Get the drive dimensions, then use that info to create a new partition

// Drive length
GET_LENGTH_INFORMATION sLenInfo = { 0 };
if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &sLenInfo, sizeof(sLenInfo), &dwBytesReturned, NULL))
{
THROW_CSTRING(L"ERROR: IOCTL_DISK_GET_LENGTH_INFO failed: 0x%x", GetLastError());
}
assert(sizeof(sLenInfo.Length.QuadPart) == sizeof(__int64));
__int64 iDiskLengthBytes = sLenInfo.Length.QuadPart;pdg->PartitionStyle = PARTITION_STYLE_MBR;
pdg->PartitionCount = 4;
pdg->Mbr.Signature = 1;

pdg->PartitionEntry[0].PartitionStyle = PARTITION_STYLE_MBR;
pdg->PartitionEntry[0].StartingOffset.QuadPart = 0;
pdg->PartitionEntry[0].PartitionLength.QuadPart = iDiskLengthBytes;
pdg->PartitionEntry[0].PartitionNumber = 1;
pdg->PartitionEntry[0].RewritePartition = TRUE;

//pdg->PartitionEntry[0].Mbr.PartitionType = PARTITION_IFS; // NTFS
pdg->PartitionEntry[0].Mbr.PartitionType = PARTITION_FAT32;
pdg->PartitionEntry[0].Mbr.BootIndicator = TRUE;
pdg->PartitionEntry[0].Mbr.RecognizedPartition = 1;
pdg->PartitionEntry[0].Mbr.HiddenSectors = 0;// Partition device
if (!DeviceIoControl(hDevice, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, pdg, iDriveLayoutBytesRequired, NULL, 0, &dwBytesReturned, NULL))
{
THROW_CSTRING(L"ERROR: IOCTL_DISK_SEt_DRIVE_LAYOUT_EX failed: 0x%x", GetLastError());
}

// Tell the driver to flush its cache
if (!DeviceIoControl(hDevice, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwBytesReturned, NULL))
{
THROW_CSTRING(L"ERROR: IOCTL_DISK_UPDATE_PROPERTIES failed: 0x%x", GetLastError());
}

SET_PARTITION_INFORMATION_EX dskinfo;
memset(&dskinfo, 0, sizeof(dskinfo));
dskinfo.PartitionStyle = PARTITION_STYLE_MBR;
dskinfo.Mbr.PartitionType = PARTITION_FAT32;

if (!DeviceIoControl(hDevice, IOCTL_DISK_SET_PARTITION_INFO_EX, &dskinfo, sizeof(dskinfo), NULL, 0, &dwBytesReturned, NULL))
{
THROW_CSTRING(L"ERROR: IOCTL_DISK_SET_PARTITION_INFO_EX failed: 0x%x", GetLastError());
}

}

catch (CString csErr)
{
// Error lookup: https://msdn.microsoft.com/en-us/library/w indows/desktop/ms681382(v=vs.85).aspx
// 0x7a - ERROR_INSUFFICIENT_BUFFER
// 0x57 - ERROR_INVALID_PARAMETER
// 0x32 - ERROR_NOT_SUPPORTED
// 0x18 - ERROR_BAD_LENGTH
// 0x05 - ERROR_ACCESS_DENIED
wcout << csErr.GetString();
}

CloseHandle(hDevice);
delete pdg;
return 0;
}

0

Решение

У меня есть решение, но оно немного запутанное. Я использую DeviceIoControl (), как указано выше, для разбиения диска. Затем я использую VDS и интерфейс IID_IVdsVolumeMF для создания файловой системы, но для этого нужно немного поработать. Цель состоит в том, чтобы разбить и отформатировать все флеш-накопители (флешки) в системе. VDS будет выполнять форматирование через интерфейс IID_IVdsVolumeMF, НО он не скажет вам (по крайней мере, я не выяснил, как), какие устройства являются съемными. Но WMI скажет вам, какие устройства являются съемными, но не имеет функции форматирования. Так…

Сначала используйте WMI, чтобы получить список всех съемный пути томов в системе, например:

CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc)
pLoc->ConnectServer(CComBSTR(L"ROOT\\CIMV2"), nullptr, nullptr, nullptr, 0, nullptr, nullptr, pWbemSvc)
CoSetProxyBlanket(
*pWbemSvc,                        // Indicates the proxy to set
RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
NULL,                        // Server principal name
RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL,                        // client identity
EOAC_NONE                    // proxy capabilities

pWbemSvc->ExecQuery(CComBSTR(L"WQL"), CComBSTR(L"SELECT * FROM Win32_Volume WHERE DriveType=2"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator)

Дает вам такие пути, как:

 L"\\\\?\\Volume{3899cb7b-7c3f-11e6-bf82-005056c00008}\\"

Затем используйте VDS, чтобы получить список всех томов VDS на машине. В основном вы загружаете VDS, а затем получаете всех поставщиков программного обеспечения. В этом источнике для краткости отсутствуют детали, но я думаю, что оставил достаточно, чтобы объяснить, что происходит:

pSvc->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS, &pEnumProviders)

Теперь рассмотрим список поставщиков, получающих пакеты от каждого поставщика:

pEnumProviders->Next(1, &pUnk, &cFetched)
pProv = pUnk;
pProv->QueryPacks(&pEnumpacks)
vPacks.push_back(pEnumpacks);

Теперь перебираем пакеты и получаем все тома в каждом пакете:

iterator iPacks = vPacks.begin();
(*iPacks)->Next(1, &pUnk, &cFetched)
pPack = pUnk;
pPack->QueryVolumes(&pEnumvolumes)
pvpEnumvolumes->push_back(pEnumvolumes)

Теперь у вас есть список путей к съемным устройствам, и у вас есть список всех томов в системе. Время сравнить их и выяснить, какие тома являются съемный.

iVolEnum = pvpEnumOfVDSVolumes->begin()
(*iVolEnum)->Next(1, &pUnk, &cFetched)
pVMF3 = pUnk;
CComHeapPtr<LPWSTR> pVDSVolumePaths;
pVMF3->QueryVolumeGuidPathnames(&pVDSVolumePaths, &nPaths)
iterator iWMIVolPath = pvWMIRemovableVols->begin();
loop..
if (wcscmp(iWMIVolPath->data(), pVDSVolumePaths[i]) == 0)
{  // VDS Vol is removable! }

Теперь используйте этот объект тома VDS для форматирования тома:

foreach( vol in vRemovableVDSVols )
{
CComQIPtr<IVdsVolume> pVolume = *(vol);
IVdsVolumeMF *pVolumeMF;
pVolume->QueryInterface(IID_IVdsVolumeMF, (void **)&pVolumeMF);
pVolumeMF->Format(  VDS_FST_FAT32,
L"MyFob",
512, // alloc size
true, // force
false, // quick
false, // compression
&pAsync); // async
}

И престо твой флешка отформатирован! Фух … но, похоже, работает.

Неужели Microsoft не могла сделать это проще?

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]