[SHELL32] Fix Control_RunDLLW (#5400)
[reactos.git] / base / system / diskpart / create.c
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 }