https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2ba6b097543d7ede44c12e7942a94ebbec3a6293

commit 2ba6b097543d7ede44c12e7942a94ebbec3a6293
Author:     Eric Kohl <[email protected]>
AuthorDate: Sat Mar 26 15:18:08 2022 +0100
Commit:     Eric Kohl <[email protected]>
CommitDate: Sat Mar 26 15:18:08 2022 +0100

    [DISKPART] Add volume support
    
    Add the 'list volume' and 'select volume' commands
---
 base/system/diskpart/diskpart.c    |   2 +
 base/system/diskpart/diskpart.h    |  24 +++++++
 base/system/diskpart/lang/en-US.rc |   5 +-
 base/system/diskpart/lang/pl-PL.rc |   5 +-
 base/system/diskpart/lang/pt-PT.rc |   5 +-
 base/system/diskpart/lang/ro-RO.rc |   5 +-
 base/system/diskpart/lang/ru-RU.rc |   5 +-
 base/system/diskpart/lang/sq-AL.rc |   5 +-
 base/system/diskpart/lang/tr-TR.rc |   5 +-
 base/system/diskpart/lang/zh-CN.rc |   5 +-
 base/system/diskpart/lang/zh-TW.rc |   5 +-
 base/system/diskpart/list.c        |  41 +++++++++++
 base/system/diskpart/partlist.c    | 135 +++++++++++++++++++++++++++++++++++++
 base/system/diskpart/rescan.c      |   2 +
 base/system/diskpart/resource.h    |   3 +
 base/system/diskpart/select.c      |  59 ++++++++++++++++
 16 files changed, 302 insertions(+), 9 deletions(-)

diff --git a/base/system/diskpart/diskpart.c b/base/system/diskpart/diskpart.c
index 30b7da20f35..5f678a556d7 100644
--- a/base/system/diskpart/diskpart.c
+++ b/base/system/diskpart/diskpart.c
@@ -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;
diff --git a/base/system/diskpart/diskpart.h b/base/system/diskpart/diskpart.h
index abfc2213c74..751c3ff6aaf 100644
--- a/base/system/diskpart/diskpart.h
+++ b/base/system/diskpart/diskpart.h
@@ -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);
 
diff --git a/base/system/diskpart/lang/en-US.rc 
b/base/system/diskpart/lang/en-US.rc
index 0137f34f10c..f23a5cc13e0 100644
--- a/base/system/diskpart/lang/en-US.rc
+++ b/base/system/diskpart/lang/en-US.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/pl-PL.rc 
b/base/system/diskpart/lang/pl-PL.rc
index 8078bed8715..2656950d8b7 100644
--- a/base/system/diskpart/lang/pl-PL.rc
+++ b/base/system/diskpart/lang/pl-PL.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/pt-PT.rc 
b/base/system/diskpart/lang/pt-PT.rc
index 9ce8e6ac0a1..f3321412c72 100644
--- a/base/system/diskpart/lang/pt-PT.rc
+++ b/base/system/diskpart/lang/pt-PT.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/ro-RO.rc 
b/base/system/diskpart/lang/ro-RO.rc
index 0e75e449ac2..99c311a7800 100644
--- a/base/system/diskpart/lang/ro-RO.rc
+++ b/base/system/diskpart/lang/ro-RO.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/ru-RU.rc 
b/base/system/diskpart/lang/ru-RU.rc
index b3bd8015dfe..ad20e840a0c 100644
--- a/base/system/diskpart/lang/ru-RU.rc
+++ b/base/system/diskpart/lang/ru-RU.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/sq-AL.rc 
b/base/system/diskpart/lang/sq-AL.rc
index 87ad6659c59..2238218d669 100644
--- a/base/system/diskpart/lang/sq-AL.rc
+++ b/base/system/diskpart/lang/sq-AL.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/tr-TR.rc 
b/base/system/diskpart/lang/tr-TR.rc
index 4788477ea59..193502965c6 100644
--- a/base/system/diskpart/lang/tr-TR.rc
+++ b/base/system/diskpart/lang/tr-TR.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/zh-CN.rc 
b/base/system/diskpart/lang/zh-CN.rc
index 1a9fd494bb4..e04d919004c 100644
--- a/base/system/diskpart/lang/zh-CN.rc
+++ b/base/system/diskpart/lang/zh-CN.rc
@@ -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 */
diff --git a/base/system/diskpart/lang/zh-TW.rc 
b/base/system/diskpart/lang/zh-TW.rc
index 21be6d0cd81..15a26899024 100644
--- a/base/system/diskpart/lang/zh-TW.rc
+++ b/base/system/diskpart/lang/zh-TW.rc
@@ -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 */
diff --git a/base/system/diskpart/list.c b/base/system/diskpart/list.c
index dd7e54c8f38..714f5e3c257 100644
--- a/base/system/diskpart/list.c
+++ b/base/system/diskpart/list.c
@@ -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
diff --git a/base/system/diskpart/partlist.c b/base/system/diskpart/partlist.c
index 6202eb0439c..2113373ce83 100644
--- a/base/system/diskpart/partlist.c
+++ b/base/system/diskpart/partlist.c
@@ -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 */
diff --git a/base/system/diskpart/rescan.c b/base/system/diskpart/rescan.c
index cf4e461a0f2..29371861f01 100644
--- a/base/system/diskpart/rescan.c
+++ b/base/system/diskpart/rescan.c
@@ -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;
diff --git a/base/system/diskpart/resource.h b/base/system/diskpart/resource.h
index 4e2b35f9e24..34924947a98 100644
--- a/base/system/diskpart/resource.h
+++ b/base/system/diskpart/resource.h
@@ -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
diff --git a/base/system/diskpart/select.c b/base/system/diskpart/select.c
index bebdbadde5a..4a1804ebbfd 100644
--- a/base/system/diskpart/select.c
+++ b/base/system/diskpart/select.c
@@ -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);
 

Reply via email to