[DISKPART] Add volume support

Add the 'list volume' and 'select volume' commands
This commit is contained in:
Eric Kohl 2022-03-26 15:18:08 +01:00
parent eeb4cbcb6b
commit 2ba6b09754
16 changed files with 302 additions and 9 deletions

View file

@ -94,6 +94,7 @@ int wmain(int argc, const LPWSTR argv[])
timeout = 0;
CreatePartitionList();
CreateVolumeList();
/* If there are no command arguments, then go straight to the interpreter */
if (argc < 2)
@ -190,6 +191,7 @@ int wmain(int argc, const LPWSTR argv[])
ConResPuts(StdOut, IDS_APP_LEAVING);
done:
DestroyVolumeList();
DestroyPartitionList();
return result;

View file

@ -170,14 +170,32 @@ typedef struct _DISKENTRY
} DISKENTRY, *PDISKENTRY;
typedef struct _VOLENTRY
{
LIST_ENTRY ListEntry;
ULONG VolumeNumber;
WCHAR VolumeName[MAX_PATH];
WCHAR DriveLetter;
PWSTR pszLabel;
PWSTR pszFilesystem;
UINT DriveType;
ULARGE_INTEGER Size;
} VOLENTRY, *PVOLENTRY;
/* GLOBAL VARIABLES ***********************************************************/
extern LIST_ENTRY DiskListHead;
extern LIST_ENTRY BiosDiskListHead;
extern LIST_ENTRY VolumeListHead;
extern PDISKENTRY CurrentDisk;
extern PPARTENTRY CurrentPartition;
extern PVOLENTRY CurrentVolume;
/* PROTOTYPES *****************************************************************/
@ -282,6 +300,12 @@ CreatePartitionList(VOID);
VOID
DestroyPartitionList(VOID);
NTSTATUS
CreateVolumeList(VOID);
VOID
DestroyVolumeList(VOID);
/* recover.c */
BOOL recover_main(INT argc, LPWSTR *argv);

View file

