Как инициализировать диск на Windows Server 2008/2012 через программу на C++

Мы пытаемся инициализировать диск со свойствами какого-то существующего диска на сервере Windows 2008/2012 через программу C++.

Мы используем метод DeviceIoControl() и коды IOCTL_DISK_CREATE_DISK, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, IOCTL_DISK_SET_PARTITION_INFO_EX из кодов управления управлением дисками. сделать диск доступным для использования.

Получил следующий фрагмент кода, немного поискав

//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,... стилей. Дайте ссылку, если кто-то знает.


person prasad    schedule 11.09.2014    source источник


Ответы (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++.

person Ross Ridge    schedule 13.09.2014