Reactos
1/*
2 * PROJECT: ReactOS DiskPart
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/diskpart/delete.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
15BOOL
16IsKnownPartition(
17 _In_ PPARTENTRY PartEntry)
18{
19 if (IsRecognizedPartition(PartEntry->Mbr.PartitionType) ||
20 IsContainerPartition(PartEntry->Mbr.PartitionType))
21 return TRUE;
22
23 return FALSE;
24}
25
26
27EXIT_CODE
28DeleteDisk(
29 _In_ INT argc,
30 _In_ PWSTR *argv)
31{
32 return EXIT_SUCCESS;
33}
34
35
36static
37VOID
38DeleteMbrPartition(
39 _In_ BOOL bOverride)
40{
41 PPARTENTRY PrevPartEntry;
42 PPARTENTRY NextPartEntry;
43 PPARTENTRY LogicalPartEntry;
44 PLIST_ENTRY Entry;
45 NTSTATUS Status;
46
47 ASSERT(CurrentPartition->Mbr.PartitionType != PARTITION_ENTRY_UNUSED);
48
49 /* Clear the system partition if it is being deleted */
50#if 0
51 if (List->SystemPartition == PartEntry)
52 {
53 ASSERT(List->SystemPartition);
54 List->SystemPartition = NULL;
55 }
56#endif
57
58 if ((bOverride == FALSE) && (IsKnownPartition(CurrentPartition) == FALSE))
59 {
60 ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL);
61 return;
62 }
63
64 /* Check which type of partition (primary/logical or extended) is being deleted */
65 if (CurrentDisk->ExtendedPartition == CurrentPartition)
66 {
67 /* An extended partition is being deleted: delete all logical partition entries */
68 while (!IsListEmpty(&CurrentDisk->LogicalPartListHead))
69 {
70 Entry = RemoveHeadList(&CurrentDisk->LogicalPartListHead);
71 LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
72
73 /* Dismount the logical partition */
74 DismountVolume(LogicalPartEntry);
75
76 /* Delete it */
77 RtlFreeHeap(RtlGetProcessHeap(), 0, LogicalPartEntry);
78 }
79
80 CurrentDisk->ExtendedPartition = NULL;
81 }
82 else
83 {
84 /* A primary partition is being deleted: dismount it */
85 DismountVolume(CurrentPartition);
86 }
87
88 /* Adjust the unpartitioned disk space entries */
89
90 /* Get pointer to previous and next unpartitioned entries */
91 PrevPartEntry = GetPrevUnpartitionedEntry(CurrentPartition);
92 NextPartEntry = GetNextUnpartitionedEntry(CurrentPartition);
93
94 if (PrevPartEntry != NULL && NextPartEntry != NULL)
95 {
96 /* Merge the previous, current and next unpartitioned entries */
97
98 /* Adjust the previous entry length */
99 PrevPartEntry->SectorCount.QuadPart += (CurrentPartition->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
100
101 /* Remove the current and next entries */
102 RemoveEntryList(&CurrentPartition->ListEntry);
103 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition);
104 RemoveEntryList(&NextPartEntry->ListEntry);
105 RtlFreeHeap(RtlGetProcessHeap(), 0, NextPartEntry);
106 }
107 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
108 {
109 /* Merge the current and the previous unpartitioned entries */
110
111 /* Adjust the previous entry length */
112 PrevPartEntry->SectorCount.QuadPart += CurrentPartition->SectorCount.QuadPart;
113
114 /* Remove the current entry */
115 RemoveEntryList(&CurrentPartition->ListEntry);
116 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition);
117 }
118 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
119 {
120 /* Merge the current and the next unpartitioned entries */
121
122 /* Adjust the next entry offset and length */
123 NextPartEntry->StartSector.QuadPart = CurrentPartition->StartSector.QuadPart;
124 NextPartEntry->SectorCount.QuadPart += CurrentPartition->SectorCount.QuadPart;
125
126 /* Remove the current entry */
127 RemoveEntryList(&CurrentPartition->ListEntry);
128 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition);
129 }
130 else
131 {
132 /* Nothing to merge but change the current entry */
133 CurrentPartition->IsPartitioned = FALSE;
134 CurrentPartition->OnDiskPartitionNumber = 0;
135 CurrentPartition->PartitionNumber = 0;
136 // CurrentPartition->PartitionIndex = 0;
137 CurrentPartition->Mbr.BootIndicator = FALSE;
138 CurrentPartition->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
139 CurrentPartition->FormatState = Unformatted;
140 CurrentPartition->FileSystemName[0] = L'\0';
141 CurrentPartition->DriveLetter = 0;
142 RtlZeroMemory(CurrentPartition->VolumeLabel, sizeof(CurrentPartition->VolumeLabel));
143 }
144
145 CurrentPartition = NULL;
146
147 UpdateMbrDiskLayout(CurrentDisk);
148 Status = WriteMbrPartitions(CurrentDisk);
149 if (!NT_SUCCESS(Status))
150 {
151 ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL);
152 return;
153 }
154
155 ConResPuts(StdOut, IDS_DELETE_PARTITION_SUCCESS);
156}
157
158
159static
160VOID
161DeleteGptPartition(
162 _In_ BOOL bOverride)
163{
164 PPARTENTRY PrevPartEntry;
165 PPARTENTRY NextPartEntry;
166 NTSTATUS Status;
167
168 /* Clear the system partition if it is being deleted */
169#if 0
170 if (List->SystemPartition == PartEntry)
171 {
172 ASSERT(List->SystemPartition);
173 List->SystemPartition = NULL;
174 }
175#endif
176
177 if ((bOverride == FALSE) &&
178 ((memcmp(&CurrentPartition->Gpt.PartitionType, &PARTITION_SYSTEM_GUID, sizeof(GUID)) == 0) ||
179 (memcmp(&CurrentPartition->Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID, sizeof(GUID)) == 0)))
180 {
181 ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL);
182 return;
183 }
184
185#ifdef DUMP_PARTITION_LIST
186 DumpPartitionList(CurrentDisk);
187#endif
188
189 /* Dismount the partition */
190 DismountVolume(CurrentPartition);
191
192 /* Adjust the unpartitioned disk space entries */
193
194 /* Get pointer to previous and next unpartitioned entries */
195 PrevPartEntry = GetPrevUnpartitionedEntry(CurrentPartition);
196 NextPartEntry = GetNextUnpartitionedEntry(CurrentPartition);
197
198 if (PrevPartEntry != NULL && NextPartEntry != NULL)
199 {
200 /* Merge the previous, current and next unpartitioned entries */
201
202 /* Adjust the previous entry length */
203 PrevPartEntry->SectorCount.QuadPart += (CurrentPartition->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
204
205 /* Remove the current and next entries */
206 RemoveEntryList(&CurrentPartition->ListEntry);
207 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition);
208 RemoveEntryList(&NextPartEntry->ListEntry);
209 RtlFreeHeap(RtlGetProcessHeap(), 0, NextPartEntry);
210 }
211 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
212 {
213 /* Merge the current and the previous unpartitioned entries */
214
215 /* Adjust the previous entry length */
216 PrevPartEntry->SectorCount.QuadPart += CurrentPartition->SectorCount.QuadPart;
217
218 /* Remove the current entry */
219 RemoveEntryList(&CurrentPartition->ListEntry);
220 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition);
221 }
222 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
223 {
224 /* Merge the current and the next unpartitioned entries */
225
226 /* Adjust the next entry offset and length */
227 NextPartEntry->StartSector.QuadPart = CurrentPartition->StartSector.QuadPart;
228 NextPartEntry->SectorCount.QuadPart += CurrentPartition->SectorCount.QuadPart;
229
230 /* Remove the current entry */
231 RemoveEntryList(&CurrentPartition->ListEntry);
232 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentPartition);
233 }
234 else
235 {
236 /* Nothing to merge but change the current entry */
237 CurrentPartition->IsPartitioned = FALSE;
238 CurrentPartition->OnDiskPartitionNumber = 0;
239 CurrentPartition->PartitionNumber = 0;
240 // CurrentPartition->PartitionIndex = 0;
241
242 ZeroMemory(&CurrentPartition->Gpt.PartitionType, sizeof(GUID));
243 ZeroMemory(&CurrentPartition->Gpt.PartitionId, sizeof(GUID));
244 CurrentPartition->Gpt.Attributes = 0ULL;
245
246 CurrentPartition->FormatState = Unformatted;
247 CurrentPartition->FileSystemName[0] = L'\0';
248 CurrentPartition->DriveLetter = 0;
249 RtlZeroMemory(CurrentPartition->VolumeLabel, sizeof(CurrentPartition->VolumeLabel));
250 }
251
252 CurrentPartition = NULL;
253
254#ifdef DUMP_PARTITION_LIST
255 DumpPartitionList(CurrentDisk);
256#endif
257
258 UpdateGptDiskLayout(CurrentDisk, TRUE);
259#ifdef DUMP_PARTITION_TABLE
260 DumpPartitionTable(CurrentDisk);
261#endif
262 Status = WriteGptPartitions(CurrentDisk);
263 if (!NT_SUCCESS(Status))
264 {
265 ConResPuts(StdOut, IDS_DELETE_PARTITION_FAIL);
266 return;
267 }
268
269 ConResPuts(StdOut, IDS_DELETE_PARTITION_SUCCESS);
270}
271
272
273EXIT_CODE
274DeletePartition(
275 _In_ INT argc,
276 _In_ PWSTR *argv)
277{
278 INT i;
279 BOOL bOverride = FALSE;
280
281 DPRINT("DeletePartition()\n");
282
283 if (CurrentDisk == NULL)
284 {
285 ConResPuts(StdOut, IDS_SELECT_NO_DISK);
286 return EXIT_SUCCESS;
287 }
288
289 if (CurrentPartition == NULL)
290 {
291 ConResPuts(StdOut, IDS_SELECT_NO_PARTITION);
292 return EXIT_SUCCESS;
293 }
294
295 for (i = 2; i < argc; i++)
296 {
297 if (_wcsicmp(argv[i], L"noerr") == 0)
298 {
299 /* noerr */
300 DPRINT("NOERR\n");
301 ConPuts(StdOut, L"The NOERR option is not supported yet!\n");
302#if 0
303 bNoErr = TRUE;
304#endif
305 }
306 }
307
308 for (i = 2; i < argc; i++)
309 {
310 if (_wcsicmp(argv[i], L"noerr") == 0)
311 {
312 /* noerr - Already handled above */
313 }
314 else if (_wcsicmp(argv[i], L"override") == 0)
315 {
316 /* override */
317 DPRINT("OVERRIDE\n");
318 bOverride = TRUE;
319 }
320 else
321 {
322 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS);
323 return EXIT_SUCCESS;
324 }
325 }
326
327 if (CurrentPartition->IsBoot || CurrentPartition->IsSystem)
328 {
329 ConResPuts(StdOut, IDS_DELETE_PARTITION_SYSTEM);
330 return EXIT_SUCCESS;
331 }
332
333 if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR)
334 {
335 DeleteMbrPartition(bOverride);
336 }
337 else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT)
338 {
339 DeleteGptPartition(bOverride);
340 }
341
342 return EXIT_SUCCESS;
343}
344
345
346EXIT_CODE
347DeleteVolume(
348 _In_ INT argc,
349 _In_ PWSTR *argv)
350{
351 return EXIT_SUCCESS;
352}