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