C ++ WINAPI создает несколько разделов на монтируемом виртуальном жестком диске - PullRequest
1 голос
/ 26 июня 2019

Мне удалось создать виртуальный жесткий диск и прикрепить его.После этого я создал диск (IOCTL CREATE_DISK) и установил его макет с помощью IOCTL_DISK_SET_DRIVE_LAYOUT_EX.Теперь, когда я проверяю диск через Управление дисками.У меня 14 МБ с разделом 7 МБ, как ожидается.

int sign = 80001;
CREATE_DISK disk;
disk.Mbr.Signature = sign;
disk.PartitionStyle = PARTITION_STYLE_MBR;

auto res = DeviceIoControl(device_handle, IOCTL_DISK_CREATE_DISK, &disk, sizeof(disk), NULL, 0, NULL, NULL);
res = DeviceIoControl(device_handle, IOCTL_DISK_UPDATE_PROPERTIES, 0, 0, NULL, 0, NULL, NULL);

LARGE_INTEGER partition_size;
partition_size.QuadPart = 0xF00;
DWORD driver_layout_ex_len = sizeof(DRIVE_LAYOUT_INFORMATION_EX);
DRIVE_LAYOUT_INFORMATION_EX driver_layout_info;
memset(&driver_layout_info, 0, sizeof(DRIVE_LAYOUT_INFORMATION_EX));

driver_layout_info.Mbr.Signature = sign;
driver_layout_info.PartitionCount = 1;
driver_layout_info.PartitionStyle = PARTITION_STYLE_MBR;

PARTITION_INFORMATION_EX part_info;
PARTITION_INFORMATION_MBR mbr_info;
part_info.StartingOffset.QuadPart = 32256;
part_info.RewritePartition = TRUE;
part_info.PartitionLength.QuadPart = partition_size.QuadPart/2 * 4096;
part_info.PartitionNumber = 1;
part_info.PartitionStyle = PARTITION_STYLE_MBR;

mbr_info.BootIndicator = TRUE;
mbr_info.HiddenSectors = 32256 / 512;
mbr_info.PartitionType = PARTITION_FAT32;
mbr_info.RecognizedPartition = 1;
part_info.Mbr = mbr_info;
driver_layout_info.PartitionEntry[0] = part_info;
auto res_layout = DeviceIoControl(device_handle, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, &driver_layout_info, sizeof(driver_layout_info), NULL, 0, NULL, NULL);

Теперь, как мне разбить этот диск на два раздела?Я хочу создать еще один раздел из неразделенной части диска (в основном другая половина).В документации сказано, что PartitionEntry - это массив переменных размеров (нет, это не массив размером 1.) Я называю set set IOCTL для каждого раздела, который я хочу создать?Если да, то как ты это делаешь?Возможно ли мульти-разделение через интерфейс WINAPI?

PS: я знаю, что люди обычно используют diskpart для этой работы.

Редактировать: Добавление второго макета второго раздела испортило мой стек, поэтому я выбрал другой маршрут (кучу).

DWORD driver_layout_ex_len = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX); // one layout+partition + partition
PDRIVE_LAYOUT_INFORMATION_EX driver_layout_info = (PDRIVE_LAYOUT_INFORMATION_EX) std::calloc(1, driver_layout_ex_len);

driver_layout_info->Mbr.Signature = sign;
driver_layout_info->PartitionCount = 2;
driver_layout_info->PartitionStyle = PARTITION_STYLE_MBR;
// omitted here..
PARTITION_INFORMATION_EX part_info2;
part_info2.StartingOffset.QuadPart = 32256 + part_info.PartitionLength.QuadPart;
part_info2.RewritePartition = TRUE;
part_info2.PartitionLength.QuadPart = partition_size.QuadPart / 2 * 4096;
part_info2.PartitionNumber = 2;
part_info2.PartitionStyle = PARTITION_STYLE_MBR;

part_info2.Mbr = mbr_info;


driver_layout_info->PartitionEntry[0] = part_info;
driver_layout_info->PartitionEntry[1] = part_info2;
auto res_layout = DeviceIoControl(device_handle, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, driver_layout_info, driver_layout_ex_len, NULL, 0, NULL, NULL);
auto res_err = GetLastError(); 

Так как он переопределял мой device_handle, я вообще не мог IOCTL,Это улучшение устранило это.Не забудьте передать driver_layout_info вместо & driver_layout_info после этого изменения.

1 Ответ

0 голосов
/ 27 июня 2019

В документации сказано, что PartitionEntry - это массив переменный размер (нет, это не массив размером 1).

"Некоторые структуры Windows имеют переменный размер, начиная с фиксированного заголовка, затем массив переменного размера. Когда эти структуры объявлены, они часто объявляют массив размером 1, где массив переменного размера должен быть ". См. @ блог Раймонда .

Здесь Структура DRIVE_LAYOUT_INFORMATION_EX является примером:

typedef struct _DRIVE_LAYOUT_INFORMATION_EX {
  DWORD                    PartitionStyle;
  DWORD                    PartitionCount;
  union {
    DRIVE_LAYOUT_INFORMATION_MBR Mbr;
    DRIVE_LAYOUT_INFORMATION_GPT Gpt;
  } DUMMYUNIONNAME;
  PARTITION_INFORMATION_EX PartitionEntry[1];
} DRIVE_LAYOUT_INFORMATION_EX, *PDRIVE_LAYOUT_INFORMATION_EX;

С помощью этого объявления вы бы выделяли память для одного такого структура DRIVE_LAYOUT_INFORMATION_EX переменного размера, подобная этой:

PDRIVE_LAYOUT_INFORMATION_EX driver_layout_info = (PDRIVE_LAYOUT_INFORMATION_EX)malloc(FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[NumberOfPartitions]));

Вы бы инициализировали структуру следующим образом (используйте в качестве примера 2 раздела):

DWORD NumberOfPartitions = 2;
LARGE_INTEGER partition_size;
partition_size.QuadPart = 0xF00;

PARTITION_INFORMATION_MBR mbr_info;
mbr_info.BootIndicator = TRUE;
mbr_info.HiddenSectors = 32256 / 512;
mbr_info.PartitionType = PARTITION_FAT32;
mbr_info.RecognizedPartition = TRUE;

PDRIVE_LAYOUT_INFORMATION_EX driver_layout_info = (PDRIVE_LAYOUT_INFORMATION_EX)malloc(FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[NumberOfPartitions]));
for (DWORD Index = 0; Index < NumberOfPartitions ; Index++) {

    driver_layout_info->PartitionEntry[Index].PartitionStyle = PARTITION_STYLE_MBR;
    driver_layout_info->PartitionEntry[Index].PartitionNumber = Index + 1;
    driver_layout_info->PartitionEntry[Index].RewritePartition = TRUE;
    driver_layout_info->PartitionEntry[Index].PartitionLength.QuadPart = partition_size.QuadPart / 2 * 4096;
    driver_layout_info->PartitionEntry[Index].Mbr = mbr_info;
}

driver_layout_info->Mbr.Signature = sign;
driver_layout_info->PartitionCount = 1;
driver_layout_info->PartitionStyle = PARTITION_STYLE_MBR;

driver_layout_info->PartitionEntry[0].StartingOffset.QuadPart = 32256;
driver_layout_info->PartitionEntry[1].StartingOffset.QuadPart = 32256 + driver_layout_info->PartitionEntry->StartingOffset.QuadPart;

DWORD driver_layout_ex_len = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX);

Позвоните free(driver_layout_info); после полного использования.

...