Reactos
at master 451 lines 14 kB view raw
1/* 2 * PROJECT: ReactOS DiskPart 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/system/diskpart/list.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/* FUNCTIONS ******************************************************************/ 15 16static 17VOID 18PrintSize( 19 _In_ ULONGLONG ullSize, 20 _Out_ PWSTR pszOutBuffer, 21 _In_ ULONG ulOutBufferSize) 22{ 23 WCHAR szUnitBuffer[8]; 24 INT nUnitId; 25 26 if (ullSize >= SIZE_10TB) /* 10 TB */ 27 { 28 ullSize = RoundingDivide(ullSize, SIZE_1TB); 29 nUnitId = IDS_UNIT_TB; 30 } 31 else if (ullSize >= SIZE_10GB) /* 10 GB */ 32 { 33 ullSize = RoundingDivide(ullSize, SIZE_1GB); 34 nUnitId = IDS_UNIT_GB; 35 } 36 else if (ullSize >= SIZE_10MB) /* 10 MB */ 37 { 38 ullSize = RoundingDivide(ullSize, SIZE_1MB); 39 nUnitId = IDS_UNIT_MB; 40 } 41 else if (ullSize >= SIZE_10KB) /* 10 KB */ 42 { 43 ullSize = RoundingDivide(ullSize, SIZE_1KB); 44 nUnitId = IDS_UNIT_KB; 45 } 46 else 47 { 48 nUnitId = IDS_UNIT_B; 49 } 50 51 LoadStringW(GetModuleHandle(NULL), 52 nUnitId, 53 szUnitBuffer, ARRAYSIZE(szUnitBuffer)); 54 55 swprintf(pszOutBuffer, L"%4I64u %-2s", ullSize, szUnitBuffer); 56 StringCchPrintfW(pszOutBuffer, 57 ulOutBufferSize, 58 L"%4I64u %-2s", ullSize, szUnitBuffer); 59} 60 61 62static 63ULONGLONG 64GetFreeDiskSize( 65 _In_ PDISKENTRY DiskEntry) 66{ 67 ULONGLONG SectorCount; 68 PLIST_ENTRY Entry; 69 PPARTENTRY PartEntry; 70 71 if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR) 72 { 73 SectorCount = DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1; 74 75 Entry = DiskEntry->PrimaryPartListHead.Flink; 76 while (Entry != &DiskEntry->PrimaryPartListHead) 77 { 78 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 79 80 if ((PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED) && 81 !IsContainerPartition(PartEntry->Mbr.PartitionType)) 82 { 83 SectorCount -= PartEntry->SectorCount.QuadPart; 84 } 85 86 Entry = Entry->Flink; 87 } 88 89 Entry = DiskEntry->LogicalPartListHead.Flink; 90 while (Entry != &DiskEntry->LogicalPartListHead) 91 { 92 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 93 94 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED) 95 { 96 SectorCount -= PartEntry->SectorCount.QuadPart; 97 } 98 99 Entry = Entry->Flink; 100 } 101 } 102 else if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT) 103 { 104 SectorCount = DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1; 105 106 Entry = DiskEntry->PrimaryPartListHead.Flink; 107 while (Entry != &DiskEntry->PrimaryPartListHead) 108 { 109 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 110 111 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) 112 { 113 SectorCount -= PartEntry->SectorCount.QuadPart; 114 } 115 116 Entry = Entry->Flink; 117 } 118 } 119 else 120 { 121 SectorCount = DiskEntry->SectorCount.QuadPart; 122 } 123 124 return SectorCount * DiskEntry->BytesPerSector; 125} 126 127 128VOID 129PrintDisk( 130 _In_ PDISKENTRY DiskEntry) 131{ 132 WCHAR szDiskSizeBuffer[8]; 133 WCHAR szFreeSizeBuffer[8]; 134 WCHAR szBuffer[40]; 135 ULONGLONG DiskSize; 136 ULONGLONG FreeSize; 137 138 DiskSize = DiskEntry->SectorCount.QuadPart * 139 (ULONGLONG)DiskEntry->BytesPerSector; 140 PrintSize(DiskSize, szDiskSizeBuffer, ARRAYSIZE(szDiskSizeBuffer)); 141 142 FreeSize = GetFreeDiskSize(DiskEntry); 143 PrintSize(FreeSize, szFreeSizeBuffer, ARRAYSIZE(szFreeSizeBuffer)); 144 145 LoadStringW(GetModuleHandle(NULL), 146 IDS_STATUS_ONLINE, 147 szBuffer, ARRAYSIZE(szBuffer)); 148 149 ConResPrintf(StdOut, IDS_LIST_DISK_FORMAT, 150 (CurrentDisk == DiskEntry) ? L'*' : L' ', 151 DiskEntry->DiskNumber, 152 szBuffer, 153 szDiskSizeBuffer, 154 szFreeSizeBuffer, 155 L" ", 156 (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT) ? L"*" : L" "); 157} 158 159 160EXIT_CODE 161ListDisk( 162 _In_ INT argc, 163 _In_ PWSTR *argv) 164{ 165 PLIST_ENTRY Entry; 166 PDISKENTRY DiskEntry; 167 168 /* Header labels */ 169 ConPuts(StdOut, L"\n"); 170 ConResPuts(StdOut, IDS_LIST_DISK_HEAD); 171 ConResPuts(StdOut, IDS_LIST_DISK_LINE); 172 173 Entry = DiskListHead.Flink; 174 while (Entry != &DiskListHead) 175 { 176 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry); 177 178 PrintDisk(DiskEntry); 179 180 Entry = Entry->Flink; 181 } 182 183 ConPuts(StdOut, L"\n\n"); 184 185 return EXIT_SUCCESS; 186} 187 188 189EXIT_CODE 190ListPartition( 191 _In_ INT argc, 192 _In_ PWSTR *argv) 193{ 194 PLIST_ENTRY Entry; 195 PPARTENTRY PartEntry; 196 ULONGLONG PartSize; 197 ULONGLONG PartOffset; 198 ULONG PartNumber = 1; 199 BOOL bPartitionFound = FALSE; 200 WCHAR szPartitionTypeBuffer[40]; 201 WCHAR szSizeBuffer[8]; 202 WCHAR szOffsetBuffer[8]; 203 INT nPartitionType; 204 205 if (CurrentDisk == NULL) 206 { 207 ConResPuts(StdOut, IDS_LIST_PARTITION_NO_DISK); 208 return EXIT_SUCCESS; 209 } 210 211 if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) 212 { 213 Entry = CurrentDisk->PrimaryPartListHead.Flink; 214 while (Entry != &CurrentDisk->PrimaryPartListHead) 215 { 216 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 217 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED) 218 bPartitionFound = TRUE; 219 220 Entry = Entry->Flink; 221 } 222 } 223 else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) 224 { 225 Entry = CurrentDisk->PrimaryPartListHead.Flink; 226 while (Entry != &CurrentDisk->PrimaryPartListHead) 227 { 228 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 229 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) 230 bPartitionFound = TRUE; 231 232 Entry = Entry->Flink; 233 } 234 } 235 236 if (bPartitionFound == FALSE) 237 { 238 ConPuts(StdOut, L"\n"); 239 ConResPuts(StdOut, IDS_LIST_PARTITION_NONE); 240 ConPuts(StdOut, L"\n"); 241 return EXIT_SUCCESS; 242 } 243 244 /* Header labels */ 245 ConPuts(StdOut, L"\n"); 246 ConResPuts(StdOut, IDS_LIST_PARTITION_HEAD); 247 ConResPuts(StdOut, IDS_LIST_PARTITION_LINE); 248 249 if (CurrentDisk->PartitionStyle == PARTITION_STYLE_MBR) 250 { 251 Entry = CurrentDisk->PrimaryPartListHead.Flink; 252 while (Entry != &CurrentDisk->PrimaryPartListHead) 253 { 254 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 255 256 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED) 257 { 258 PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; 259 PrintSize(PartSize, szSizeBuffer, ARRAYSIZE(szSizeBuffer)); 260 261 PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; 262 PrintSize(PartOffset, szOffsetBuffer, ARRAYSIZE(szOffsetBuffer)); 263 264 LoadStringW(GetModuleHandle(NULL), 265 IsContainerPartition(PartEntry->Mbr.PartitionType) ? IDS_PARTITION_TYPE_EXTENDED : IDS_PARTITION_TYPE_PRIMARY, 266 szPartitionTypeBuffer, ARRAYSIZE(szPartitionTypeBuffer)); 267 268 ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, 269 (CurrentPartition == PartEntry) ? L'*' : L' ', 270 PartNumber++, 271 szPartitionTypeBuffer, 272 szSizeBuffer, 273 szOffsetBuffer); 274 } 275 276 Entry = Entry->Flink; 277 } 278 279 Entry = CurrentDisk->LogicalPartListHead.Flink; 280 while (Entry != &CurrentDisk->LogicalPartListHead) 281 { 282 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 283 284 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED) 285 { 286 PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; 287 PrintSize(PartSize, szSizeBuffer, ARRAYSIZE(szSizeBuffer)); 288 289 PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; 290 PrintSize(PartOffset, szOffsetBuffer, ARRAYSIZE(szOffsetBuffer)); 291 292 LoadStringW(GetModuleHandle(NULL), 293 IDS_PARTITION_TYPE_LOGICAL, 294 szPartitionTypeBuffer, ARRAYSIZE(szPartitionTypeBuffer)); 295 ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, 296 (CurrentPartition == PartEntry) ? L'*' : L' ', 297 PartNumber++, 298 szPartitionTypeBuffer, 299 szSizeBuffer, 300 szOffsetBuffer); 301 } 302 303 Entry = Entry->Flink; 304 } 305 } 306 else if (CurrentDisk->PartitionStyle == PARTITION_STYLE_GPT) 307 { 308 Entry = CurrentDisk->PrimaryPartListHead.Flink; 309 while (Entry != &CurrentDisk->PrimaryPartListHead) 310 { 311 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); 312 313 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) 314 { 315 PartSize = PartEntry->SectorCount.QuadPart * CurrentDisk->BytesPerSector; 316 PrintSize(PartSize, szSizeBuffer, ARRAYSIZE(szSizeBuffer)); 317 318 PartOffset = PartEntry->StartSector.QuadPart * CurrentDisk->BytesPerSector; 319 PrintSize(PartOffset, szOffsetBuffer, ARRAYSIZE(szOffsetBuffer)); 320 321 if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) 322 { 323 nPartitionType = IDS_PARTITION_TYPE_UNUSED; 324 } 325 else if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_BASIC_DATA_GUID)) 326 { 327 nPartitionType = IDS_PARTITION_TYPE_PRIMARY; 328 } 329 else if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_SYSTEM_GUID)) 330 { 331 nPartitionType = IDS_PARTITION_TYPE_SYSTEM; 332 } 333 else if (IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID)) 334 { 335 nPartitionType = IDS_PARTITION_TYPE_RESERVED; 336 } 337 else 338 { 339 nPartitionType = IDS_PARTITION_TYPE_UNKNOWN; 340 } 341 342 LoadStringW(GetModuleHandle(NULL), 343 nPartitionType, 344 szPartitionTypeBuffer, ARRAYSIZE(szPartitionTypeBuffer)); 345 346 ConResPrintf(StdOut, IDS_LIST_PARTITION_FORMAT, 347 (CurrentPartition == PartEntry) ? L'*' : L' ', 348 PartNumber++, 349 szPartitionTypeBuffer, 350 szSizeBuffer, 351 szOffsetBuffer); 352 } 353 354 Entry = Entry->Flink; 355 } 356 } 357 358 ConPuts(StdOut, L"\n"); 359 360 return EXIT_SUCCESS; 361} 362 363 364VOID 365PrintVolume( 366 _In_ PVOLENTRY VolumeEntry) 367{ 368 WCHAR szVolumeTypeBuffer[30]; 369 WCHAR szInfoBuffer[16]; 370 WCHAR szSizeBuffer[8]; 371 INT nVolumeType; 372 373 switch (VolumeEntry->VolumeType) 374 { 375 case VOLUME_TYPE_CDROM: 376 nVolumeType = IDS_VOLUME_TYPE_DVD; 377 break; 378 379 case VOLUME_TYPE_PARTITION: 380 nVolumeType = IDS_VOLUME_TYPE_PARTITION; 381 break; 382 383 case VOLUME_TYPE_REMOVABLE: 384 nVolumeType = IDS_VOLUME_TYPE_REMOVABLE; 385 break; 386 387 case VOLUME_TYPE_UNKNOWN: 388 default: 389 nVolumeType = IDS_VOLUME_TYPE_UNKNOWN; 390 break; 391 } 392 393 LoadStringW(GetModuleHandle(NULL), nVolumeType, szVolumeTypeBuffer, ARRAYSIZE(szVolumeTypeBuffer)); 394 395 PrintSize(VolumeEntry->Size.QuadPart, szSizeBuffer, ARRAYSIZE(szSizeBuffer)); 396 397 szInfoBuffer[0] = UNICODE_NULL; 398 if (VolumeEntry->IsSystem) 399 LoadStringW(GetModuleHandle(NULL), IDS_INFO_SYSTEM, szInfoBuffer, ARRAYSIZE(szInfoBuffer)); 400 else if (VolumeEntry->IsBoot) 401 LoadStringW(GetModuleHandle(NULL), IDS_INFO_BOOT, szInfoBuffer, ARRAYSIZE(szInfoBuffer)); 402 403 ConResPrintf(StdOut, IDS_LIST_VOLUME_FORMAT, 404 (CurrentVolume == VolumeEntry) ? L'*' : L' ', 405 VolumeEntry->VolumeNumber, 406 VolumeEntry->DriveLetter, 407 (VolumeEntry->pszLabel) ? VolumeEntry->pszLabel : L"", 408 (VolumeEntry->pszFilesystem) ? VolumeEntry->pszFilesystem : L"", 409 szVolumeTypeBuffer, 410 szSizeBuffer, 411 L"", 412 szInfoBuffer); 413} 414 415 416EXIT_CODE 417ListVolume( 418 _In_ INT argc, 419 _In_ PWSTR *argv) 420{ 421 PLIST_ENTRY Entry; 422 PVOLENTRY VolumeEntry; 423 424 ConPuts(StdOut, L"\n"); 425 ConResPuts(StdOut, IDS_LIST_VOLUME_HEAD); 426 ConResPuts(StdOut, IDS_LIST_VOLUME_LINE); 427 428 Entry = VolumeListHead.Flink; 429 while (Entry != &VolumeListHead) 430 { 431 VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry); 432 433 PrintVolume(VolumeEntry); 434 435 Entry = Entry->Flink; 436 } 437 438 ConPuts(StdOut, L"\n"); 439 440 return EXIT_SUCCESS; 441} 442 443 444EXIT_CODE 445ListVirtualDisk( 446 _In_ INT argc, 447 _In_ PWSTR *argv) 448{ 449 ConPuts(StdOut, L"The LIST VDISK command is not implemented yet!\n"); 450 return EXIT_SUCCESS; 451}