@ -44,7 +44,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ---------------- ------- -------\n"
IDS_LIST_PARTITION_FORMAT "%c Partition %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\nThere is no disk to list partitions.\nPlease select a disk and try again.\n\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -66,6 +68,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\nInvalid partition.\n\n"
IDS_SELECT_NO_VOLUME "\nThere is no volume currently selected.\nPlease select a disk and try again.\n\n"
IDS_SELECT_VOLUME "\nVolume %lu is now the selected volume.\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -44,7 +44,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ---------------- ------- ------------\n"
IDS_LIST_PARTITION_FORMAT "%c Partycja %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\nNie wybrano dysku do wyświetlenia partycji.\nWybierz dysk i spróbuj ponownie.\n\n"
IDS_LIST_VOLUME_HEAD " Wolumin ### Lit Etykieta\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -66,6 +68,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\nNieprawidłowa partycja.\n\n"
IDS_SELECT_NO_VOLUME "\nNie wybrano woluminu.\nWybierz dysk i spróbuj ponownie.\n\n"
IDS_SELECT_VOLUME "\nObecnie wybranym woluminem jest wolumin %lu.\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -46,7 +46,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ------- --------- -------\n"
IDS_LIST_PARTITION_FORMAT "%c Partição %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\nSem discos para listar Partições.\nPor favor seleccione um disco e tente novamente.\n\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -68,6 +70,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\nInvalid partition.\n\n"
IDS_SELECT_NO_VOLUME "\nNenhum volume actualmente seleccionado.\nPor favor seleccione um disco e tente novamente.\n\n"
IDS_SELECT_VOLUME "\nVolume %lu é agora o volume seleccionado.\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -46,7 +46,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ---------------- ------- -------\n"
IDS_LIST_PARTITION_FORMAT "%c Partiție %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\nNu există niciun disc pentru a afișa partiții.\nSelectați un disc apoi reîncercați.\n\n"
IDS_LIST_VOLUME_HEAD "Volum ###\tLtr\tEtichetă\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -68,6 +70,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\nPartiție nevalidă.\n\n"
IDS_SELECT_NO_VOLUME "\nMomentan nu există niciun volum selectat.\nSelectați un disc apoi reîncercați.\n\n"
IDS_SELECT_VOLUME "\nVolumul %lu este selectat acum.\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -46,7 +46,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ---------------- ------- -------\n"
IDS_LIST_PARTITION_FORMAT "%c Раздел %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\nДиск с разметкой элементов не выбран.\nУкажите диск и повторите попытку.\n\n"
IDS_LIST_VOLUME_HEAD "Том ###\tИмя\tМетка\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -68,6 +70,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\nОшибка в разметке диска.\n\n"
IDS_SELECT_NO_VOLUME "\nТом на диске не указан.\nВыберите том диска и повторите.\n\n"
IDS_SELECT_VOLUME "\nВыбран текущим %lu том диска.\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -48,7 +48,9 @@ BEGIN
IDS_LIST_PARTITION_LINE "%c ------------- ---------------- ------- -------\n"
IDS_LIST_PARTITION_FORMAT " Partition %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\nThere is no disk to list partitions.\nPlease select a disk and try again.\n\n"
IDS_LIST_VOLUME_HEAD "Volume ###\tLtr\tLabel\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -70,6 +72,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\nInvalid partition.\n\n"
IDS_SELECT_NO_VOLUME "\nThere is no volume currently selected.\nPlease select a disk and try again.\n\n"
IDS_SELECT_VOLUME "\nVolume %lu is now the selected volume.\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -46,7 +46,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ---------------- ------- -------\n"
IDS_LIST_PARTITION_FORMAT "%c Bölüm %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\nBölümleri listelemek için bir disk yok.\nLütfen bir disk seçiniz ve yeniden deneyiniz.\n\n"
IDS_LIST_VOLUME_HEAD "Birim ###\tHarf\tEtiket\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -68,6 +70,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\nGeçersiz bölüm.\n\n"
IDS_SELECT_NO_VOLUME "\nŞimdilik bir birim seçilmemiş.\nLütfen bir disk seçiniz ve yeniden deneyiniz.\n\n"
IDS_SELECT_VOLUME "\nBirim %lu şimdi seçilen birimdir.\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -47,7 +47,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ---------------- ------- -------\n"
IDS_LIST_PARTITION_FORMAT "%c Partition %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\n这里没有要列出分区的磁盘。\n请选择一个磁盘再试一次。\n\n"
IDS_LIST_VOLUME_HEAD " 卷 ### Ltr 标签\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -69,6 +71,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\n无效的分区。\n\n"
IDS_SELECT_NO_VOLUME "\n没有当前所选的卷。\n请选择一个磁盘再试一次。\n\n"
IDS_SELECT_VOLUME "\n卷 %lu 现在是所选的卷。\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -47,7 +47,9 @@ BEGIN
IDS_LIST_PARTITION_LINE " ------------- ---------------- ------- -------\n"
IDS_LIST_PARTITION_FORMAT "%c 磁碟分割 %2lu %-16s %4I64u %-2s %4I64u %-2s\n"
IDS_LIST_PARTITION_NO_DISK "\n沒有可列出分區的磁碟。\n請選擇一個磁碟再試一次。\n\n"
IDS_LIST_VOLUME_HEAD " 磁碟區 ### Ltr 標籤\n"
IDS_LIST_VOLUME_HEAD " Volume ### Ltr Label FS Type Size Status Info\n"
IDS_LIST_VOLUME_LINE " ---------- --- ----------- ----- ---------- ------- ------- --------\n"
IDS_LIST_VOLUME_FORMAT " Volume %3lu %c %-11s %-5s %10u %4I64u %-2s\n"
END
/* RESCAN command string */
@ -69,6 +71,7 @@ BEGIN
IDS_SELECT_PARTITION_INVALID "\n無效的磁碟分割。\n\n"
IDS_SELECT_NO_VOLUME "\n目前沒有選擇磁碟區。\n請選擇一個磁碟然後再試一次。\n\n"
IDS_SELECT_VOLUME "\n磁碟區 %lu 現在是所選的磁碟區。\n\n"
IDS_SELECT_VOLUME_INVALID "\nInvalid volume.\n\n"
END
/* Disk Status */

View file

