1 /* 2 * PROJECT: ReactOS DiskPart 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/system/diskpart/create.c 5 * PURPOSE: Manages all the partitions of the OS in an interactive way. 6 * PROGRAMMERS: Lee Schroeder 7 */ 8 9 #include "diskpart.h" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 15 BOOL 16 CreateExtendedPartition( 17 _In_ INT argc, 18 _In_ PWSTR *argv) 19 { 20 PPARTENTRY PartEntry, NewPartEntry; 21 PLIST_ENTRY ListEntry; 22 ULONGLONG ullSize = 0ULL; 23 ULONGLONG ullSectorCount; 24 #if 0 25 ULONGLONG ullOffset = 0ULL; 26 BOOL bNoErr = FALSE; 27 #endif 28 INT i; 29 PWSTR pszSuffix = NULL; 30 NTSTATUS Status; 31 32 if (CurrentDisk == NULL) 33 { 34 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 35 return TRUE; 36 } 37 38 for (i = 3; i < argc; i++) 39 { 40 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 41 { 42 /* size=<N> (MB) */ 43 DPRINT("Size : %s\n", pszSuffix); 44 45 ullSize = _wcstoui64(pszSuffix, NULL, 10); 46 if ((ullSize == 0) && (errno == ERANGE)) 47 { 48 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 49 return TRUE; 50 } 51 } 52 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 53 { 54 /* offset=<N> (KB) */ 55 DPRINT("Offset : %s\n", pszSuffix); 56 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 57 #if 0 58 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 59 if ((ullOffset == 0) && (errno == ERANGE)) 60 { 61 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 62 return TRUE; 63 } 64 #endif 65 } 66 else if (HasPrefix(argv[i], L"align=", &pszSuffix)) 67 { 68 /* align=<N> */ 69 DPRINT("Align : %s\n", pszSuffix); 70 ConPuts(StdOut, L"The ALIGN option is not supported yet!\n"); 71 #if 0 72 bAlign = TRUE; 73 #endif 74 } 75 else if (_wcsicmp(argv[i], L"noerr") == 0) 76 { 77 /* noerr */ 78 DPRINT("NoErr\n", pszSuffix); 79 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 80 #if 0 81 bNoErr = TRUE; 82 #endif 83 } 84 else 85 { 86 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 87 return TRUE; 88 } 89 } 90 91 DPRINT1("Size: %I64u\n", ullSize); 92 #if 0 93 DPRINT1("Offset: %I64u\n", ullOffset); 94 #endif 95 96 if (GetPrimaryPartitionCount(CurrentDisk) >= 4) 97 { 98 ConPuts(StdOut, L"No space left for an extended partition!\n"); 99 return TRUE; 100 } 101 102 if (CurrentDisk->ExtendedPartition != NULL) 103 { 104 ConPuts(StdOut, L"We already have an extended partition on this disk!\n"); 105 return TRUE; 106 } 107 108 if (ullSize != 0) 109 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 110 else 111 ullSectorCount = 0; 112 113 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 114 115 ListEntry = CurrentDisk->PrimaryPartListHead.Blink; 116 117 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); 118 if (PartEntry->IsPartitioned) 119 { 120 ConPuts(StdOut, L"No disk space left for an extended partition!\n"); 121 return TRUE; 122 } 123 124 if (ullSectorCount == 0) 125 { 126 PartEntry->IsPartitioned = TRUE; 127 PartEntry->New = TRUE; 128 PartEntry->PartitionType = PARTITION_EXTENDED; 129 PartEntry->FormatState = Unformatted; 130 PartEntry->FileSystemName[0] = L'\0'; 131 132 CurrentPartition = PartEntry; 133 CurrentDisk->Dirty = TRUE; 134 } 135 else 136 { 137 if (PartEntry->SectorCount.QuadPart == ullSectorCount) 138 { 139 PartEntry->IsPartitioned = TRUE; 140 PartEntry->New = TRUE; 141 PartEntry->PartitionType = PARTITION_EXTENDED; 142 PartEntry->FormatState = Unformatted; 143 PartEntry->FileSystemName[0] = L'\0'; 144 145 CurrentPartition = PartEntry; 146 CurrentDisk->Dirty = TRUE; 147 } 148 else if (PartEntry->SectorCount.QuadPart > ullSectorCount) 149 { 150 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); 151 if (NewPartEntry == NULL) 152 { 153 ConPuts(StdOut, L"Memory allocation failed!\n"); 154 return TRUE; 155 } 156 157 NewPartEntry->DiskEntry = PartEntry->DiskEntry; 158 159 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; 160 NewPartEntry->SectorCount.QuadPart = ullSectorCount; 161 162 NewPartEntry->LogicalPartition = FALSE; 163 NewPartEntry->IsPartitioned = TRUE; 164 NewPartEntry->New = TRUE; 165 NewPartEntry->PartitionType = PARTITION_EXTENDED; 166 NewPartEntry->FormatState = Unformatted; 167 NewPartEntry->FileSystemName[0] = L'\0'; 168 169 PartEntry->StartSector.QuadPart += ullSectorCount; 170 PartEntry->SectorCount.QuadPart -= ullSectorCount; 171 172 InsertTailList(ListEntry, &NewPartEntry->ListEntry); 173 174 CurrentPartition = NewPartEntry; 175 CurrentDisk->Dirty = TRUE; 176 } 177 } 178 179 UpdateDiskLayout(CurrentDisk); 180 Status = WritePartitions(CurrentDisk); 181 if (!NT_SUCCESS(Status)) 182 { 183 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 184 CurrentPartition = NULL; 185 return TRUE; 186 } 187 188 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 189 190 return TRUE; 191 } 192 193 194 BOOL 195 CreateLogicalPartition( 196 _In_ INT argc, 197 _In_ PWSTR *argv) 198 { 199 PPARTENTRY PartEntry, NewPartEntry; 200 PLIST_ENTRY ListEntry; 201 ULONGLONG ullSize = 0ULL; 202 ULONGLONG ullSectorCount; 203 #if 0 204 ULONGLONG ullOffset = 0ULL; 205 BOOL bNoErr = FALSE; 206 #endif 207 UCHAR PartitionType = PARTITION_HUGE; 208 INT i, length; 209 PWSTR pszSuffix = NULL; 210 NTSTATUS Status; 211 212 if (CurrentDisk == NULL) 213 { 214 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 215 return TRUE; 216 } 217 218 for (i = 3; i < argc; i++) 219 { 220 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 221 { 222 /* size=<N> (MB) */ 223 DPRINT("Size : %s\n", pszSuffix); 224 225 ullSize = _wcstoui64(pszSuffix, NULL, 10); 226 if ((ullSize == 0) && (errno == ERANGE)) 227 { 228 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 229 return TRUE; 230 } 231 } 232 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 233 { 234 /* offset=<N> (KB) */ 235 DPRINT("Offset : %s\n", pszSuffix); 236 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 237 #if 0 238 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 239 if ((ullOffset == 0) && (errno == ERANGE)) 240 { 241 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 242 return TRUE; 243 } 244 #endif 245 } 246 else if (HasPrefix(argv[i], L"id=", &pszSuffix)) 247 { 248 /* id=<Byte>|<GUID> */ 249 DPRINT("Id : %s\n", pszSuffix); 250 251 length = wcslen(pszSuffix); 252 if ((length == 1) || (length == 2)) 253 { 254 /* Byte */ 255 PartitionType = (UCHAR)wcstoul(pszSuffix, NULL, 16); 256 if ((PartitionType == 0) && (errno == ERANGE)) 257 { 258 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 259 return TRUE; 260 } 261 } 262 #if 0 263 else if () 264 { 265 /* GUID */ 266 } 267 #endif 268 else 269 { 270 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 271 return TRUE; 272 } 273 } 274 else if (HasPrefix(argv[i], L"align=", &pszSuffix)) 275 { 276 /* align=<N> */ 277 DPRINT("Align : %s\n", pszSuffix); 278 ConPuts(StdOut, L"The ALIGN option is not supported yet!\n"); 279 #if 0 280 bAlign = TRUE; 281 #endif 282 } 283 else if (_wcsicmp(argv[i], L"noerr") == 0) 284 { 285 /* noerr */ 286 DPRINT("NoErr\n", pszSuffix); 287 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 288 #if 0 289 bNoErr = TRUE; 290 #endif 291 } 292 else 293 { 294 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 295 return TRUE; 296 } 297 } 298 299 DPRINT1("Size: %I64u\n", ullSize); 300 #if 0 301 DPRINT1("Offset: %I64u\n", ullOffset); 302 #endif 303 DPRINT1("Partition Type: %hx\n", PartitionType); 304 305 if (ullSize != 0) 306 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 307 else 308 ullSectorCount = 0; 309 310 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 311 312 for (ListEntry = CurrentDisk->LogicalPartListHead.Flink; 313 ListEntry != &CurrentDisk->LogicalPartListHead; 314 ListEntry = ListEntry->Flink) 315 { 316 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); 317 if (PartEntry->IsPartitioned) 318 continue; 319 320 if (ullSectorCount == 0) 321 { 322 PartEntry->IsPartitioned = TRUE; 323 PartEntry->New = TRUE; 324 PartEntry->PartitionType = PartitionType; 325 PartEntry->FormatState = Unformatted; 326 PartEntry->FileSystemName[0] = L'\0'; 327 328 CurrentPartition = PartEntry; 329 CurrentDisk->Dirty = TRUE; 330 break; 331 } 332 else 333 { 334 if (PartEntry->SectorCount.QuadPart == ullSectorCount) 335 { 336 PartEntry->IsPartitioned = TRUE; 337 PartEntry->New = TRUE; 338 PartEntry->PartitionType = PartitionType; 339 PartEntry->FormatState = Unformatted; 340 PartEntry->FileSystemName[0] = L'\0'; 341 342 CurrentPartition = PartEntry; 343 CurrentDisk->Dirty = TRUE; 344 break; 345 } 346 else if (PartEntry->SectorCount.QuadPart > ullSectorCount) 347 { 348 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); 349 if (NewPartEntry == NULL) 350 { 351 ConPuts(StdOut, L"Memory allocation failed!\n"); 352 return TRUE; 353 } 354 355 NewPartEntry->DiskEntry = PartEntry->DiskEntry; 356 357 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; 358 NewPartEntry->SectorCount.QuadPart = ullSectorCount; 359 360 NewPartEntry->LogicalPartition = TRUE; 361 NewPartEntry->IsPartitioned = TRUE; 362 NewPartEntry->New = TRUE; 363 NewPartEntry->PartitionType = PartitionType; 364 NewPartEntry->FormatState = Unformatted; 365 NewPartEntry->FileSystemName[0] = L'\0'; 366 367 PartEntry->StartSector.QuadPart += ullSectorCount; 368 PartEntry->SectorCount.QuadPart -= ullSectorCount; 369 370 InsertTailList(ListEntry, &NewPartEntry->ListEntry); 371 372 CurrentPartition = NewPartEntry; 373 CurrentDisk->Dirty = TRUE; 374 break; 375 } 376 } 377 } 378 379 UpdateDiskLayout(CurrentDisk); 380 Status = WritePartitions(CurrentDisk); 381 if (!NT_SUCCESS(Status)) 382 { 383 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 384 CurrentPartition = NULL; 385 return TRUE; 386 } 387 388 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 389 390 return TRUE; 391 } 392 393 394 BOOL 395 CreatePrimaryPartition( 396 _In_ INT argc, 397 _In_ PWSTR *argv) 398 { 399 PPARTENTRY PartEntry, NewPartEntry; 400 PLIST_ENTRY ListEntry; 401 ULONGLONG ullSize = 0ULL; 402 ULONGLONG ullSectorCount; 403 #if 0 404 ULONGLONG ullOffset = 0ULL; 405 BOOL bNoErr = FALSE; 406 #endif 407 UCHAR PartitionType = PARTITION_HUGE; 408 INT i, length; 409 PWSTR pszSuffix = NULL; 410 NTSTATUS Status; 411 412 if (CurrentDisk == NULL) 413 { 414 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 415 return TRUE; 416 } 417 418 for (i = 3; i < argc; i++) 419 { 420 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 421 { 422 /* size=<N> (MB) */ 423 DPRINT("Size : %s\n", pszSuffix); 424 425 ullSize = _wcstoui64(pszSuffix, NULL, 10); 426 if ((ullSize == 0) && (errno == ERANGE)) 427 { 428 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 429 return TRUE; 430 } 431 } 432 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 433 { 434 /* offset=<N> (KB) */ 435 DPRINT("Offset : %s\n", pszSuffix); 436 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 437 #if 0 438 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 439 if ((ullOffset == 0) && (errno == ERANGE)) 440 { 441 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 442 return TRUE; 443 } 444 #endif 445 } 446 else if (HasPrefix(argv[i], L"id=", &pszSuffix)) 447 { 448 /* id=<Byte>|<GUID> */ 449 DPRINT("Id : %s\n", pszSuffix); 450 451 length = wcslen(pszSuffix); 452 if ((length == 1) || (length == 2)) 453 { 454 /* Byte */ 455 PartitionType = (UCHAR)wcstoul(pszSuffix, NULL, 16); 456 if ((PartitionType == 0) && (errno == ERANGE)) 457 { 458 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 459 return TRUE; 460 } 461 } 462 #if 0 463 else if () 464 { 465 /* GUID */ 466 } 467 #endif 468 else 469 { 470 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 471 return TRUE; 472 } 473 } 474 else if (HasPrefix(argv[i], L"align=", &pszSuffix)) 475 { 476 /* align=<N> */ 477 DPRINT("Align : %s\n", pszSuffix); 478 ConPuts(StdOut, L"The ALIGN option is not supported yet!\n"); 479 #if 0 480 bAlign = TRUE; 481 #endif 482 } 483 else if (_wcsicmp(argv[i], L"noerr") == 0) 484 { 485 /* noerr */ 486 DPRINT("NoErr\n", pszSuffix); 487 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 488 #if 0 489 bNoErr = TRUE; 490 #endif 491 } 492 else 493 { 494 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 495 return TRUE; 496 } 497 } 498 499 DPRINT1("Size: %I64u\n", ullSize); 500 #if 0 501 DPRINT1("Offset: %I64u\n", ullOffset); 502 #endif 503 DPRINT1("Partition Type: %hx\n", PartitionType); 504 505 if (GetPrimaryPartitionCount(CurrentDisk) >= 4) 506 { 507 ConPuts(StdOut, L"No space left for another primary partition!\n"); 508 return TRUE; 509 } 510 511 if (ullSize != 0) 512 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 513 else 514 ullSectorCount = 0; 515 516 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 517 518 for (ListEntry = CurrentDisk->PrimaryPartListHead.Flink; 519 ListEntry != &CurrentDisk->PrimaryPartListHead; 520 ListEntry = ListEntry->Flink) 521 { 522 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); 523 if (PartEntry->IsPartitioned) 524 continue; 525 526 if (ullSectorCount == 0) 527 { 528 PartEntry->IsPartitioned = TRUE; 529 PartEntry->New = TRUE; 530 PartEntry->PartitionType = PartitionType; 531 PartEntry->FormatState = Unformatted; 532 PartEntry->FileSystemName[0] = L'\0'; 533 534 CurrentPartition = PartEntry; 535 CurrentDisk->Dirty = TRUE; 536 break; 537 } 538 else 539 { 540 if (PartEntry->SectorCount.QuadPart == ullSectorCount) 541 { 542 PartEntry->IsPartitioned = TRUE; 543 PartEntry->New = TRUE; 544 PartEntry->PartitionType = PartitionType; 545 PartEntry->FormatState = Unformatted; 546 PartEntry->FileSystemName[0] = L'\0'; 547 548 CurrentPartition = PartEntry; 549 CurrentDisk->Dirty = TRUE; 550 break; 551 } 552 else if (PartEntry->SectorCount.QuadPart > ullSectorCount) 553 { 554 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); 555 if (NewPartEntry == NULL) 556 { 557 ConPuts(StdOut, L"Memory allocation failed!\n"); 558 return TRUE; 559 } 560 561 NewPartEntry->DiskEntry = PartEntry->DiskEntry; 562 563 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; 564 NewPartEntry->SectorCount.QuadPart = ullSectorCount; 565 566 NewPartEntry->LogicalPartition = FALSE; 567 NewPartEntry->IsPartitioned = TRUE; 568 NewPartEntry->New = TRUE; 569 NewPartEntry->PartitionType = PartitionType; 570 NewPartEntry->FormatState = Unformatted; 571 NewPartEntry->FileSystemName[0] = L'\0'; 572 573 PartEntry->StartSector.QuadPart += ullSectorCount; 574 PartEntry->SectorCount.QuadPart -= ullSectorCount; 575 576 InsertTailList(ListEntry, &NewPartEntry->ListEntry); 577 578 CurrentPartition = NewPartEntry; 579 CurrentDisk->Dirty = TRUE; 580 break; 581 } 582 } 583 } 584 585 UpdateDiskLayout(CurrentDisk); 586 Status = WritePartitions(CurrentDisk); 587 if (!NT_SUCCESS(Status)) 588 { 589 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 590 CurrentPartition = NULL; 591 return TRUE; 592 } 593 594 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 595 596 return TRUE; 597 } 598