reactos/base/system/diskpart/clean.c
2022-06-17 01:37:26 +02:00

248 lines
7.7 KiB
C

/*
* PROJECT: ReactOS DiskPart
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/system/diskpart/clean.c
* PURPOSE: Manages all the partitions of the OS in an interactive way.
* PROGRAMMERS: Lee Schroeder
*/
#include "diskpart.h"
#define NDEBUG
#include <debug.h>
BOOL
clean_main(
_In_ INT argc,
_In_ PWSTR *argv)
{
PLIST_ENTRY Entry;
PPARTENTRY PartEntry;
PVOLENTRY VolumeEntry;
BOOL bAll = FALSE;
PUCHAR SectorsBuffer = NULL;
ULONG LayoutBufferSize, Size;
INT i;
WCHAR Buffer[MAX_PATH];
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle = NULL;
LARGE_INTEGER Offset, Count, MaxCount;
NTSTATUS Status;
DPRINT("Clean()\n");
if (CurrentDisk == NULL)
{
ConResPuts(StdOut, IDS_SELECT_NO_DISK);
return TRUE;
}
/* Do not allow to clean the boot disk */
if ((CurrentDisk->BiosFound == TRUE) &&
(CurrentDisk->BiosDiskNumber == 0))
{
ConResPuts(StdOut, IDS_CLEAN_SYSTEM);
return TRUE;
}
for (i = 1; i < argc; i++)
{
if (_wcsicmp(argv[1], L"all") == 0)
{
bAll = TRUE;
}
}
/* Dismount and remove all logical partitions */
while (!IsListEmpty(&CurrentDisk->LogicalPartListHead))
{
Entry = RemoveHeadList(&CurrentDisk->LogicalPartListHead);
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
/* Dismount the logical partition */
if (PartEntry->PartitionType != 0)
{
DismountVolume(PartEntry);
VolumeEntry = GetVolumeFromPartition(PartEntry);
if (VolumeEntry)
RemoveVolume(VolumeEntry);
}
/* Delete it */
RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
}
/* Dismount and remove all primary partitions */
while (!IsListEmpty(&CurrentDisk->PrimaryPartListHead))
{
Entry = RemoveHeadList(&CurrentDisk->PrimaryPartListHead);
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
/* Dismount the primary partition */
if ((PartEntry->PartitionType != 0) &&
(IsContainerPartition(PartEntry->PartitionType) == FALSE))
{
DismountVolume(PartEntry);
VolumeEntry = GetVolumeFromPartition(PartEntry);
if (VolumeEntry)
RemoveVolume(VolumeEntry);
}
/* Delete it */
RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
}
/* Initialize the disk entry */
CurrentDisk->ExtendedPartition = NULL;
CurrentDisk->Dirty = FALSE;
CurrentDisk->NewDisk = TRUE;
CurrentDisk->NoMbr = TRUE;
/* Wipe the layout buffer */
RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDisk->LayoutBuffer);
LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
CurrentDisk->LayoutBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
LayoutBufferSize);
if (CurrentDisk->LayoutBuffer == NULL)
{
DPRINT1("Failed to allocate the disk layout buffer!\n");
return TRUE;
}
/* Allocate a 1MB sectors buffer */
SectorsBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
1024 * 1024);
if (SectorsBuffer == NULL)
{
DPRINT1("Failed to allocate the sectors buffer!\n");
goto done;
}
/* Open the disk for writing */
StringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
L"\\Device\\Harddisk%d\\Partition0",
CurrentDisk->DiskNumber);
RtlInitUnicodeString(&Name, Buffer);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&FileHandle,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to open the disk! (Status 0x%08lx)\n", Status);
ConResPuts(StdOut, IDS_CLEAN_FAIL);
goto done;
}
/* Clean sectors */
if (bAll)
{
MaxCount.QuadPart = (CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) / (1024 * 1024);
for (Count.QuadPart = 0; Count.QuadPart < MaxCount.QuadPart; Count.QuadPart++)
{
Offset.QuadPart = Count.QuadPart * (1024 * 1024);
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
SectorsBuffer,
1024 * 1024,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to write MB! (Status 0x%08lx)\n", Status);
ConResPuts(StdOut, IDS_CLEAN_FAIL);
goto done;
}
}
Size = (ULONG)(CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) % (1024 * 1024);
if (Size != 0)
{
Offset.QuadPart += (1024 * 1024);
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
SectorsBuffer,
Size,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to write the last part! (Status 0x%08lx)\n", Status);
ConResPuts(StdOut, IDS_CLEAN_FAIL);
goto done;
}
}
}
else
{
/* Clean the first MB */
Offset.QuadPart = 0;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
SectorsBuffer,
1024 * 1024,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to write the first MB! (Status 0x%08lx)\n", Status);
ConResPuts(StdOut, IDS_CLEAN_FAIL);
goto done;
}
/* Clean the last MB */
Offset.QuadPart = (CurrentDisk->SectorCount.QuadPart * CurrentDisk->BytesPerSector) - (1024 * 1024);
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
SectorsBuffer,
1024 * 1024,
&Offset,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to write the last MB! (Status 0x%08lx)\n", Status);
ConResPuts(StdOut, IDS_CLEAN_FAIL);
goto done;
}
}
ConResPuts(StdOut, IDS_CLEAN_SUCCESS);
done:
if (FileHandle != NULL)
NtClose(FileHandle);
if (SectorsBuffer != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, SectorsBuffer);
return TRUE;
}