@ -220,7 +220,48 @@ static
VOID
ListVolume(VOID)
{
PLIST_ENTRY Entry;
PVOLENTRY VolumeEntry;
ULONGLONG VolumeSize;
LPWSTR lpSizeUnit;
ConResPuts(StdOut, IDS_LIST_VOLUME_HEAD);
ConResPuts(StdOut, IDS_LIST_VOLUME_LINE);
Entry = VolumeListHead.Flink;
while (Entry != &VolumeListHead)
{
VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
VolumeSize = VolumeEntry->Size.QuadPart;
if (VolumeSize >= 10737418240) /* 10 GB */
{
VolumeSize = RoundingDivide(VolumeSize, 1073741824);
lpSizeUnit = L"GB";
}
else if (VolumeSize >= 10485760) /* 10 MB */
{
VolumeSize = RoundingDivide(VolumeSize, 1048576);
lpSizeUnit = L"MB";
}
else
{
VolumeSize = RoundingDivide(VolumeSize, 1024);
lpSizeUnit = L"KB";
}
ConResPrintf(StdOut, IDS_LIST_VOLUME_FORMAT,
VolumeEntry->VolumeNumber,
VolumeEntry->DriveLetter,
(VolumeEntry->pszLabel) ? VolumeEntry->pszLabel : L"",
(VolumeEntry->pszFilesystem) ? VolumeEntry->pszFilesystem : L"",
VolumeEntry->DriveType,
VolumeSize, lpSizeUnit);
Entry = Entry->Flink;
}
ConPuts(StdOut, L"\n\n");
}
static

View file

@ -69,9 +69,11 @@ typedef struct _PARTITION_SECTOR
LIST_ENTRY DiskListHead;
LIST_ENTRY BiosDiskListHead;
LIST_ENTRY VolumeListHead;
PDISKENTRY CurrentDisk = NULL;
PPARTENTRY CurrentPartition = NULL;
PVOLENTRY CurrentVolume = NULL;
/* FUNCTIONS ******************************************************************/
@ -1173,4 +1175,137 @@ DestroyPartitionList(VOID)
}
}
static
VOID
AddVolumeToList(
ULONG ulVolumeNumber,
PWSTR pszVolumeName)
{
PVOLENTRY VolumeEntry;
WCHAR szPathNames[256];
DWORD dwLength;
WCHAR szVolumeName[MAX_PATH + 1];
WCHAR szFilesystem[MAX_PATH + 1];
VolumeEntry = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(VOLENTRY));
if (VolumeEntry == NULL)
{
return;
}
if (GetVolumePathNamesForVolumeNameW(pszVolumeName,
szPathNames,
256,
&dwLength))
{
VolumeEntry->DriveLetter = szPathNames[0];
if (GetVolumeInformationW(szPathNames,
szVolumeName,
MAX_PATH + 1,
NULL, // [out, optional] LPDWORD lpVolumeSerialNumber,
NULL, // [out, optional] LPDWORD lpMaximumComponentLength,
NULL, // [out, optional] LPDWORD lpFileSystemFlags,
szFilesystem,
MAX_PATH + 1))
{
VolumeEntry->pszLabel = RtlAllocateHeap(RtlGetProcessHeap(),
0,
(wcslen(szVolumeName) + 1) * sizeof(WCHAR));
if (VolumeEntry->pszLabel)
wcscpy(VolumeEntry->pszLabel, szVolumeName);
VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(),
0,
(wcslen(szFilesystem) + 1) * sizeof(WCHAR));
if (VolumeEntry->pszFilesystem)
wcscpy(VolumeEntry->pszFilesystem, szFilesystem);
VolumeEntry->DriveType = GetDriveType(szPathNames);
GetDiskFreeSpaceExW(szPathNames,
NULL, // [out, optional] PULARGE_INTEGER lpFreeBytesAvailableToCaller,
&VolumeEntry->Size, // [out, optional] PULARGE_INTEGER lpTotalNumberOfBytes,
NULL // [out, optional] PULARGE_INTEGER lpTotalNumberOfFreeBytes
);
}
}
VolumeEntry->VolumeNumber = ulVolumeNumber;
wcscpy(VolumeEntry->VolumeName, pszVolumeName);
InsertTailList(&VolumeListHead,
&VolumeEntry->ListEntry);
}
NTSTATUS
CreateVolumeList(VOID)
{
HANDLE hVolume = INVALID_HANDLE_VALUE;
WCHAR szVolumeName[MAX_PATH];
ULONG ulVolumeNumber = 0;
BOOL Success;
CurrentVolume = NULL;
InitializeListHead(&VolumeListHead);
hVolume = FindFirstVolumeW(szVolumeName, ARRAYSIZE(szVolumeName));
if (hVolume == INVALID_HANDLE_VALUE)
{
return STATUS_UNSUCCESSFUL;
}
AddVolumeToList(ulVolumeNumber++, szVolumeName);
for (;;)
{
Success = FindNextVolumeW(hVolume, szVolumeName, ARRAYSIZE(szVolumeName));
if (!Success)
{
break;
}
AddVolumeToList(ulVolumeNumber++, szVolumeName);
}
FindVolumeClose(hVolume);
return STATUS_SUCCESS;
}
VOID
DestroyVolumeList(VOID)
{
PLIST_ENTRY Entry;
PVOLENTRY VolumeEntry;
CurrentVolume = NULL;
/* Release disk and partition info */
while (!IsListEmpty(&VolumeListHead))
{
Entry = RemoveHeadList(&VolumeListHead);
VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
if (VolumeEntry->pszLabel)
RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
if (VolumeEntry->pszFilesystem)
RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
/* Release disk entry */
RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
}
}
/* EOF */

