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 15 BOOL 16 clean_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 TRUE; 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 TRUE; 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->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->PartitionType != 0) && 86 (IsContainerPartition(PartEntry->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->NoMbr = TRUE; 103 104 /* Wipe the layout buffer */ 105 RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDisk->LayoutBuffer); 106 107 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) + 108 ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION)); 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 TRUE; 116 } 117 118 /* Allocate a 1MB sectors buffer */ 119 SectorsBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 120 HEAP_ZERO_MEMORY, 121 1024 * 1024); 122 if (SectorsBuffer == NULL) 123 { 124 DPRINT1("Failed to allocate the sectors buffer!\n"); 125 goto done; 126 } 127 128 /* Open the disk for writing */ 129 StringCchPrintfW(Buffer, ARRAYSIZE(Buffer), 130 L"\\Device\\Harddisk%d\\Partition0", 131 CurrentDisk->DiskNumber); 132 133 RtlInitUnicodeString(&Name, Buffer); 134 135 InitializeObjectAttributes(&ObjectAttributes, 136 &Name, 137 OBJ_CASE_INSENSITIVE, 138 NULL, 139 NULL); 140 141 Status = NtOpenFile(&FileHandle, 142 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 143 &ObjectAttributes, 144 &IoStatusBlock, 145 0, 146 FILE_SYNCHRONOUS_IO_NONALERT); 147 if (!NT_SUCCESS(Status)) 148 { 149 DPRINT1("Failed to open the disk! (Status 0x%08lx)\n", Status); 150 ConResPuts(StdOut, IDS_CLEAN_FAIL); 151 goto done; 152 } 153 154 /* Clean sectors */ 155 if (bAll) 156 { 157 MaxCount.QuadPart = (CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) / (1024 * 1024); 158 for (Count.QuadPart = 0; Count.QuadPart < MaxCount.QuadPart; Count.QuadPart++) 159 { 160 Offset.QuadPart = Count.QuadPart * (1024 * 1024); 161 Status = NtWriteFile(FileHandle, 162 NULL, 163 NULL, 164 NULL, 165 &IoStatusBlock, 166 SectorsBuffer, 167 1024 * 1024, 168 &Offset, 169 NULL); 170 if (!NT_SUCCESS(Status)) 171 { 172 DPRINT1("Failed to write MB! (Status 0x%08lx)\n", Status); 173 ConResPuts(StdOut, IDS_CLEAN_FAIL); 174 goto done; 175 } 176 } 177 178 Size = (ULONG)(CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) % (1024 * 1024); 179 if (Size != 0) 180 { 181 Offset.QuadPart += (1024 * 1024); 182 Status = NtWriteFile(FileHandle, 183 NULL, 184 NULL, 185 NULL, 186 &IoStatusBlock, 187 SectorsBuffer, 188 Size, 189 &Offset, 190 NULL); 191 if (!NT_SUCCESS(Status)) 192 { 193 DPRINT1("Failed to write the last part! (Status 0x%08lx)\n", Status); 194 ConResPuts(StdOut, IDS_CLEAN_FAIL); 195 goto done; 196 } 197 } 198 } 199 else 200 { 201 /* Clean the first MB */ 202 Offset.QuadPart = 0; 203 Status = NtWriteFile(FileHandle, 204 NULL, 205 NULL, 206 NULL, 207 &IoStatusBlock, 208 SectorsBuffer, 209 1024 * 1024, 210 &Offset, 211 NULL); 212 if (!NT_SUCCESS(Status)) 213 { 214 DPRINT1("Failed to write the first MB! (Status 0x%08lx)\n", Status); 215 ConResPuts(StdOut, IDS_CLEAN_FAIL); 216 goto done; 217 } 218 219 /* Clean the last MB */ 220 Offset.QuadPart = (CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) - (1024 * 1024); 221 Status = NtWriteFile(FileHandle, 222 NULL, 223 NULL, 224 NULL, 225 &IoStatusBlock, 226 SectorsBuffer, 227 1024 * 1024, 228 &Offset, 229 NULL); 230 if (!NT_SUCCESS(Status)) 231 { 232 DPRINT1("Failed to write the last MB! (Status 0x%08lx)\n", Status); 233 ConResPuts(StdOut, IDS_CLEAN_FAIL); 234 goto done; 235 } 236 } 237 238 ConResPuts(StdOut, IDS_CLEAN_SUCCESS); 239 240 done: 241 if (FileHandle != NULL) 242 NtClose(FileHandle); 243 244 if (SectorsBuffer != NULL) 245 RtlFreeHeap(RtlGetProcessHeap(), 0, SectorsBuffer); 246 247 return TRUE; 248 } 249