xref: /reactos/base/system/diskpart/clean.c (revision 2be7af18)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS DiskPart
3c2c66affSColin Finck  * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            base/system/diskpart/clean.c
5c2c66affSColin Finck  * PURPOSE:         Manages all the partitions of the OS in an interactive way.
6c2c66affSColin Finck  * PROGRAMMERS:     Lee Schroeder
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include "diskpart.h"
10c2c66affSColin Finck 
11*2be7af18SEric Kohl #define NDEBUG
12*2be7af18SEric Kohl #include <debug.h>
13*2be7af18SEric Kohl 
14*2be7af18SEric Kohl 
15*2be7af18SEric Kohl BOOL
clean_main(_In_ INT argc,_In_ PWSTR * argv)16*2be7af18SEric Kohl clean_main(
17*2be7af18SEric Kohl     _In_ INT argc,
18*2be7af18SEric Kohl     _In_ PWSTR *argv)
19c2c66affSColin Finck {
20*2be7af18SEric Kohl     PLIST_ENTRY Entry;
21*2be7af18SEric Kohl     PPARTENTRY PartEntry;
22*2be7af18SEric Kohl     PVOLENTRY VolumeEntry;
23*2be7af18SEric Kohl     BOOL bAll = FALSE;
24*2be7af18SEric Kohl     PUCHAR SectorsBuffer = NULL;
25*2be7af18SEric Kohl     ULONG LayoutBufferSize, Size;
26*2be7af18SEric Kohl     INT i;
27*2be7af18SEric Kohl     WCHAR Buffer[MAX_PATH];
28*2be7af18SEric Kohl     UNICODE_STRING Name;
29*2be7af18SEric Kohl     OBJECT_ATTRIBUTES ObjectAttributes;
30*2be7af18SEric Kohl     IO_STATUS_BLOCK IoStatusBlock;
31*2be7af18SEric Kohl     HANDLE FileHandle = NULL;
32*2be7af18SEric Kohl     LARGE_INTEGER Offset, Count, MaxCount;
33*2be7af18SEric Kohl     NTSTATUS Status;
34*2be7af18SEric Kohl 
35*2be7af18SEric Kohl     DPRINT("Clean()\n");
36*2be7af18SEric Kohl 
37*2be7af18SEric Kohl     if (CurrentDisk == NULL)
38*2be7af18SEric Kohl     {
39*2be7af18SEric Kohl         ConResPuts(StdOut, IDS_SELECT_NO_DISK);
40*2be7af18SEric Kohl         return TRUE;
41*2be7af18SEric Kohl     }
42*2be7af18SEric Kohl 
43*2be7af18SEric Kohl     /* Do not allow to clean the boot disk */
44*2be7af18SEric Kohl     if ((CurrentDisk->BiosFound == TRUE) &&
45*2be7af18SEric Kohl         (CurrentDisk->BiosDiskNumber == 0))
46*2be7af18SEric Kohl     {
47*2be7af18SEric Kohl         ConResPuts(StdOut, IDS_CLEAN_SYSTEM);
48*2be7af18SEric Kohl         return TRUE;
49*2be7af18SEric Kohl     }
50*2be7af18SEric Kohl 
51*2be7af18SEric Kohl     for (i = 1; i < argc; i++)
52*2be7af18SEric Kohl     {
53*2be7af18SEric Kohl         if (_wcsicmp(argv[1], L"all") == 0)
54*2be7af18SEric Kohl         {
55*2be7af18SEric Kohl             bAll = TRUE;
56*2be7af18SEric Kohl         }
57*2be7af18SEric Kohl     }
58*2be7af18SEric Kohl 
59*2be7af18SEric Kohl     /* Dismount and remove all logical partitions */
60*2be7af18SEric Kohl     while (!IsListEmpty(&CurrentDisk->LogicalPartListHead))
61*2be7af18SEric Kohl     {
62*2be7af18SEric Kohl         Entry = RemoveHeadList(&CurrentDisk->LogicalPartListHead);
63*2be7af18SEric Kohl         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
64*2be7af18SEric Kohl 
65*2be7af18SEric Kohl         /* Dismount the logical partition */
66*2be7af18SEric Kohl         if (PartEntry->PartitionType != 0)
67*2be7af18SEric Kohl         {
68*2be7af18SEric Kohl             DismountVolume(PartEntry);
69*2be7af18SEric Kohl             VolumeEntry = GetVolumeFromPartition(PartEntry);
70*2be7af18SEric Kohl             if (VolumeEntry)
71*2be7af18SEric Kohl                 RemoveVolume(VolumeEntry);
72*2be7af18SEric Kohl         }
73*2be7af18SEric Kohl 
74*2be7af18SEric Kohl         /* Delete it */
75*2be7af18SEric Kohl         RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
76*2be7af18SEric Kohl     }
77*2be7af18SEric Kohl 
78*2be7af18SEric Kohl     /* Dismount and remove all primary partitions */
79*2be7af18SEric Kohl     while (!IsListEmpty(&CurrentDisk->PrimaryPartListHead))
80*2be7af18SEric Kohl     {
81*2be7af18SEric Kohl         Entry = RemoveHeadList(&CurrentDisk->PrimaryPartListHead);
82*2be7af18SEric Kohl         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
83*2be7af18SEric Kohl 
84*2be7af18SEric Kohl         /* Dismount the primary partition */
85*2be7af18SEric Kohl         if ((PartEntry->PartitionType != 0) &&
86*2be7af18SEric Kohl             (IsContainerPartition(PartEntry->PartitionType) == FALSE))
87*2be7af18SEric Kohl         {
88*2be7af18SEric Kohl             DismountVolume(PartEntry);
89*2be7af18SEric Kohl             VolumeEntry = GetVolumeFromPartition(PartEntry);
90*2be7af18SEric Kohl             if (VolumeEntry)
91*2be7af18SEric Kohl                 RemoveVolume(VolumeEntry);
92*2be7af18SEric Kohl         }
93*2be7af18SEric Kohl 
94*2be7af18SEric Kohl         /* Delete it */
95*2be7af18SEric Kohl         RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
96*2be7af18SEric Kohl     }
97*2be7af18SEric Kohl 
98*2be7af18SEric Kohl     /* Initialize the disk entry */
99*2be7af18SEric Kohl     CurrentDisk->ExtendedPartition = NULL;
100*2be7af18SEric Kohl     CurrentDisk->Dirty = FALSE;
101*2be7af18SEric Kohl     CurrentDisk->NewDisk = TRUE;
102*2be7af18SEric Kohl     CurrentDisk->NoMbr = TRUE;
103*2be7af18SEric Kohl 
104*2be7af18SEric Kohl     /* Wipe the layout buffer */
105*2be7af18SEric Kohl     RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDisk->LayoutBuffer);
106*2be7af18SEric Kohl 
107*2be7af18SEric Kohl     LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
108*2be7af18SEric Kohl                        ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
109*2be7af18SEric Kohl     CurrentDisk->LayoutBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
110*2be7af18SEric Kohl                                                 HEAP_ZERO_MEMORY,
111*2be7af18SEric Kohl                                                 LayoutBufferSize);
112*2be7af18SEric Kohl     if (CurrentDisk->LayoutBuffer == NULL)
113*2be7af18SEric Kohl     {
114*2be7af18SEric Kohl         DPRINT1("Failed to allocate the disk layout buffer!\n");
115*2be7af18SEric Kohl         return TRUE;
116*2be7af18SEric Kohl     }
117*2be7af18SEric Kohl 
118*2be7af18SEric Kohl     /* Allocate a 1MB sectors buffer */
119*2be7af18SEric Kohl     SectorsBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
120*2be7af18SEric Kohl                                     HEAP_ZERO_MEMORY,
121*2be7af18SEric Kohl                                     1024 * 1024);
122*2be7af18SEric Kohl     if (SectorsBuffer == NULL)
123*2be7af18SEric Kohl     {
124*2be7af18SEric Kohl         DPRINT1("Failed to allocate the sectors buffer!\n");
125*2be7af18SEric Kohl         goto done;
126*2be7af18SEric Kohl     }
127*2be7af18SEric Kohl 
128*2be7af18SEric Kohl     /* Open the disk for writing */
129*2be7af18SEric Kohl     StringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
130*2be7af18SEric Kohl                      L"\\Device\\Harddisk%d\\Partition0",
131*2be7af18SEric Kohl                      CurrentDisk->DiskNumber);
132*2be7af18SEric Kohl 
133*2be7af18SEric Kohl     RtlInitUnicodeString(&Name, Buffer);
134*2be7af18SEric Kohl 
135*2be7af18SEric Kohl     InitializeObjectAttributes(&ObjectAttributes,
136*2be7af18SEric Kohl                                &Name,
137*2be7af18SEric Kohl                                OBJ_CASE_INSENSITIVE,
138*2be7af18SEric Kohl                                NULL,
139*2be7af18SEric Kohl                                NULL);
140*2be7af18SEric Kohl 
141*2be7af18SEric Kohl     Status = NtOpenFile(&FileHandle,
142*2be7af18SEric Kohl                         GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
143*2be7af18SEric Kohl                         &ObjectAttributes,
144*2be7af18SEric Kohl                         &IoStatusBlock,
145*2be7af18SEric Kohl                         0,
146*2be7af18SEric Kohl                         FILE_SYNCHRONOUS_IO_NONALERT);
147*2be7af18SEric Kohl     if (!NT_SUCCESS(Status))
148*2be7af18SEric Kohl     {
149*2be7af18SEric Kohl         DPRINT1("Failed to open the disk! (Status 0x%08lx)\n", Status);
150*2be7af18SEric Kohl         ConResPuts(StdOut, IDS_CLEAN_FAIL);
151*2be7af18SEric Kohl         goto done;
152*2be7af18SEric Kohl     }
153*2be7af18SEric Kohl 
154*2be7af18SEric Kohl     /* Clean sectors */
155*2be7af18SEric Kohl     if (bAll)
156*2be7af18SEric Kohl     {
157*2be7af18SEric Kohl         MaxCount.QuadPart = (CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) / (1024 * 1024);
158*2be7af18SEric Kohl         for (Count.QuadPart = 0; Count.QuadPart < MaxCount.QuadPart; Count.QuadPart++)
159*2be7af18SEric Kohl         {
160*2be7af18SEric Kohl             Offset.QuadPart = Count.QuadPart * (1024 * 1024);
161*2be7af18SEric Kohl             Status = NtWriteFile(FileHandle,
162*2be7af18SEric Kohl                                  NULL,
163*2be7af18SEric Kohl                                  NULL,
164*2be7af18SEric Kohl                                  NULL,
165*2be7af18SEric Kohl                                  &IoStatusBlock,
166*2be7af18SEric Kohl                                  SectorsBuffer,
167*2be7af18SEric Kohl                                  1024 * 1024,
168*2be7af18SEric Kohl                                  &Offset,
169*2be7af18SEric Kohl                                  NULL);
170*2be7af18SEric Kohl             if (!NT_SUCCESS(Status))
171*2be7af18SEric Kohl             {
172*2be7af18SEric Kohl                 DPRINT1("Failed to write MB! (Status 0x%08lx)\n", Status);
173*2be7af18SEric Kohl                 ConResPuts(StdOut, IDS_CLEAN_FAIL);
174*2be7af18SEric Kohl                 goto done;
175*2be7af18SEric Kohl             }
176*2be7af18SEric Kohl         }
177*2be7af18SEric Kohl 
178*2be7af18SEric Kohl         Size = (ULONG)(CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) % (1024 * 1024);
179*2be7af18SEric Kohl         if (Size != 0)
180*2be7af18SEric Kohl         {
181*2be7af18SEric Kohl             Offset.QuadPart += (1024 * 1024);
182*2be7af18SEric Kohl             Status = NtWriteFile(FileHandle,
183*2be7af18SEric Kohl                                  NULL,
184*2be7af18SEric Kohl                                  NULL,
185*2be7af18SEric Kohl                                  NULL,
186*2be7af18SEric Kohl                                  &IoStatusBlock,
187*2be7af18SEric Kohl                                  SectorsBuffer,
188*2be7af18SEric Kohl                                  Size,
189*2be7af18SEric Kohl                                  &Offset,
190*2be7af18SEric Kohl                                  NULL);
191*2be7af18SEric Kohl             if (!NT_SUCCESS(Status))
192*2be7af18SEric Kohl             {
193*2be7af18SEric Kohl                 DPRINT1("Failed to write the last part! (Status 0x%08lx)\n", Status);
194*2be7af18SEric Kohl                 ConResPuts(StdOut, IDS_CLEAN_FAIL);
195*2be7af18SEric Kohl                 goto done;
196*2be7af18SEric Kohl             }
197*2be7af18SEric Kohl         }
198*2be7af18SEric Kohl     }
199*2be7af18SEric Kohl     else
200*2be7af18SEric Kohl     {
201*2be7af18SEric Kohl         /* Clean the first MB */
202*2be7af18SEric Kohl         Offset.QuadPart = 0;
203*2be7af18SEric Kohl         Status = NtWriteFile(FileHandle,
204*2be7af18SEric Kohl                              NULL,
205*2be7af18SEric Kohl                              NULL,
206*2be7af18SEric Kohl                              NULL,
207*2be7af18SEric Kohl                              &IoStatusBlock,
208*2be7af18SEric Kohl                              SectorsBuffer,
209*2be7af18SEric Kohl                              1024 * 1024,
210*2be7af18SEric Kohl                              &Offset,
211*2be7af18SEric Kohl                              NULL);
212*2be7af18SEric Kohl         if (!NT_SUCCESS(Status))
213*2be7af18SEric Kohl         {
214*2be7af18SEric Kohl             DPRINT1("Failed to write the first MB! (Status 0x%08lx)\n", Status);
215*2be7af18SEric Kohl             ConResPuts(StdOut, IDS_CLEAN_FAIL);
216*2be7af18SEric Kohl             goto done;
217*2be7af18SEric Kohl         }
218*2be7af18SEric Kohl 
219*2be7af18SEric Kohl         /* Clean the last MB */
220*2be7af18SEric Kohl         Offset.QuadPart = (CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) - (1024 * 1024);
221*2be7af18SEric Kohl         Status = NtWriteFile(FileHandle,
222*2be7af18SEric Kohl                              NULL,
223*2be7af18SEric Kohl                              NULL,
224*2be7af18SEric Kohl                              NULL,
225*2be7af18SEric Kohl                              &IoStatusBlock,
226*2be7af18SEric Kohl                              SectorsBuffer,
227*2be7af18SEric Kohl                              1024 * 1024,
228*2be7af18SEric Kohl                              &Offset,
229*2be7af18SEric Kohl                              NULL);
230*2be7af18SEric Kohl         if (!NT_SUCCESS(Status))
231*2be7af18SEric Kohl         {
232*2be7af18SEric Kohl             DPRINT1("Failed to write the last MB! (Status 0x%08lx)\n", Status);
233*2be7af18SEric Kohl             ConResPuts(StdOut, IDS_CLEAN_FAIL);
234*2be7af18SEric Kohl             goto done;
235*2be7af18SEric Kohl         }
236*2be7af18SEric Kohl     }
237*2be7af18SEric Kohl 
238*2be7af18SEric Kohl     ConResPuts(StdOut, IDS_CLEAN_SUCCESS);
239*2be7af18SEric Kohl 
240*2be7af18SEric Kohl done:
241*2be7af18SEric Kohl     if (FileHandle != NULL)
242*2be7af18SEric Kohl         NtClose(FileHandle);
243*2be7af18SEric Kohl 
244*2be7af18SEric Kohl     if (SectorsBuffer != NULL)
245*2be7af18SEric Kohl         RtlFreeHeap(RtlGetProcessHeap(), 0, SectorsBuffer);
246*2be7af18SEric Kohl 
247c2c66affSColin Finck     return TRUE;
248c2c66affSColin Finck }
249