WIN32 API创建USB分区后显示RAW格式问题求助
问题描述
我尝试用WIN32 API格式化USB驱动器,已经成功创建了指定大小的分区,但该分区始终显示为RAW格式。即便我在信息结构体里传入了PARTITION_IFS(对应NTFS)类型,问题还是没解决。以下是相关代码:
const PARTITION_STYLE gptMbr = args.useUefi ? PARTITION_STYLE_GPT : PARTITION_STYLE_MBR; //const TCHAR driveLetter[] = { _T('\\'), _T('\\'), _T('.'), _T('\\'), args.driveLabel, (':'), _T('\0') }; const TCHAR driveLetter[] = "\\\\.\\PHYSICALDRIVE4"; HANDLE drive = CreateFile(driveLetter, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); DWORD err = GetLastError(); if (drive == INVALID_HANDLE_VALUE) return FERR_CANT_OPEN_DRIVE; // Close handle on exit ScopeExit exit([&drive]() { CloseHandle(drive); }); CREATE_DISK diskArgs; memset(&diskArgs, 0, sizeof(CREATE_DISK)); CREATE_DISK_MBR dskMbr = { 0 }; dskMbr.Signature = 1; diskArgs.PartitionStyle = gptMbr; diskArgs.Mbr = dskMbr; if (!DeviceIoControl(drive, IOCTL_DISK_CREATE_DISK, &diskArgs, sizeof(diskArgs), NULL, 0, NULL, NULL)) return FERR_FORMAT_FAILURE; // listen for MSR partition arrival if using GPT if (args.useUefi) { } // drive size GET_LENGTH_INFORMATION lenInfo = { 0 }; if (!DeviceIoControl(drive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &lenInfo, sizeof(lenInfo), NULL, NULL)) return FERR_FORMAT_FAILURE; const size_t nLayoutBytes = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX) * 3; DRIVE_LAYOUT_INFORMATION_EX* layout = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(nLayoutBytes); memset(layout, 0, nLayoutBytes); layout->PartitionStyle = gptMbr; layout->PartitionCount = 1; layout->Mbr.Signature = diskArgs.Mbr.Signature; PARTITION_INFORMATION_EX& partition = layout->PartitionEntry[0]; partition.PartitionStyle = gptMbr; partition.StartingOffset.QuadPart = 0; partition.PartitionLength.QuadPart = lenInfo.Length.QuadPart; //3221225472; partition.PartitionNumber = 1; partition.RewritePartition = TRUE; partition.IsServicePartition = FALSE; partition.Mbr.PartitionType = PARTITION_IFS; partition.Mbr.BootIndicator = FALSE; partition.Mbr.RecognizedPartition = TRUE; partition.Mbr.HiddenSectors = 0; if (!DeviceIoControl(drive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, layout, nLayoutBytes, NULL, 0, NULL, NULL)) return FERR_FORMAT_FAILURE; return FERR_OK;
问题原因分析
- 未创建实际文件系统:设置
PARTITION_IFS只是标记分区为IFS类文件系统(如NTFS、FAT32)的用途,并不会自动在分区上写入文件系统的核心结构(引导扇区、MFT等)。RAW格式的本质就是分区无有效文件系统。 - GPT分区参数缺失:如果是GPT分区,代码仅设置了MBR相关字段,未指定GPT分区的类型GUID(如
PARTITION_BASIC_DATA_GUID),系统无法正确识别分区用途。 - 起始偏移错误:将分区起始偏移设为
0会覆盖磁盘的MBR/GPT表头区域,导致分区表损坏或无法被系统正确识别。MBR磁盘需跳过前2048扇区(1MB对齐),GPT磁盘同样需避开表头和分区表区域。
修复方案
1. 修正分区起始偏移
调整分区起始偏移为1MB对齐值,避免覆盖磁盘结构:
// 1MB = 1024*1024字节 = 2048扇区(每扇区512字节) partition.StartingOffset.QuadPart = 1024LL * 1024; // 分区长度需减去起始偏移的大小 partition.PartitionLength.QuadPart = lenInfo.Length.QuadPart - partition.StartingOffset.QuadPart;
2. 补充GPT分区参数
如果使用GPT分区,需添加GUID类型设置:
#include <initguid.h> // 定义基础数据分区GUID DEFINE_GUID(GUID_PARTITION_BASIC_DATA, 0xEBD0A0A2, 0xB9E5, 0x4433, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7); // 在设置分区参数时添加 if (gptMbr == PARTITION_STYLE_GPT) { partition.Gpt.PartitionTypeGuid = GUID_PARTITION_BASIC_DATA; partition.Gpt.Attributes = 0; // 可根据需求设置,如PARTITION_ATTRIBUTE_NO_DRIVE_LETTER wcsncpy_s(partition.Gpt.Name, L"Basic Data Partition", _TRUNCATE); }
3. 添加格式化步骤
创建分区后,需为分区分配驱动器号并执行格式化操作,以下是示例代码:
// 步骤1:枚举卷获取分区的驱动器号(简化示例,实际需通过IOCTL_DISK_GET_PARTITION_INFO_EX或FindFirstVolume等API获取) TCHAR volumePath[MAX_PATH] = L"\\\\.\\E:"; // 替换为实际分区路径 HANDLE hPartition = CreateFile(volumePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hPartition != INVALID_HANDLE_VALUE) { // 步骤2:执行快速格式化(以NTFS为例) TCHAR formatCmd[MAX_PATH]; _stprintf_s(formatCmd, MAX_PATH, _T("format %c: /FS:NTFS /Q /Y"), volumePath[4]); // 使用CreateProcess执行命令,避免阻塞主线程(此处用system简化示例) system(formatCmd); CloseHandle(hPartition); }
4. 确保管理员权限
格式化磁盘需要管理员权限,需确保程序以管理员身份运行,否则DeviceIoControl和格式化命令会因权限不足失败。
内容的提问来源于stack exchange,提问作者Tommy Bowles
相关产品推荐
相关产品推荐

