如何通过 C++ 程序在 Windows server 2008/2012 上初始化磁盘
Posted
技术标签:
【中文标题】如何通过 C++ 程序在 Windows server 2008/2012 上初始化磁盘【英文标题】:How to initialize disk on Windows server 2008/2012 through a C++ program 【发布时间】:2014-09-11 16:30:17 【问题描述】:我们正在尝试通过 C++ 程序使用 Windows server 2008/2012 上某些现有磁盘的属性来初始化磁盘。
我们正在使用DeviceIoControl()
方法和来自Disk management control codes 的IOCTL_DISK_CREATE_DISK
、IOCTL_DISK_SET_DRIVE_LAYOUT_EX, IOCTL_DISK_SET_PARTITION_INFO_EX
代码来使磁盘可用。
搜索了一下得到如下代码sn-p
//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 的任何样本,...样式。如果有人知道,请给一个链接。
【问题讨论】:
【参考方案1】:您在IOCTL_DISK_SET_PARTITION_INFO_EX
中使用了错误的结构类型。它采用SET_PARTITION_INFORMATION_EX
结构,而不是PARTITION_INFORMATION_EX
结构。
您可能不需要使用IOCTL_DISK_SET_PARTITION_INFO_EX
,因为它只是设置分区类型,而应该已经使用IOCTL_DISK_SET_DRIVE_LAYOUT_EX
设置。不幸的是,您使用它设置了错误的分区类型。 NTFS 分区的分区类型为PARTITION_IFS
。
lgPartitionSize
乘以 200
几乎肯定是错误的。如果lgPartitionSize
应该是扇区的大小,那么您需要将其乘以磁盘的扇区大小。硬盘驱动器的扇区大小过去始终为 512 字节(0x200
字节),但现代驱动器使用 4096 字节的扇区大小。
正确创建分区表并不容易,像你所做的那样盲目地复制其他人的代码是行不通的。即使您解决了我上面提到的问题,您仍然可能会遇到其他问题。您确实需要了解如何布置分区的所有限制。
您可能需要考虑使用 diskpart
命令以编程方式初始化磁盘而不是 C++ 代码。
【讨论】:
以上是关于如何通过 C++ 程序在 Windows server 2008/2012 上初始化磁盘的主要内容,如果未能解决你的问题,请参考以下文章
32位机上用vs2008开发的c++程序如何能在64位系统下运行?
如何从 windows10 中的命令提示符生成 opencv 3.0 c++ 程序的 .exe?
C++ 程序在 Linux 上完美运行,但不能在 Windows 上运行
php artisan serve - 如何让mysql运行