View file

@ -11,8 +11,10 @@
BOOL rescan_main(INT argc, LPWSTR *argv)
{
ConResPuts(StdOut, IDS_RESCAN_START);
DestroyVolumeList();
DestroyPartitionList();
CreatePartitionList();
CreateVolumeList();
ConResPuts(StdOut, IDS_RESCAN_END);
return TRUE;

View file

@ -40,6 +40,8 @@
#define IDS_LIST_PARTITION_FORMAT 3305
#define IDS_LIST_PARTITION_NO_DISK 3306
#define IDS_LIST_VOLUME_HEAD 3307
#define IDS_LIST_VOLUME_LINE 3308
#define IDS_LIST_VOLUME_FORMAT 3309
#define IDS_RESCAN_START 4100
#define IDS_RESCAN_END 4101
@ -53,6 +55,7 @@
#define IDS_SELECT_PARTITION_INVALID 4406
#define IDS_SELECT_NO_VOLUME 4407
#define IDS_SELECT_VOLUME 4408
#define IDS_SELECT_VOLUME_INVALID 4409
#define IDS_STATUS_YES 31
#define IDS_STATUS_NO 32

View file

@ -157,6 +157,63 @@ SelectPartition(
}
static
VOID
SelectVolume(
INT argc,
LPWSTR *argv)
{
PLIST_ENTRY Entry;
PVOLENTRY VolumeEntry;
LONG lValue;
LPWSTR endptr = NULL;
DPRINT("SelectVolume()\n");
if (argc > 3)
{
ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS);
return;
}
if (argc == 2)
{
if (CurrentDisk == NULL)
ConResPuts(StdOut, IDS_SELECT_NO_VOLUME);
else
ConResPrintf(StdOut, IDS_SELECT_VOLUME, CurrentVolume->VolumeNumber);
return;
}
lValue = wcstol(argv[2], &endptr, 10);
if (((lValue == 0) && (endptr == argv[2])) ||
(lValue < 0))
{
ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS);
return;
}
CurrentVolume = NULL;
Entry = VolumeListHead.Flink;
while (Entry != &VolumeListHead)
{
VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
if (VolumeEntry->VolumeNumber == (ULONG)lValue)
{
CurrentVolume = VolumeEntry;
ConResPrintf(StdOut, IDS_SELECT_VOLUME, CurrentVolume->VolumeNumber);
return;
}
Entry = Entry->Flink;
}
ConResPuts(StdErr, IDS_SELECT_VOLUME_INVALID);
}
BOOL
select_main(
INT argc,
@ -174,6 +231,8 @@ select_main(
SelectDisk(argc, argv);
else if (!wcsicmp(argv[1], L"partition"))
SelectPartition(argc, argv);
else if (!wcsicmp(argv[1], L"volume"))
SelectVolume(argc, argv);
else
ConResPuts(StdOut, IDS_HELP_CMD_SELECT);