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