我们正尝试通过C ++程序在Windows Server 2008/2012上使用某些现有磁盘的属性来初始化磁盘。
我们使用磁盘pipe理控制代码中的 DeviceIoControl()
方法和IOCTL_DISK_CREATE_DISK
, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, IOCTL_DISK_SET_PARTITION_INFO_EX
代码使磁盘可供使用。
通过search得到了下面的代码片段
//To open the drive hDevice = CreateFile( TEXT("\\\\.\\PhysicalDrive7"), GENERIC_READ | GENERIC_WRITE, // no access to the drive FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL); // do not copy file attributes CREATE_DISK dsk; dsk.PartitionStyle = PARTITION_STYLE_MBR; //It can also be PARTITION_STYLE_GPT dsk.Mbr.Signature = 1; // Initialize disk bResult = DeviceIoControl( hDevice, // device to be queried IOCTL_DISK_CREATE_DISK, // operation to perform &dsk, sizeof(dsk), NULL, 0, // no output buffer &junk, // # bytes returned NULL ); LARGE_INTEGER lgPartitionSize; lgPartitionSize.QuadPart = (1024 * 1024 * 1024); DWORD dwDriverLayoutInfoExLen = sizeof (DRIVE_LAYOUT_INFORMATION_EX) + 3 * sizeof(PARTITION_INFORMATION_EX); DRIVE_LAYOUT_INFORMATION_EX *pdg = (DRIVE_LAYOUT_INFORMATION_EX *)new BYTE[dwDriverLayoutInfoExLen]; SecureZeroMemory(pdg, dwDriverLayoutInfoExLen); pdg->PartitionStyle = PARTITION_STYLE_MBR; pdg->PartitionCount = 1; pdg->Mbr.Signature = 1; pdg->PartitionEntry[0].PartitionStyle = PARTITION_STYLE_MBR; pdg->PartitionEntry[0].StartingOffset.QuadPart = 1048576; pdg->PartitionEntry[0].PartitionLength.QuadPart = lgPartitionSize.QuadPart * 200; pdg->PartitionEntry[0].PartitionNumber = 1; pdg->PartitionEntry[0].RewritePartition = TRUE; pdg->PartitionEntry[0].Mbr.PartitionType = PARTITION_NTFT; // PARTITION_IFS (NTFS partition or logical drive) pdg->PartitionEntry[0].Mbr.BootIndicator = TRUE; pdg->PartitionEntry[0].Mbr.RecognizedPartition = 1; pdg->PartitionEntry[0].Mbr.HiddenSectors = 32256 / 512; // Partition a disk bResult = DeviceIoControl( hDevice, // device to be queried IOCTL_DISK_SET_DRIVE_LAYOUT_EX, // operation to perform pdg, sizeof DRIVE_LAYOUT_INFORMATION_EX, //output buffer NULL, 0, // no output buffer &junk, // # bytes returned NULL ); bResult = DeviceIoControl( hDevice, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &junk, NULL); PARTITION_INFORMATION_EX dskinfo; PARTITION_INFORMATION_MBR mbrinfo; mbrinfo.PartitionType = PARTITION_NTFT; mbrinfo.HiddenSectors = (32256 / 512); mbrinfo.BootIndicator = 1; mbrinfo.RecognizedPartition = 1; dskinfo.PartitionStyle = PARTITION_STYLE_MBR; dskinfo.StartingOffset.QuadPart = 1048576;//0; dskinfo.PartitionLength.QuadPart = lgPartitionSize.QuadPart * 200; dskinfo.PartitionNumber = 1; dskinfo.RewritePartition = TRUE; dskinfo.Mbr = mbrinfo; bResult = DeviceIoControl( hDevice, // device to be queried IOCTL_DISK_SET_PARTITION_INFO_EX, // operation to perform &dskinfo, sizeof(dskinfo), // output buffer NULL, 0, // no output buffer &junk, // # bytes returned NULL );
所有对DeviceIoControl()
的调用都会成功,除了最后一个IOCTL_DISK_SET_PARTITION_INFO_EX
代码错误1(即不正确的函数)。 这可能是什么原因?
如果我们注释掉最后一次调用,磁盘正在初始化为原始磁盘,但这不符合我们的要求。
以上示例仅适用于MBR分区样式。 我们找不到GPT的样本,样式。 如果有人知道一个请给一个链接。
您正在使用IOCTL_DISK_SET_PARTITION_INFO_EX
错误的结构类型。 它需要SET_PARTITION_INFORMATION_EX
结构,而不是PARTITION_INFORMATION_EX
结构。
您可能不需要使用IOCTL_DISK_SET_PARTITION_INFO_EX
,因为它只是设置了分区类型,应该使用IOCTL_DISK_SET_PARTITION_INFO_EX
来设置分区类型。 不幸的是,你用它来设置错误的分区类型。 NTFS分区具有分区类型PARTITION_IFS
。
将lgPartitionSize
乘以200
几乎肯定是错误的。 如果lgPartitionSize
被认为是扇区的大小,那么你需要把它乘以磁盘的扇区大小。 硬盘的扇区大小总是512字节( 0x200
字节),但现代驱动器使用4096字节的扇区大小。
正确地创建分区表不是一件容易的事情,像你这样无意识地复制别人的代码是不行的。 即使解决了上面提到的问题,您仍然可能遇到其他问题。 你真的需要了解如何设置分区的所有限制。
您可能要考虑使用diskpart
命令来编程初始化磁盘而不是C ++代码。