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
16 CreateExtendedPartition(
20 PPARTENTRY PartEntry
, NewPartEntry
;
21 PLIST_ENTRY ListEntry
;
22 ULONGLONG ullSize
= 0ULL;
23 ULONGLONG ullSectorCount
;
25 ULONGLONG ullOffset
= 0ULL;
29 PWSTR pszSuffix
= NULL
;
32 if (CurrentDisk
== NULL
)
34 ConResPuts(StdOut
, IDS_SELECT_NO_DISK
);
38 for (i
= 3; i
< argc
; i
++)
40 if (HasPrefix(argv
[i
], L
"size=", &pszSuffix
))
43 DPRINT("Size : %s\n", pszSuffix
);
45 ullSize
= _wcstoui64(pszSuffix
, NULL
, 10);
46 if ((ullSize
== 0) && (errno
== ERANGE
))
48 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
52 else if (HasPrefix(argv
[i
], L
"offset=", &pszSuffix
))
55 DPRINT("Offset : %s\n", pszSuffix
);
56 ConPuts(StdOut
, L
"The OFFSET option is not supported yet!\n");
58 ullOffset
= _wcstoui64(pszSuffix
, NULL
, 10);
59 if ((ullOffset
== 0) && (errno
== ERANGE
))
61 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
66 else if (HasPrefix(argv
[i
], L
"align=", &pszSuffix
))
69 DPRINT("Align : %s\n", pszSuffix
);
70 ConPuts(StdOut
, L
"The ALIGN option is not supported yet!\n");
75 else if (_wcsicmp(argv
[i
], L
"noerr") == 0)
78 DPRINT("NoErr\n", pszSuffix
);
79 ConPuts(StdOut
, L
"The NOERR option is not supported yet!\n");
86 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
91 DPRINT1("Size: %I64u\n", ullSize
);
93 DPRINT1("Offset: %I64u\n", ullOffset
);
96 if (GetPrimaryPartitionCount(CurrentDisk
) >= 4)
98 ConPuts(StdOut
, L
"No space left for an extended partition!\n");
102 if (CurrentDisk
->ExtendedPartition
!= NULL
)
104 ConPuts(StdOut
, L
"We already have an extended partition on this disk!\n");
109 ullSectorCount
= (ullSize
* 1024 * 1024) / CurrentDisk
->BytesPerSector
;
113 DPRINT1("SectorCount: %I64u\n", ullSectorCount
);
115 ListEntry
= CurrentDisk
->PrimaryPartListHead
.Blink
;
117 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
118 if (PartEntry
->IsPartitioned
)
120 ConPuts(StdOut
, L
"No disk space left for an extended partition!\n");
124 if (ullSectorCount
== 0)
126 PartEntry
->IsPartitioned
= TRUE
;
127 PartEntry
->New
= TRUE
;
128 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
129 PartEntry
->FormatState
= Unformatted
;
130 PartEntry
->FileSystemName
[0] = L
'\0';
132 CurrentPartition
= PartEntry
;
133 CurrentDisk
->Dirty
= TRUE
;
137 if (PartEntry
->SectorCount
.QuadPart
== ullSectorCount
)
139 PartEntry
->IsPartitioned
= TRUE
;
140 PartEntry
->New
= TRUE
;
141 PartEntry
->PartitionType
= PARTITION_EXTENDED
;
142 PartEntry
->FormatState
= Unformatted
;
143 PartEntry
->FileSystemName
[0] = L
'\0';
145 CurrentPartition
= PartEntry
;
146 CurrentDisk
->Dirty
= TRUE
;
148 else if (PartEntry
->SectorCount
.QuadPart
> ullSectorCount
)
150 NewPartEntry
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PPARTENTRY
));
151 if (NewPartEntry
== NULL
)
153 ConPuts(StdOut
, L
"Memory allocation failed!\n");
157 NewPartEntry
->DiskEntry
= PartEntry
->DiskEntry
;
159 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
160 NewPartEntry
->SectorCount
.QuadPart
= ullSectorCount
;
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';
169 PartEntry
->StartSector
.QuadPart
+= ullSectorCount
;
170 PartEntry
->SectorCount
.QuadPart
-= ullSectorCount
;
172 InsertTailList(ListEntry
, &NewPartEntry
->ListEntry
);
174 CurrentPartition
= NewPartEntry
;
175 CurrentDisk
->Dirty
= TRUE
;
179 UpdateDiskLayout(CurrentDisk
);
180 Status
= WritePartitions(CurrentDisk
);
181 if (!NT_SUCCESS(Status
))
183 ConResPuts(StdOut
, IDS_CREATE_PARTITION_FAIL
);
184 CurrentPartition
= NULL
;
188 ConResPuts(StdOut
, IDS_CREATE_PARTITION_SUCCESS
);
195 CreateLogicalPartition(
199 PPARTENTRY PartEntry
, NewPartEntry
;
200 PLIST_ENTRY ListEntry
;
201 ULONGLONG ullSize
= 0ULL;
202 ULONGLONG ullSectorCount
;
204 ULONGLONG ullOffset
= 0ULL;
207 UCHAR PartitionType
= PARTITION_HUGE
;
209 PWSTR pszSuffix
= NULL
;
212 if (CurrentDisk
== NULL
)
214 ConResPuts(StdOut
, IDS_SELECT_NO_DISK
);
218 for (i
= 3; i
< argc
; i
++)
220 if (HasPrefix(argv
[i
], L
"size=", &pszSuffix
))
223 DPRINT("Size : %s\n", pszSuffix
);
225 ullSize
= _wcstoui64(pszSuffix
, NULL
, 10);
226 if ((ullSize
== 0) && (errno
== ERANGE
))
228 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
232 else if (HasPrefix(argv
[i
], L
"offset=", &pszSuffix
))
234 /* offset=<N> (KB) */
235 DPRINT("Offset : %s\n", pszSuffix
);
236 ConPuts(StdOut
, L
"The OFFSET option is not supported yet!\n");
238 ullOffset
= _wcstoui64(pszSuffix
, NULL
, 10);
239 if ((ullOffset
== 0) && (errno
== ERANGE
))
241 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
246 else if (HasPrefix(argv
[i
], L
"id=", &pszSuffix
))
248 /* id=<Byte>|<GUID> */
249 DPRINT("Id : %s\n", pszSuffix
);
251 length
= wcslen(pszSuffix
);
252 if ((length
== 1) || (length
== 2))
255 PartitionType
= (UCHAR
)wcstoul(pszSuffix
, NULL
, 16);
256 if ((PartitionType
== 0) && (errno
== ERANGE
))
258 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
270 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
274 else if (HasPrefix(argv
[i
], L
"align=", &pszSuffix
))
277 DPRINT("Align : %s\n", pszSuffix
);
278 ConPuts(StdOut
, L
"The ALIGN option is not supported yet!\n");
283 else if (_wcsicmp(argv
[i
], L
"noerr") == 0)
286 DPRINT("NoErr\n", pszSuffix
);
287 ConPuts(StdOut
, L
"The NOERR option is not supported yet!\n");
294 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
299 DPRINT1("Size: %I64u\n", ullSize
);
301 DPRINT1("Offset: %I64u\n", ullOffset
);
303 DPRINT1("Partition Type: %hx\n", PartitionType
);
306 ullSectorCount
= (ullSize
* 1024 * 1024) / CurrentDisk
->BytesPerSector
;
310 DPRINT1("SectorCount: %I64u\n", ullSectorCount
);
312 for (ListEntry
= CurrentDisk
->LogicalPartListHead
.Flink
;
313 ListEntry
!= &CurrentDisk
->LogicalPartListHead
;
314 ListEntry
= ListEntry
->Flink
)
316 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
317 if (PartEntry
->IsPartitioned
)
320 if (ullSectorCount
== 0)
322 PartEntry
->IsPartitioned
= TRUE
;
323 PartEntry
->New
= TRUE
;
324 PartEntry
->PartitionType
= PartitionType
;
325 PartEntry
->FormatState
= Unformatted
;
326 PartEntry
->FileSystemName
[0] = L
'\0';
328 CurrentPartition
= PartEntry
;
329 CurrentDisk
->Dirty
= TRUE
;
334 if (PartEntry
->SectorCount
.QuadPart
== ullSectorCount
)
336 PartEntry
->IsPartitioned
= TRUE
;
337 PartEntry
->New
= TRUE
;
338 PartEntry
->PartitionType
= PartitionType
;
339 PartEntry
->FormatState
= Unformatted
;
340 PartEntry
->FileSystemName
[0] = L
'\0';
342 CurrentPartition
= PartEntry
;
343 CurrentDisk
->Dirty
= TRUE
;
346 else if (PartEntry
->SectorCount
.QuadPart
> ullSectorCount
)
348 NewPartEntry
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PPARTENTRY
));
349 if (NewPartEntry
== NULL
)
351 ConPuts(StdOut
, L
"Memory allocation failed!\n");
355 NewPartEntry
->DiskEntry
= PartEntry
->DiskEntry
;
357 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
358 NewPartEntry
->SectorCount
.QuadPart
= ullSectorCount
;
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';
367 PartEntry
->StartSector
.QuadPart
+= ullSectorCount
;
368 PartEntry
->SectorCount
.QuadPart
-= ullSectorCount
;
370 InsertTailList(ListEntry
, &NewPartEntry
->ListEntry
);
372 CurrentPartition
= NewPartEntry
;
373 CurrentDisk
->Dirty
= TRUE
;
379 UpdateDiskLayout(CurrentDisk
);
380 Status
= WritePartitions(CurrentDisk
);
381 if (!NT_SUCCESS(Status
))
383 ConResPuts(StdOut
, IDS_CREATE_PARTITION_FAIL
);
384 CurrentPartition
= NULL
;
388 ConResPuts(StdOut
, IDS_CREATE_PARTITION_SUCCESS
);
395 CreatePrimaryPartition(
399 PPARTENTRY PartEntry
, NewPartEntry
;
400 PLIST_ENTRY ListEntry
;
401 ULONGLONG ullSize
= 0ULL;
402 ULONGLONG ullSectorCount
;
404 ULONGLONG ullOffset
= 0ULL;
407 UCHAR PartitionType
= PARTITION_HUGE
;
409 PWSTR pszSuffix
= NULL
;
412 if (CurrentDisk
== NULL
)
414 ConResPuts(StdOut
, IDS_SELECT_NO_DISK
);
418 for (i
= 3; i
< argc
; i
++)
420 if (HasPrefix(argv
[i
], L
"size=", &pszSuffix
))
423 DPRINT("Size : %s\n", pszSuffix
);
425 ullSize
= _wcstoui64(pszSuffix
, NULL
, 10);
426 if ((ullSize
== 0) && (errno
== ERANGE
))
428 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
432 else if (HasPrefix(argv
[i
], L
"offset=", &pszSuffix
))
434 /* offset=<N> (KB) */
435 DPRINT("Offset : %s\n", pszSuffix
);
436 ConPuts(StdOut
, L
"The OFFSET option is not supported yet!\n");
438 ullOffset
= _wcstoui64(pszSuffix
, NULL
, 10);
439 if ((ullOffset
== 0) && (errno
== ERANGE
))
441 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
446 else if (HasPrefix(argv
[i
], L
"id=", &pszSuffix
))
448 /* id=<Byte>|<GUID> */
449 DPRINT("Id : %s\n", pszSuffix
);
451 length
= wcslen(pszSuffix
);
452 if ((length
== 1) || (length
== 2))
455 PartitionType
= (UCHAR
)wcstoul(pszSuffix
, NULL
, 16);
456 if ((PartitionType
== 0) && (errno
== ERANGE
))
458 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
470 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
474 else if (HasPrefix(argv
[i
], L
"align=", &pszSuffix
))
477 DPRINT("Align : %s\n", pszSuffix
);
478 ConPuts(StdOut
, L
"The ALIGN option is not supported yet!\n");
483 else if (_wcsicmp(argv
[i
], L
"noerr") == 0)
486 DPRINT("NoErr\n", pszSuffix
);
487 ConPuts(StdOut
, L
"The NOERR option is not supported yet!\n");
494 ConResPuts(StdErr
, IDS_ERROR_INVALID_ARGS
);
499 DPRINT1("Size: %I64u\n", ullSize
);
501 DPRINT1("Offset: %I64u\n", ullOffset
);
503 DPRINT1("Partition Type: %hx\n", PartitionType
);
505 if (GetPrimaryPartitionCount(CurrentDisk
) >= 4)
507 ConPuts(StdOut
, L
"No space left for another primary partition!\n");
512 ullSectorCount
= (ullSize
* 1024 * 1024) / CurrentDisk
->BytesPerSector
;
516 DPRINT1("SectorCount: %I64u\n", ullSectorCount
);
518 for (ListEntry
= CurrentDisk
->PrimaryPartListHead
.Flink
;
519 ListEntry
!= &CurrentDisk
->PrimaryPartListHead
;
520 ListEntry
= ListEntry
->Flink
)
522 PartEntry
= CONTAINING_RECORD(ListEntry
, PARTENTRY
, ListEntry
);
523 if (PartEntry
->IsPartitioned
)
526 if (ullSectorCount
== 0)
528 PartEntry
->IsPartitioned
= TRUE
;
529 PartEntry
->New
= TRUE
;
530 PartEntry
->PartitionType
= PartitionType
;
531 PartEntry
->FormatState
= Unformatted
;
532 PartEntry
->FileSystemName
[0] = L
'\0';
534 CurrentPartition
= PartEntry
;
535 CurrentDisk
->Dirty
= TRUE
;
540 if (PartEntry
->SectorCount
.QuadPart
== ullSectorCount
)
542 PartEntry
->IsPartitioned
= TRUE
;
543 PartEntry
->New
= TRUE
;
544 PartEntry
->PartitionType
= PartitionType
;
545 PartEntry
->FormatState
= Unformatted
;
546 PartEntry
->FileSystemName
[0] = L
'\0';
548 CurrentPartition
= PartEntry
;
549 CurrentDisk
->Dirty
= TRUE
;
552 else if (PartEntry
->SectorCount
.QuadPart
> ullSectorCount
)
554 NewPartEntry
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PPARTENTRY
));
555 if (NewPartEntry
== NULL
)
557 ConPuts(StdOut
, L
"Memory allocation failed!\n");
561 NewPartEntry
->DiskEntry
= PartEntry
->DiskEntry
;
563 NewPartEntry
->StartSector
.QuadPart
= PartEntry
->StartSector
.QuadPart
;
564 NewPartEntry
->SectorCount
.QuadPart
= ullSectorCount
;
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';
573 PartEntry
->StartSector
.QuadPart
+= ullSectorCount
;
574 PartEntry
->SectorCount
.QuadPart
-= ullSectorCount
;
576 InsertTailList(ListEntry
, &NewPartEntry
->ListEntry
);
578 CurrentPartition
= NewPartEntry
;
579 CurrentDisk
->Dirty
= TRUE
;
585 UpdateDiskLayout(CurrentDisk
);
586 Status
= WritePartitions(CurrentDisk
);
587 if (!NT_SUCCESS(Status
))
589 ConResPuts(StdOut
, IDS_CREATE_PARTITION_FAIL
);
590 CurrentPartition
= NULL
;
594 ConResPuts(StdOut
, IDS_CREATE_PARTITION_SUCCESS
);