Reactos
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}