Reactos
at master 1100 lines 31 kB view raw
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 14static 15PPARTENTRY 16InsertGptPartition( 17 _In_ PDISKENTRY pDisk, 18 _In_ ULONGLONG ullSectorSize, 19 _In_ const GUID *pPartitionType) 20{ 21 PPARTENTRY PartEntry, NewPartEntry; 22 PLIST_ENTRY ListEntry; 23 24 for (ListEntry = pDisk->PrimaryPartListHead.Flink; 25 ListEntry != &CurrentDisk->PrimaryPartListHead; 26 ListEntry = ListEntry->Flink) 27 { 28 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); 29 if (PartEntry->IsPartitioned) 30 continue; 31 32 if (ullSectorSize == 0ULL) 33 { 34 DPRINT("Claim whole unused space!\n"); 35 PartEntry->IsPartitioned = TRUE; 36 PartEntry->New = TRUE; 37 CopyMemory(&PartEntry->Gpt.PartitionType, pPartitionType, sizeof(GUID)); 38 CreateGUID(&PartEntry->Gpt.PartitionId); 39 PartEntry->Gpt.Attributes = 0ULL; 40 PartEntry->PartitionNumber = 0; 41 PartEntry->FormatState = Unformatted; 42 PartEntry->FileSystemName[0] = L'\0'; 43 44 return PartEntry; 45 } 46 else 47 { 48 if (ullSectorSize == PartEntry->SectorCount.QuadPart) 49 { 50 DPRINT("Claim matching unused space!\n"); 51 PartEntry->IsPartitioned = TRUE; 52 PartEntry->New = TRUE; 53 CopyMemory(&PartEntry->Gpt.PartitionType, pPartitionType, sizeof(GUID)); 54 CreateGUID(&PartEntry->Gpt.PartitionId); 55 PartEntry->Gpt.Attributes = 0ULL; 56 PartEntry->PartitionNumber = 0; 57 PartEntry->FormatState = Unformatted; 58 PartEntry->FileSystemName[0] = L'\0'; 59 60 return PartEntry; 61 } 62 else if (ullSectorSize < PartEntry->SectorCount.QuadPart) 63 { 64 DPRINT("Claim part of unused space\n"); 65 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); 66 if (NewPartEntry == NULL) 67 { 68 ConPuts(StdOut, L"Memory allocation failed!\n"); 69 return NULL; 70 } 71 72 NewPartEntry->DiskEntry = PartEntry->DiskEntry; 73 74 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; 75 NewPartEntry->SectorCount.QuadPart = ullSectorSize; 76 77 NewPartEntry->LogicalPartition = FALSE; 78 NewPartEntry->IsPartitioned = TRUE; 79 NewPartEntry->New = TRUE; 80 CopyMemory(&NewPartEntry->Gpt.PartitionType, pPartitionType, sizeof(GUID)); 81 CreateGUID(&NewPartEntry->Gpt.PartitionId); 82 NewPartEntry->Gpt.Attributes = 0ULL; 83 NewPartEntry->PartitionNumber = 0; 84 NewPartEntry->FormatState = Unformatted; 85 NewPartEntry->FileSystemName[0] = L'\0'; 86 87 PartEntry->StartSector.QuadPart += ullSectorSize; 88 PartEntry->SectorCount.QuadPart -= ullSectorSize; 89 90 InsertTailList(ListEntry, &NewPartEntry->ListEntry); 91 92 return NewPartEntry; 93 } 94 } 95 } 96 97 return NULL; 98} 99 100 101EXIT_CODE 102CreateEfiPartition( 103 _In_ INT argc, 104 _In_ PWSTR *argv) 105{ 106 PPARTENTRY PartEntry; 107 ULONGLONG ullSize = 0ULL; 108 ULONGLONG ullSectorCount; 109#if 0 110 BOOL bNoErr = FALSE; 111#endif 112 INT i; 113 PWSTR pszSuffix = NULL; 114 NTSTATUS Status; 115 116 DPRINT1("CreateEfiPartition()\n"); 117 118 if (CurrentDisk == NULL) 119 { 120 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 121 return EXIT_SUCCESS; 122 } 123 124 if (CurrentDisk->PartitionStyle != PARTITION_STYLE_GPT) 125 { 126 ConResPuts(StdOut, IDS_CREATE_PARTITION_INVALID_STYLE); 127 return EXIT_SUCCESS; 128 } 129 130 for (i = 3; i < argc; i++) 131 { 132 if (_wcsicmp(argv[i], L"noerr") == 0) 133 { 134 /* noerr */ 135 DPRINT("NoErr\n", pszSuffix); 136 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 137#if 0 138 bNoErr = TRUE; 139#endif 140 } 141 } 142 143 for (i = 3; i < argc; i++) 144 { 145 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 146 { 147 /* size=<N> (MB) */ 148 DPRINT("Size : %s\n", pszSuffix); 149 150 ullSize = _wcstoui64(pszSuffix, NULL, 10); 151 if ((ullSize == 0) && (errno == ERANGE)) 152 { 153 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 154 return EXIT_SUCCESS; 155 } 156 } 157 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 158 { 159 /* offset=<N> (KB) */ 160 DPRINT("Offset : %s\n", pszSuffix); 161 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 162#if 0 163 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 164 if ((ullOffset == 0) && (errno == ERANGE)) 165 { 166 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 167 return EXIT_SUCCESS; 168 } 169#endif 170 } 171 else if (_wcsicmp(argv[i], L"noerr") == 0) 172 { 173 /* noerr - Already handled above */ 174 } 175 else 176 { 177 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 178 return EXIT_SUCCESS; 179 } 180 } 181 182 DPRINT1("Size: %I64u\n", ullSize); 183#if 0 184 DPRINT1("Offset: %I64u\n", ullOffset); 185#endif 186 187 /* Size */ 188 if (ullSize != 0) 189 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 190 else 191 ullSectorCount = 0; 192 193 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 194 195#ifdef DUMP_PARTITION_LIST 196 DumpPartitionList(CurrentDisk); 197#endif 198 199 PartEntry = InsertGptPartition(CurrentDisk, 200 ullSectorCount, 201 &PARTITION_SYSTEM_GUID); 202 if (PartEntry == FALSE) 203 { 204 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 205 CurrentPartition = NULL; 206 return EXIT_SUCCESS; 207 } 208 209 CurrentPartition = PartEntry; 210 CurrentDisk->Dirty = TRUE; 211 212#ifdef DUMP_PARTITION_LIST 213 DumpPartitionList(CurrentDisk); 214#endif 215 216 UpdateGptDiskLayout(CurrentDisk, FALSE); 217 Status = WriteGptPartitions(CurrentDisk); 218 if (!NT_SUCCESS(Status)) 219 { 220 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 221 CurrentPartition = NULL; 222 return EXIT_SUCCESS; 223 } 224 225 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 226 227 return EXIT_SUCCESS; 228} 229 230 231EXIT_CODE 232CreateExtendedPartition( 233 _In_ INT argc, 234 _In_ PWSTR *argv) 235{ 236 PPARTENTRY PartEntry, NewPartEntry; 237 PLIST_ENTRY ListEntry; 238 ULONGLONG ullSize = 0ULL; 239 ULONGLONG ullSectorCount; 240#if 0 241 ULONGLONG ullOffset = 0ULL; 242 BOOL bNoErr = FALSE; 243#endif 244 INT i; 245 PWSTR pszSuffix = NULL; 246 NTSTATUS Status; 247 248 if (CurrentDisk == NULL) 249 { 250 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 251 return EXIT_SUCCESS; 252 } 253 254 if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) 255 { 256 ConResPuts(StdOut, IDS_CREATE_PARTITION_INVALID_STYLE); 257 return EXIT_SUCCESS; 258 } 259 else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_RAW) 260 { 261 CREATE_DISK DiskInfo; 262 NTSTATUS Status; 263 264 DiskInfo.PartitionStyle = PARTITION_STYLE_MBR; 265 CreateSignature(&DiskInfo.Mbr.Signature); 266 267 Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo); 268 if (!NT_SUCCESS(Status)) 269 { 270 DPRINT1("CreateDisk() failed!\n"); 271 return EXIT_SUCCESS; 272 } 273 274 CurrentDisk->StartSector.QuadPart = (ULONGLONG)CurrentDisk->SectorAlignment; 275 CurrentDisk->EndSector.QuadPart = min(CurrentDisk->SectorCount.QuadPart, 0x100000000) - 1; 276 277 ScanForUnpartitionedMbrDiskSpace(CurrentDisk); 278 } 279 280 for (i = 3; i < argc; i++) 281 { 282 if (_wcsicmp(argv[i], L"noerr") == 0) 283 { 284 /* noerr */ 285 DPRINT("NoErr\n", pszSuffix); 286 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 287#if 0 288 bNoErr = TRUE; 289#endif 290 } 291 } 292 293 for (i = 3; i < argc; i++) 294 { 295 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 296 { 297 /* size=<N> (MB) */ 298 DPRINT("Size : %s\n", pszSuffix); 299 300 ullSize = _wcstoui64(pszSuffix, NULL, 10); 301 if ((ullSize == 0) && (errno == ERANGE)) 302 { 303 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 304 return EXIT_SUCCESS; 305 } 306 } 307 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 308 { 309 /* offset=<N> (KB) */ 310 DPRINT("Offset : %s\n", pszSuffix); 311 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 312#if 0 313 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 314 if ((ullOffset == 0) && (errno == ERANGE)) 315 { 316 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 317 return EXIT_SUCCESS; 318 } 319#endif 320 } 321 else if (HasPrefix(argv[i], L"align=", &pszSuffix)) 322 { 323 /* align=<N> */ 324 DPRINT("Align : %s\n", pszSuffix); 325 ConPuts(StdOut, L"The ALIGN option is not supported yet!\n"); 326#if 0 327 bAlign = TRUE; 328#endif 329 } 330 else if (_wcsicmp(argv[i], L"noerr") == 0) 331 { 332 /* noerr - Already handled above */ 333 } 334 else 335 { 336 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 337 return EXIT_SUCCESS; 338 } 339 } 340 341 DPRINT1("Size: %I64u\n", ullSize); 342#if 0 343 DPRINT1("Offset: %I64u\n", ullOffset); 344#endif 345 346 if (GetPrimaryPartitionCount(CurrentDisk) >= 4) 347 { 348 ConPuts(StdOut, L"No space left for an extended partition!\n"); 349 return EXIT_SUCCESS; 350 } 351 352 if (CurrentDisk->ExtendedPartition != NULL) 353 { 354 ConPuts(StdOut, L"We already have an extended partition on this disk!\n"); 355 return EXIT_SUCCESS; 356 } 357 358 if (ullSize != 0) 359 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 360 else 361 ullSectorCount = 0; 362 363 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 364 365 ListEntry = CurrentDisk->PrimaryPartListHead.Blink; 366 367 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); 368 if (PartEntry->IsPartitioned) 369 { 370 ConPuts(StdOut, L"No disk space left for an extended partition!\n"); 371 return EXIT_SUCCESS; 372 } 373 374 if (ullSectorCount == 0) 375 { 376 PartEntry->IsPartitioned = TRUE; 377 PartEntry->New = TRUE; 378 PartEntry->Mbr.PartitionType = PARTITION_EXTENDED; 379 PartEntry->FormatState = Unformatted; 380 PartEntry->FileSystemName[0] = L'\0'; 381 382 CurrentPartition = PartEntry; 383 CurrentDisk->Dirty = TRUE; 384 } 385 else 386 { 387 if (PartEntry->SectorCount.QuadPart == ullSectorCount) 388 { 389 PartEntry->IsPartitioned = TRUE; 390 PartEntry->New = TRUE; 391 PartEntry->Mbr.PartitionType = PARTITION_EXTENDED; 392 PartEntry->FormatState = Unformatted; 393 PartEntry->FileSystemName[0] = L'\0'; 394 395 CurrentPartition = PartEntry; 396 CurrentDisk->Dirty = TRUE; 397 } 398 else if (PartEntry->SectorCount.QuadPart > ullSectorCount) 399 { 400 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); 401 if (NewPartEntry == NULL) 402 { 403 ConPuts(StdOut, L"Memory allocation failed!\n"); 404 return TRUE; 405 } 406 407 NewPartEntry->DiskEntry = PartEntry->DiskEntry; 408 409 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; 410 NewPartEntry->SectorCount.QuadPart = ullSectorCount; 411 412 NewPartEntry->LogicalPartition = FALSE; 413 NewPartEntry->IsPartitioned = TRUE; 414 NewPartEntry->New = TRUE; 415 NewPartEntry->Mbr.PartitionType = PARTITION_EXTENDED; 416 NewPartEntry->FormatState = Unformatted; 417 NewPartEntry->FileSystemName[0] = L'\0'; 418 419 PartEntry->StartSector.QuadPart += ullSectorCount; 420 PartEntry->SectorCount.QuadPart -= ullSectorCount; 421 422 InsertTailList(ListEntry, &NewPartEntry->ListEntry); 423 424 CurrentPartition = NewPartEntry; 425 CurrentDisk->Dirty = TRUE; 426 } 427 } 428 429 UpdateMbrDiskLayout(CurrentDisk); 430 Status = WriteMbrPartitions(CurrentDisk); 431 if (!NT_SUCCESS(Status)) 432 { 433 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 434 CurrentPartition = NULL; 435 return EXIT_SUCCESS; 436 } 437 438 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 439 440 return EXIT_SUCCESS; 441} 442 443 444EXIT_CODE 445CreateLogicalPartition( 446 _In_ INT argc, 447 _In_ PWSTR *argv) 448{ 449 PPARTENTRY PartEntry, NewPartEntry; 450 PLIST_ENTRY ListEntry; 451 ULONGLONG ullSize = 0ULL; 452 ULONGLONG ullSectorCount; 453#if 0 454 ULONGLONG ullOffset = 0ULL; 455 BOOL bNoErr = FALSE; 456#endif 457 UCHAR PartitionType = PARTITION_HUGE; 458 INT i, length; 459 PWSTR pszSuffix = NULL; 460 NTSTATUS Status; 461 462 if (CurrentDisk == NULL) 463 { 464 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 465 return EXIT_SUCCESS; 466 } 467 468 if (CurrentDisk->PartitionStyle != PARTITION_STYLE_MBR) 469 { 470 ConResPuts(StdOut, IDS_CREATE_PARTITION_INVALID_STYLE); 471 return EXIT_SUCCESS; 472 } 473 474 for (i = 3; i < argc; i++) 475 { 476 if (_wcsicmp(argv[i], L"noerr") == 0) 477 { 478 /* noerr */ 479 DPRINT("NoErr\n", pszSuffix); 480 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 481#if 0 482 bNoErr = TRUE; 483#endif 484 } 485 } 486 487 for (i = 3; i < argc; i++) 488 { 489 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 490 { 491 /* size=<N> (MB) */ 492 DPRINT("Size : %s\n", pszSuffix); 493 494 ullSize = _wcstoui64(pszSuffix, NULL, 10); 495 if ((ullSize == 0) && (errno == ERANGE)) 496 { 497 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 498 return EXIT_SUCCESS; 499 } 500 } 501 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 502 { 503 /* offset=<N> (KB) */ 504 DPRINT("Offset : %s\n", pszSuffix); 505 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 506#if 0 507 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 508 if ((ullOffset == 0) && (errno == ERANGE)) 509 { 510 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 511 return EXIT_SUCCESS; 512 } 513#endif 514 } 515 else if (HasPrefix(argv[i], L"id=", &pszSuffix)) 516 { 517 /* id=<Byte> */ 518 DPRINT("Id : %s\n", pszSuffix); 519 520 length = wcslen(pszSuffix); 521 if ((length == 1) || (length == 2)) 522 { 523 /* Byte */ 524 PartitionType = (UCHAR)wcstoul(pszSuffix, NULL, 16); 525 if ((PartitionType == 0) && (errno == ERANGE)) 526 { 527 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 528 return EXIT_SUCCESS; 529 } 530 } 531 else 532 { 533 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 534 return EXIT_SUCCESS; 535 } 536 } 537 else if (HasPrefix(argv[i], L"align=", &pszSuffix)) 538 { 539 /* align=<N> */ 540 DPRINT("Align : %s\n", pszSuffix); 541 ConPuts(StdOut, L"The ALIGN option is not supported yet!\n"); 542#if 0 543 bAlign = TRUE; 544#endif 545 } 546 else if (_wcsicmp(argv[i], L"noerr") == 0) 547 { 548 /* noerr - Already handled above */ 549 } 550 else 551 { 552 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 553 return EXIT_SUCCESS; 554 } 555 } 556 557 DPRINT1("Size: %I64u\n", ullSize); 558#if 0 559 DPRINT1("Offset: %I64u\n", ullOffset); 560#endif 561 DPRINT1("Partition Type: %hx\n", PartitionType); 562 563 if (ullSize != 0) 564 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 565 else 566 ullSectorCount = 0; 567 568 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 569 570 for (ListEntry = CurrentDisk->LogicalPartListHead.Flink; 571 ListEntry != &CurrentDisk->LogicalPartListHead; 572 ListEntry = ListEntry->Flink) 573 { 574 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); 575 if (PartEntry->IsPartitioned) 576 continue; 577 578 if (ullSectorCount == 0) 579 { 580 PartEntry->IsPartitioned = TRUE; 581 PartEntry->New = TRUE; 582 PartEntry->Mbr.PartitionType = PartitionType; 583 PartEntry->FormatState = Unformatted; 584 PartEntry->FileSystemName[0] = L'\0'; 585 586 CurrentPartition = PartEntry; 587 CurrentDisk->Dirty = TRUE; 588 break; 589 } 590 else 591 { 592 if (PartEntry->SectorCount.QuadPart == ullSectorCount) 593 { 594 PartEntry->IsPartitioned = TRUE; 595 PartEntry->New = TRUE; 596 PartEntry->Mbr.PartitionType = PartitionType; 597 PartEntry->FormatState = Unformatted; 598 PartEntry->FileSystemName[0] = L'\0'; 599 600 CurrentPartition = PartEntry; 601 CurrentDisk->Dirty = TRUE; 602 break; 603 } 604 else if (PartEntry->SectorCount.QuadPart > ullSectorCount) 605 { 606 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); 607 if (NewPartEntry == NULL) 608 { 609 ConPuts(StdOut, L"Memory allocation failed!\n"); 610 return TRUE; 611 } 612 613 NewPartEntry->DiskEntry = PartEntry->DiskEntry; 614 615 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; 616 NewPartEntry->SectorCount.QuadPart = ullSectorCount; 617 618 NewPartEntry->LogicalPartition = TRUE; 619 NewPartEntry->IsPartitioned = TRUE; 620 NewPartEntry->New = TRUE; 621 NewPartEntry->Mbr.PartitionType = PartitionType; 622 NewPartEntry->FormatState = Unformatted; 623 NewPartEntry->FileSystemName[0] = L'\0'; 624 625 PartEntry->StartSector.QuadPart += ullSectorCount; 626 PartEntry->SectorCount.QuadPart -= ullSectorCount; 627 628 InsertTailList(ListEntry, &NewPartEntry->ListEntry); 629 630 CurrentPartition = NewPartEntry; 631 CurrentDisk->Dirty = TRUE; 632 break; 633 } 634 } 635 } 636 637 UpdateMbrDiskLayout(CurrentDisk); 638 Status = WriteMbrPartitions(CurrentDisk); 639 if (!NT_SUCCESS(Status)) 640 { 641 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 642 CurrentPartition = NULL; 643 return EXIT_SUCCESS; 644 } 645 646 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 647 648 return EXIT_SUCCESS; 649} 650 651 652EXIT_CODE 653CreateMsrPartition( 654 _In_ INT argc, 655 _In_ PWSTR *argv) 656{ 657 PPARTENTRY PartEntry; 658 ULONGLONG ullSize = 0ULL; 659 ULONGLONG ullSectorSize; 660#if 0 661 BOOL bNoErr = FALSE; 662#endif 663 INT i; 664 PWSTR pszSuffix = NULL; 665 NTSTATUS Status; 666 667 DPRINT1("CreateMsrPartition()\n"); 668 669 if (CurrentDisk == NULL) 670 { 671 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 672 return EXIT_SUCCESS; 673 } 674 675 if (CurrentDisk->PartitionStyle != PARTITION_STYLE_GPT) 676 { 677 ConResPuts(StdOut, IDS_CREATE_PARTITION_INVALID_STYLE); 678 return EXIT_SUCCESS; 679 } 680 681 for (i = 3; i < argc; i++) 682 { 683 if (_wcsicmp(argv[i], L"noerr") == 0) 684 { 685 /* noerr */ 686 DPRINT("NoErr\n", pszSuffix); 687 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 688#if 0 689 bNoErr = TRUE; 690#endif 691 } 692 } 693 694 for (i = 3; i < argc; i++) 695 { 696 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 697 { 698 /* size=<N> (MB) */ 699 DPRINT("Size : %s\n", pszSuffix); 700 701 ullSize = _wcstoui64(pszSuffix, NULL, 10); 702 if ((ullSize == 0) && (errno == ERANGE)) 703 { 704 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 705 return EXIT_SUCCESS; 706 } 707 } 708 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 709 { 710 /* offset=<N> (KB) */ 711 DPRINT("Offset : %s\n", pszSuffix); 712 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 713#if 0 714 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 715 if ((ullOffset == 0) && (errno == ERANGE)) 716 { 717 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 718 return EXIT_SUCCESS; 719 } 720#endif 721 } 722 else if (_wcsicmp(argv[i], L"noerr") == 0) 723 { 724 /* noerr - Already handled above */ 725 } 726 else 727 { 728 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 729 return EXIT_SUCCESS; 730 } 731 } 732 733 DPRINT1("Size: %I64u\n", ullSize); 734#if 0 735 DPRINT1("Offset: %I64u\n", ullOffset); 736#endif 737 738 /* Size */ 739 if (ullSize != 0) 740 ullSectorSize = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 741 else 742 ullSectorSize = 0; 743 744 DPRINT1("SectorSize: %I64u\n", ullSectorSize); 745 746#ifdef DUMP_PARTITION_LIST 747 DumpPartitionList(CurrentDisk); 748#endif 749 750 PartEntry = InsertGptPartition(CurrentDisk, 751 ullSectorSize, 752 &PARTITION_MSFT_RESERVED_GUID); 753 if (PartEntry == FALSE) 754 { 755 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 756 CurrentPartition = NULL; 757 return EXIT_SUCCESS; 758 } 759 760 CurrentPartition = PartEntry; 761 CurrentDisk->Dirty = TRUE; 762 763#ifdef DUMP_PARTITION_LIST 764 DumpPartitionList(CurrentDisk); 765#endif 766 767 UpdateGptDiskLayout(CurrentDisk, FALSE); 768 Status = WriteGptPartitions(CurrentDisk); 769 if (!NT_SUCCESS(Status)) 770 { 771 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 772 CurrentPartition = NULL; 773 return EXIT_SUCCESS; 774 } 775 776 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 777 778 return EXIT_SUCCESS; 779} 780 781 782static 783VOID 784CreatePrimaryMbrPartition( 785 _In_ ULONGLONG ullSize, 786 _In_ PWSTR pszPartitionType) 787{ 788 PPARTENTRY PartEntry, NewPartEntry; 789 PLIST_ENTRY ListEntry; 790 ULONGLONG ullSectorCount; 791 UCHAR PartitionType; 792 INT length; 793 NTSTATUS Status; 794 795 if (pszPartitionType) 796 { 797 length = wcslen(pszPartitionType); 798 if ((length != 1) && (length != 2)) 799 { 800 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 801 return; 802 } 803 804 PartitionType = (UCHAR)wcstoul(pszPartitionType, NULL, 16); 805 if ((PartitionType == 0) && (errno == ERANGE)) 806 { 807 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 808 return; 809 } 810 } 811 else 812 { 813 PartitionType = PARTITION_HUGE; 814 } 815 816 if (GetPrimaryPartitionCount(CurrentDisk) >= 4) 817 { 818 ConPuts(StdOut, L"No space left for another primary partition!\n"); 819 return; 820 } 821 822 if (ullSize != 0) 823 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 824 else 825 ullSectorCount = 0; 826 827 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 828 829 for (ListEntry = CurrentDisk->PrimaryPartListHead.Flink; 830 ListEntry != &CurrentDisk->PrimaryPartListHead; 831 ListEntry = ListEntry->Flink) 832 { 833 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); 834 if (PartEntry->IsPartitioned) 835 continue; 836 837 if (ullSectorCount == 0) 838 { 839 PartEntry->IsPartitioned = TRUE; 840 PartEntry->New = TRUE; 841 PartEntry->Mbr.PartitionType = PartitionType; 842 PartEntry->FormatState = Unformatted; 843 PartEntry->FileSystemName[0] = L'\0'; 844 845 CurrentPartition = PartEntry; 846 CurrentDisk->Dirty = TRUE; 847 break; 848 } 849 else 850 { 851 if (PartEntry->SectorCount.QuadPart == ullSectorCount) 852 { 853 PartEntry->IsPartitioned = TRUE; 854 PartEntry->New = TRUE; 855 PartEntry->Mbr.PartitionType = PartitionType; 856 PartEntry->FormatState = Unformatted; 857 PartEntry->FileSystemName[0] = L'\0'; 858 859 CurrentPartition = PartEntry; 860 CurrentDisk->Dirty = TRUE; 861 break; 862 } 863 else if (PartEntry->SectorCount.QuadPart > ullSectorCount) 864 { 865 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PPARTENTRY)); 866 if (NewPartEntry == NULL) 867 { 868 ConPuts(StdOut, L"Memory allocation failed!\n"); 869 return; 870 } 871 872 NewPartEntry->DiskEntry = PartEntry->DiskEntry; 873 874 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; 875 NewPartEntry->SectorCount.QuadPart = ullSectorCount; 876 877 NewPartEntry->LogicalPartition = FALSE; 878 NewPartEntry->IsPartitioned = TRUE; 879 NewPartEntry->New = TRUE; 880 NewPartEntry->Mbr.PartitionType = PartitionType; 881 NewPartEntry->FormatState = Unformatted; 882 NewPartEntry->FileSystemName[0] = L'\0'; 883 884 PartEntry->StartSector.QuadPart += ullSectorCount; 885 PartEntry->SectorCount.QuadPart -= ullSectorCount; 886 887 InsertTailList(ListEntry, &NewPartEntry->ListEntry); 888 889 CurrentPartition = NewPartEntry; 890 CurrentDisk->Dirty = TRUE; 891 break; 892 } 893 } 894 } 895 896 UpdateMbrDiskLayout(CurrentDisk); 897 Status = WriteMbrPartitions(CurrentDisk); 898 if (!NT_SUCCESS(Status)) 899 { 900 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 901 CurrentPartition = NULL; 902 return; 903 } 904 905 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 906} 907 908 909static 910VOID 911CreatePrimaryGptPartition( 912 _In_ ULONGLONG ullSize, 913 _In_ PWSTR pszPartitionType) 914{ 915 PPARTENTRY PartEntry; 916 ULONGLONG ullSectorCount; 917 GUID guidPartitionType; 918 NTSTATUS Status; 919 920 /* Partition Type */ 921 if (pszPartitionType) 922 { 923 if (!StringToGUID(&guidPartitionType, pszPartitionType)) 924 { 925 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 926 return; 927 } 928 } 929 else 930 { 931 CopyMemory(&guidPartitionType, &PARTITION_BASIC_DATA_GUID, sizeof(GUID)); 932 } 933 934 /* Size */ 935 if (ullSize != 0) 936 ullSectorCount = (ullSize * 1024 * 1024) / CurrentDisk->BytesPerSector; 937 else 938 ullSectorCount = 0; 939 940 DPRINT1("SectorCount: %I64u\n", ullSectorCount); 941 942#ifdef DUMP_PARTITION_LIST 943 DumpPartitionList(CurrentDisk); 944#endif 945 946 PartEntry = InsertGptPartition(CurrentDisk, 947 ullSectorCount, 948 &guidPartitionType); 949 if (PartEntry == FALSE) 950 { 951 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 952 CurrentPartition = NULL; 953 return; 954 } 955 956 CurrentPartition = PartEntry; 957 CurrentDisk->Dirty = TRUE; 958 959#ifdef DUMP_PARTITION_LIST 960 DumpPartitionList(CurrentDisk); 961#endif 962 963 UpdateGptDiskLayout(CurrentDisk, FALSE); 964 Status = WriteGptPartitions(CurrentDisk); 965 if (!NT_SUCCESS(Status)) 966 { 967 ConResPuts(StdOut, IDS_CREATE_PARTITION_FAIL); 968 CurrentPartition = NULL; 969 return; 970 } 971 972 ConResPuts(StdOut, IDS_CREATE_PARTITION_SUCCESS); 973} 974 975 976EXIT_CODE 977CreatePrimaryPartition( 978 _In_ INT argc, 979 _In_ PWSTR *argv) 980{ 981 ULONGLONG ullSize = 0ULL; 982#if 0 983 ULONGLONG ullOffset = 0ULL; 984 BOOL bNoErr = FALSE; 985#endif 986 INT i; 987 PWSTR pszSuffix = NULL; 988 PWSTR pszPartitionType = NULL; 989 990 if (CurrentDisk == NULL) 991 { 992 ConResPuts(StdOut, IDS_SELECT_NO_DISK); 993 return EXIT_SUCCESS; 994 } 995 996 if (CurrentDisk->PartitionStyle == PARTITION_STYLE_RAW) 997 { 998 CREATE_DISK DiskInfo; 999 NTSTATUS Status; 1000 1001 DiskInfo.PartitionStyle = PARTITION_STYLE_MBR; 1002 CreateSignature(&DiskInfo.Mbr.Signature); 1003 1004 Status = CreateDisk(CurrentDisk->DiskNumber, &DiskInfo); 1005 if (!NT_SUCCESS(Status)) 1006 { 1007 DPRINT1("CreateDisk() failed!\n"); 1008 return EXIT_SUCCESS; 1009 } 1010 1011 CurrentDisk->StartSector.QuadPart = (ULONGLONG)CurrentDisk->SectorAlignment; 1012 CurrentDisk->EndSector.QuadPart = min(CurrentDisk->SectorCount.QuadPart, 0x100000000) - 1; 1013 1014 ScanForUnpartitionedMbrDiskSpace(CurrentDisk); 1015 } 1016 1017 for (i = 3; i < argc; i++) 1018 { 1019 if (_wcsicmp(argv[i], L"noerr") == 0) 1020 { 1021 /* noerr */ 1022 DPRINT("NoErr\n", pszSuffix); 1023 ConPuts(StdOut, L"The NOERR option is not supported yet!\n"); 1024#if 0 1025 bNoErr = TRUE; 1026#endif 1027 } 1028 } 1029 1030 for (i = 3; i < argc; i++) 1031 { 1032 if (HasPrefix(argv[i], L"size=", &pszSuffix)) 1033 { 1034 /* size=<N> (MB) */ 1035 DPRINT("Size : %s\n", pszSuffix); 1036 1037 ullSize = _wcstoui64(pszSuffix, NULL, 10); 1038 if ((ullSize == 0) && (errno == ERANGE)) 1039 { 1040 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 1041 return EXIT_SUCCESS; 1042 } 1043 } 1044 else if (HasPrefix(argv[i], L"offset=", &pszSuffix)) 1045 { 1046 /* offset=<N> (KB) */ 1047 DPRINT("Offset : %s\n", pszSuffix); 1048 ConPuts(StdOut, L"The OFFSET option is not supported yet!\n"); 1049#if 0 1050 ullOffset = _wcstoui64(pszSuffix, NULL, 10); 1051 if ((ullOffset == 0) && (errno == ERANGE)) 1052 { 1053 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 1054 return EXIT_SUCCESS; 1055 } 1056#endif 1057 } 1058 else if (HasPrefix(argv[i], L"id=", &pszSuffix)) 1059 { 1060 /* id=<Byte>|<GUID> */ 1061 DPRINT("Id : %s\n", pszSuffix); 1062 pszPartitionType = pszSuffix; 1063 } 1064 else if (HasPrefix(argv[i], L"align=", &pszSuffix)) 1065 { 1066 /* align=<N> */ 1067 DPRINT("Align : %s\n", pszSuffix); 1068 ConPuts(StdOut, L"The ALIGN option is not supported yet!\n"); 1069#if 0 1070 bAlign = TRUE; 1071#endif 1072 } 1073 else if (_wcsicmp(argv[i], L"noerr") == 0) 1074 { 1075 /* noerr - Alread handled above */ 1076 } 1077 else 1078 { 1079 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS); 1080 return EXIT_SUCCESS; 1081 } 1082 } 1083 1084 DPRINT("Size: %I64u\n", ullSize); 1085#if 0 1086 DPRINT1("Offset: %I64u\n", ullOffset); 1087#endif 1088 1089 if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) 1090 { 1091 DPRINT("Partition Type: %s\n", pszPartitionType); 1092 CreatePrimaryMbrPartition(ullSize, pszPartitionType); 1093 } 1094 else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) 1095 { 1096 CreatePrimaryGptPartition(ullSize, pszPartitionType); 1097 } 1098 1099 return EXIT_SUCCESS; 1100}