Reactos
at master 250 lines 8.0 kB view raw
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}