ReactOS 0.4.16-dev-1990-gfa5cf28
partlist.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS DiskPart
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/diskpart/partlist.c
5 * PURPOSE: Manages all the partitions of the OS in an interactive way.
6 * PROGRAMMERS: Eric Kohl
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include "diskpart.h"
12#include "guid.h"
13#include <ntddscsi.h>
14
15#define NDEBUG
16#include <debug.h>
17
18#define InsertAscendingList(ListHead, NewEntry, Type, ListEntryField, SortField)\
19{\
20 PLIST_ENTRY current;\
21\
22 current = (ListHead)->Flink;\
23 while (current != (ListHead))\
24 {\
25 if (CONTAINING_RECORD(current, Type, ListEntryField)->SortField >=\
26 (NewEntry)->SortField)\
27 {\
28 break;\
29 }\
30 current = current->Flink;\
31 }\
32\
33 InsertTailList(current, &((NewEntry)->ListEntryField));\
34}
35
36/* We have to define it there, because it is not in the MS DDK */
37#define PARTITION_LINUX 0x83
38
39#define PARTITION_TBL_SIZE 4
40
41#define MBR_MAGIC 0xAA55
42
43#include <pshpack1.h>
44
45typedef struct _PARTITION
46{
47 unsigned char BootFlags; /* bootable? 0=no, 128=yes */
48 unsigned char StartingHead; /* beginning head number */
49 unsigned char StartingSector; /* beginning sector number */
50 unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */
51 unsigned char PartitionType; /* Operating System type indicator code */
52 unsigned char EndingHead; /* ending head number */
53 unsigned char EndingSector; /* ending sector number */
54 unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */
55 unsigned int StartingBlock; /* first sector relative to start of disk */
56 unsigned int SectorCount; /* number of sectors in partition */
58
59typedef struct _PARTITION_SECTOR
60{
61 UCHAR BootCode[440]; /* 0x000 */
62 ULONG Signature; /* 0x1B8 */
63 UCHAR Reserved[2]; /* 0x1BC */
65 USHORT Magic; /* 0x1FE */
67
68#include <poppack.h>
69
70
71/* GLOBALS ********************************************************************/
72
76
80
81
82/* FUNCTIONS ******************************************************************/
83
84#ifdef DUMP_PARTITION_TABLE
85VOID
86DumpPartitionTable(
87 _In_ PDISKENTRY DiskEntry)
88{
90 ULONG i;
91
92 DbgPrint("\n");
93
94 if (DiskEntry->LayoutBuffer->PartitionStyle == PARTITION_STYLE_MBR)
95 {
96 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
97 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
98
99 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
100 {
101 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
102 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
103 i,
104 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
105 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
106 PartitionInfo->Mbr.HiddenSectors,
107 PartitionInfo->PartitionNumber,
108 PartitionInfo->Mbr.PartitionType,
109 PartitionInfo->Mbr.BootIndicator ? '*': ' ',
110 PartitionInfo->RewritePartition ? 'Y': 'N');
111 }
112 }
113 else if (DiskEntry->LayoutBuffer->PartitionStyle == PARTITION_STYLE_GPT)
114 {
115 DbgPrint("Index Start Length Nr RW Type \n");
116 DbgPrint("----- ------------ ------------ -- -- --------\n");
117 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
118 {
119 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
120
121 DbgPrint(" %3lu %12I64u %12I64u %2lu %c %08lx\n",
122 i,
123 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
124 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
125 PartitionInfo->PartitionNumber,
126 PartitionInfo->RewritePartition ? 'Y': 'N',
127 PartitionInfo->Gpt.PartitionType.Data1);
128 }
129 }
130
131 DbgPrint("\n");
132}
133#endif
134
135#ifdef DUMP_PARTITION_LIST
136VOID
137DumpPartitionList(
138 _In_ PDISKENTRY DiskEntry)
139{
140 PLIST_ENTRY ListEntry;
141 PPARTENTRY PartEntry;
142
143 DbgPrint("\n");
144
145 if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT)
146 {
147 DbgPrint("Disk Start Disk End Disk Length \n");
148 DbgPrint("------------ ------------ ------------\n");
149 DbgPrint("%12I64u %12I64u %12I64u\n",
150 DiskEntry->StartSector.QuadPart,
151 DiskEntry->EndSector.QuadPart,
152 DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1);
153
154 DbgPrint("\n");
155
156 DbgPrint("Start End Length Nr Type P\n");
157 DbgPrint("------------ ------------ ------------ --- -------- --\n");
158
159 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
160 ListEntry != &DiskEntry->PrimaryPartListHead;
161 ListEntry = ListEntry->Flink)
162 {
163 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
164
165 DbgPrint("%12I64u %12I64u %12I64u %3lu %08lx %c\n",
166 PartEntry->StartSector.QuadPart,
167 PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1,
168 PartEntry->SectorCount.QuadPart,
169 PartEntry->PartitionNumber,
170 PartEntry->Gpt.PartitionType.Data1,
171 PartEntry->IsPartitioned ? 'Y': 'N');
172 }
173 }
174 else if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR)
175 {
176 DbgPrint("Disk Start Disk End Disk Length \n");
177 DbgPrint("------------ ------------ ------------\n");
178 DbgPrint("%12I64u %12I64u %12I64u\n",
179 DiskEntry->StartSector.QuadPart,
180 DiskEntry->EndSector.QuadPart,
181 DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1);
182
183 }
184
185 DbgPrint("\n");
186}
187#endif
188
189
194{
195 ULONGLONG Temp;
196
197 Temp = Value / Alignment;
198
199 return Temp * Alignment;
200}
201
202static
203VOID
205 PDISKENTRY DiskEntry)
206{
208 WCHAR KeyName[32];
210
212 NULL);
213
215 L"\\Scsi\\Scsi Port %lu",
216 DiskEntry->Port);
217
219 sizeof(QueryTable));
220
221 QueryTable[0].Name = L"Driver";
223 QueryTable[0].EntryContext = &DiskEntry->DriverName;
224
226 KeyName,
228 NULL,
229 NULL);
230 if (!NT_SUCCESS(Status))
231 {
232 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
233 }
234}
235
236static
238NTAPI
246{
247 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
248 UNICODE_STRING NameU;
249
250 if (ValueType == REG_SZ &&
251 ValueLength == 20 * sizeof(WCHAR))
252 {
253 NameU.Buffer = (PWCHAR)ValueData;
254 NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
255 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
256
257 NameU.Buffer = (PWCHAR)ValueData + 9;
258 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
259
260 return STATUS_SUCCESS;
261 }
262
263 return STATUS_UNSUCCESSFUL;
264}
265
266static
268NTAPI
276{
277 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
278 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
280 ULONG i;
281
284 return STATUS_UNSUCCESSFUL;
285
286 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
287
288 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
289#if 0
290 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
291 FullResourceDescriptor->PartialResourceList.Revision != 1)
292 return STATUS_UNSUCCESSFUL;
293#endif
294
295 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
296 {
299 continue;
300
301 DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
302 BiosDiskEntry->DiskGeometry = *DiskGeometry;
303
304 return STATUS_SUCCESS;
305 }
306
307 return STATUS_UNSUCCESSFUL;
308}
309
310static
312NTAPI
320{
321 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
323 ULONG i;
324
327 return STATUS_UNSUCCESSFUL;
328
329 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
330
331 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
332#if 0
333 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
334 FullResourceDescriptor->PartialResourceList.Revision != 1)
335 return STATUS_UNSUCCESSFUL;
336#endif
337
338 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
339 {
341 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
342 continue;
343
344 *Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(RtlGetProcessHeap(), 0,
345 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
346 if (*Int13Drives == NULL)
347 return STATUS_NO_MEMORY;
348
349 memcpy(*Int13Drives,
350 &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
351 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
352 return STATUS_SUCCESS;
353 }
354
355 return STATUS_UNSUCCESSFUL;
356}
357
358
359#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
360
361static
362VOID
364{
366 WCHAR Name[120];
367 ULONG AdapterCount;
368 ULONG DiskCount;
370 PCM_INT13_DRIVE_PARAMETER Int13Drives;
371 PBIOSDISKENTRY BiosDiskEntry;
372
373 memset(QueryTable, 0, sizeof(QueryTable));
374
375 QueryTable[1].Name = L"Configuration Data";
377 Int13Drives = NULL;
379 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
380 &QueryTable[1],
381 (PVOID)&Int13Drives,
382 NULL);
383 if (!NT_SUCCESS(Status))
384 {
385 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
386 return;
387 }
388
389 AdapterCount = 0;
390 while (1)
391 {
393 L"%s\\%lu", ROOT_NAME, AdapterCount);
395 Name,
396 &QueryTable[2],
397 NULL,
398 NULL);
399 if (!NT_SUCCESS(Status))
400 {
401 break;
402 }
403
405 L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
407 Name,
408 &QueryTable[2],
409 NULL,
410 NULL);
411 if (NT_SUCCESS(Status))
412 {
413 while (1)
414 {
416 L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
418 Name,
419 &QueryTable[2],
420 NULL,
421 NULL);
422 if (!NT_SUCCESS(Status))
423 {
424 RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
425 return;
426 }
427
429 L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
431 Name,
432 &QueryTable[2],
433 NULL,
434 NULL);
435 if (NT_SUCCESS(Status))
436 {
437 QueryTable[0].Name = L"Identifier";
439 QueryTable[1].Name = L"Configuration Data";
441
442 DiskCount = 0;
443 while (1)
444 {
445 BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
446 if (BiosDiskEntry == NULL)
447 {
448 break;
449 }
450
452 L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
454 Name,
456 (PVOID)BiosDiskEntry,
457 NULL);
458 if (!NT_SUCCESS(Status))
459 {
460 RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry);
461 break;
462 }
463
464 BiosDiskEntry->DiskNumber = DiskCount;
465 BiosDiskEntry->Recognized = FALSE;
466
467 if (DiskCount < Int13Drives[0].NumberDrives)
468 {
469 BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
470 }
471 else
472 {
473 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
474 }
475
476 InsertTailList(&BiosDiskListHead, &BiosDiskEntry->ListEntry);
477
478 DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
479 DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
480 DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
481 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
482 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
483 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
484 DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
485 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
486 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
487 DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
488 DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
489
490 DiskCount++;
491 }
492 }
493
494 RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
495 return;
496 }
497 }
498
499 AdapterCount++;
500 }
501
502 RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
503}
504
505
506static
507VOID
509 ULONG DiskNumber,
510 PDISKENTRY DiskEntry,
511 ULONG PartitionIndex,
513{
515 PPARTENTRY PartEntry;
516
517 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
518 if (PartitionInfo->Mbr.PartitionType == 0 ||
519 (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->Mbr.PartitionType)))
520 return;
521
522 PartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
524 sizeof(PARTENTRY));
525 if (PartEntry == NULL)
526 {
527 /* TODO: Error message */
528 return;
529 }
530
531 PartEntry->DiskEntry = DiskEntry;
532
533 PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
534 PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
535
536 PartEntry->Mbr.BootIndicator = PartitionInfo->Mbr.BootIndicator;
537 PartEntry->Mbr.PartitionType = PartitionInfo->Mbr.PartitionType;
538
540 PartEntry->IsPartitioned = TRUE;
541 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
542 PartEntry->PartitionIndex = PartitionIndex;
543
544 if (IsContainerPartition(PartEntry->Mbr.PartitionType))
545 {
546 PartEntry->FormatState = Unformatted;
547
548 if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
549 DiskEntry->ExtendedPartition = PartEntry;
550 }
551 else if ((PartEntry->Mbr.PartitionType == PARTITION_FAT_12) ||
552 (PartEntry->Mbr.PartitionType == PARTITION_FAT_16) ||
553 (PartEntry->Mbr.PartitionType == PARTITION_HUGE) ||
554 (PartEntry->Mbr.PartitionType == PARTITION_XINT13) ||
555 (PartEntry->Mbr.PartitionType == PARTITION_FAT32) ||
557 {
558#if 0
559 if (CheckFatFormat())
560 {
561 PartEntry->FormatState = Preformatted;
562 }
563 else
564 {
565 PartEntry->FormatState = Unformatted;
566 }
567#endif
568 PartEntry->FormatState = Preformatted;
569 }
570 else if (PartEntry->Mbr.PartitionType == PARTITION_LINUX)
571 {
572#if 0
573 if (CheckExt2Format())
574 {
575 PartEntry->FormatState = Preformatted;
576 }
577 else
578 {
579 PartEntry->FormatState = Unformatted;
580 }
581#endif
582 PartEntry->FormatState = Preformatted;
583 }
584 else if (PartEntry->Mbr.PartitionType == PARTITION_IFS)
585 {
586#if 0
587 if (CheckNtfsFormat())
588 {
589 PartEntry->FormatState = Preformatted;
590 }
591 else if (CheckHpfsFormat())
592 {
593 PartEntry->FormatState = Preformatted;
594 }
595 else
596 {
597 PartEntry->FormatState = Unformatted;
598 }
599#endif
600 PartEntry->FormatState = Preformatted;
601 }
602 else
603 {
604 PartEntry->FormatState = UnknownFormat;
605 }
606
609 &PartEntry->ListEntry);
610 else
612 &PartEntry->ListEntry);
613}
614
615
616static
617VOID
619 ULONG DiskNumber,
620 PDISKENTRY DiskEntry,
621 ULONG PartitionIndex)
622{
624 PPARTENTRY PartEntry;
625
626 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
627 if (IsEqualGUID(&PartitionInfo->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
628 return;
629
630 PartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
632 sizeof(PARTENTRY));
633 if (PartEntry == NULL)
634 {
635 /* TODO: Error message */
636 return;
637 }
638
639 PartEntry->DiskEntry = DiskEntry;
640
641 PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
642 PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
643
644 CopyMemory(&PartEntry->Gpt.PartitionType, &PartitionInfo->Gpt.PartitionType, sizeof(GUID));
645 CopyMemory(&PartEntry->Gpt.PartitionId, &PartitionInfo->Gpt.PartitionId, sizeof(GUID));
646 PartEntry->Gpt.Attributes = PartitionInfo->Gpt.Attributes;
647
648 PartEntry->LogicalPartition = FALSE;
649 PartEntry->IsPartitioned = TRUE;
650 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
651 PartEntry->PartitionIndex = PartitionIndex;
652
653 /* TODO: Determine the format state */
654 PartEntry->FormatState = Unformatted;
655
657 &PartEntry->ListEntry);
658}
659
660
661VOID
663 PDISKENTRY DiskEntry)
664{
665 ULONGLONG StartSector, EndSector;
666 ULONGLONG LastStartSector;
667 ULONGLONG LastSectorCount;
668 ULONGLONG LastUnusedSectorCount;
669 PPARTENTRY PartEntry;
670 PPARTENTRY NewPartEntry;
672
673 DPRINT("ScanForUnpartitionedMbrDiskSpace()\n");
674
675 /* Calculate the disk sector limits */
676 /* Limit the SectorCount to 2^32 sectors for MBR disks */
677 StartSector = (ULONGLONG)DiskEntry->SectorAlignment;
678 EndSector = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1;
679
680 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
681 {
682 DPRINT1("No primary partition!\n");
683
684 /* Create a partition table that represents the empty disk */
685 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
687 sizeof(PARTENTRY));
688 if (NewPartEntry == NULL)
689 return;
690
691 NewPartEntry->DiskEntry = DiskEntry;
692
693 NewPartEntry->IsPartitioned = FALSE;
694 NewPartEntry->StartSector.QuadPart = StartSector;
695 NewPartEntry->SectorCount.QuadPart = AlignDown(EndSector + 1, DiskEntry->SectorAlignment) -
696 NewPartEntry->StartSector.QuadPart;
697
698 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
699 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
700 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
701
702 NewPartEntry->FormatState = Unformatted;
703
705 &NewPartEntry->ListEntry);
706
707 return;
708 }
709
710 /* Start at the first usable sector */
711 LastStartSector = StartSector;
712 LastSectorCount = 0ULL;
713 LastUnusedSectorCount = 0ULL;
714
715 Entry = DiskEntry->PrimaryPartListHead.Flink;
716 while (Entry != &DiskEntry->PrimaryPartListHead)
717 {
718 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
719
720 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED ||
721 PartEntry->SectorCount.QuadPart != 0ULL)
722 {
723 LastUnusedSectorCount =
724 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
725
726 if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
727 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
728 {
729 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
730
731 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
733 sizeof(PARTENTRY));
734 if (NewPartEntry == NULL)
735 return;
736
737 NewPartEntry->DiskEntry = DiskEntry;
738
739 NewPartEntry->IsPartitioned = FALSE;
740 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
741 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
742 NewPartEntry->StartSector.QuadPart;
743
744 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
745 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
746 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
747
748 NewPartEntry->FormatState = Unformatted;
749
750 /* Insert the table into the list */
751 InsertTailList(&PartEntry->ListEntry,
752 &NewPartEntry->ListEntry);
753 }
754
755 LastStartSector = PartEntry->StartSector.QuadPart;
756 LastSectorCount = PartEntry->SectorCount.QuadPart;
757 }
758
759 Entry = Entry->Flink;
760 }
761
762 /* Check for trailing unpartitioned disk space */
763 if ((LastStartSector + LastSectorCount) < (EndSector + 1))
764 {
765 LastUnusedSectorCount = AlignDown((EndSector + 1) - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
766
767 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
768 {
769 DPRINT1("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
770
771 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
773 sizeof(PARTENTRY));
774 if (NewPartEntry == NULL)
775 return;
776
777 NewPartEntry->DiskEntry = DiskEntry;
778
779 NewPartEntry->IsPartitioned = FALSE;
780 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
781 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
782 NewPartEntry->StartSector.QuadPart;
783
784 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
785 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
786 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
787
788 NewPartEntry->FormatState = Unformatted;
789
790 /* Append the table to the list */
792 &NewPartEntry->ListEntry);
793 }
794 }
795
796 if (DiskEntry->ExtendedPartition != NULL)
797 {
798 if (IsListEmpty(&DiskEntry->LogicalPartListHead))
799 {
800 DPRINT1("No logical partition!\n");
801
802 /* Create a partition table entry that represents the empty extended partition */
803 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
805 sizeof(PARTENTRY));
806 if (NewPartEntry == NULL)
807 return;
808
809 NewPartEntry->DiskEntry = DiskEntry;
810 NewPartEntry->LogicalPartition = TRUE;
811
812 NewPartEntry->IsPartitioned = FALSE;
813 NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
814 NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
815
816 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
817 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
818 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
819
820 NewPartEntry->FormatState = Unformatted;
821
823 &NewPartEntry->ListEntry);
824
825 return;
826 }
827
828 /* Start partition at head 1, cylinder 0 */
829 LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
830 LastSectorCount = 0ULL;
831 LastUnusedSectorCount = 0ULL;
832
833 Entry = DiskEntry->LogicalPartListHead.Flink;
834 while (Entry != &DiskEntry->LogicalPartListHead)
835 {
836 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
837
838 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED ||
839 PartEntry->SectorCount.QuadPart != 0ULL)
840 {
841 LastUnusedSectorCount =
842 PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
843
844 if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
845 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
846 {
847 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
848
849 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
851 sizeof(PARTENTRY));
852 if (NewPartEntry == NULL)
853 return;
854
855 NewPartEntry->DiskEntry = DiskEntry;
856 NewPartEntry->LogicalPartition = TRUE;
857
858 NewPartEntry->IsPartitioned = FALSE;
859 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
860 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
861 NewPartEntry->StartSector.QuadPart;
862
863 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
864 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
865 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
866
867 NewPartEntry->FormatState = Unformatted;
868
869 /* Insert the table into the list */
870 InsertTailList(&PartEntry->ListEntry,
871 &NewPartEntry->ListEntry);
872 }
873
874 LastStartSector = PartEntry->StartSector.QuadPart;
875 LastSectorCount = PartEntry->SectorCount.QuadPart;
876 }
877
878 Entry = Entry->Flink;
879 }
880
881 /* Check for trailing unpartitioned disk space */
882 if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
883 {
884 LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount),
885 DiskEntry->SectorAlignment);
886
887 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
888 {
889 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
890
891 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
893 sizeof(PARTENTRY));
894 if (NewPartEntry == NULL)
895 return;
896
897 NewPartEntry->DiskEntry = DiskEntry;
898 NewPartEntry->LogicalPartition = TRUE;
899
900 NewPartEntry->IsPartitioned = FALSE;
901 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
902 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
903 NewPartEntry->StartSector.QuadPart;
904
905 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
906 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
907 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
908
909 NewPartEntry->FormatState = Unformatted;
910
911 /* Append the table to the list */
913 &NewPartEntry->ListEntry);
914 }
915 }
916 }
917
918 DPRINT("ScanForUnpartitionedMbrDiskSpace() done\n");
919}
920
921
922VOID
924 PDISKENTRY DiskEntry)
925{
926 ULONGLONG LastStartSector;
927 ULONGLONG LastSectorCount;
928 ULONGLONG LastUnusedSectorCount;
929 PPARTENTRY PartEntry;
930 PPARTENTRY NewPartEntry;
932
933 DPRINT("ScanForUnpartitionedGptDiskSpace()\n");
934
935#ifdef DUMP_PARTITION_LIST
936 DumpPartitionList(DiskEntry);
937#endif
938
939 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
940 {
941 DPRINT("No partitions!\n");
942
943 /* Create a partition table that represents the empty disk */
944 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
946 sizeof(PARTENTRY));
947 if (NewPartEntry == NULL)
948 return;
949
950 NewPartEntry->DiskEntry = DiskEntry;
951
952 NewPartEntry->IsPartitioned = FALSE;
953 NewPartEntry->StartSector.QuadPart = DiskEntry->StartSector.QuadPart;
954 NewPartEntry->SectorCount.QuadPart = DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1;
955
956 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
957 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
958 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
959
960 NewPartEntry->FormatState = Unformatted;
961
963 &NewPartEntry->ListEntry);
964
965#ifdef DUMP_PARTITION_LIST
966 DumpPartitionList(DiskEntry);
967#endif
968
969 return;
970 }
971
972 /* Start at the first usable sector */
973 LastStartSector = DiskEntry->StartSector.QuadPart;
974 LastSectorCount = 0ULL;
975 LastUnusedSectorCount = 0ULL;
976
977 Entry = DiskEntry->PrimaryPartListHead.Flink;
978 while (Entry != &DiskEntry->PrimaryPartListHead)
979 {
980 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
981
982 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID) ||
983 PartEntry->SectorCount.QuadPart != 0ULL)
984 {
985 LastUnusedSectorCount =
986 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
987
988 if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
989 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
990 {
991 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
992
993 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
995 sizeof(PARTENTRY));
996 if (NewPartEntry == NULL)
997 return;
998
999 NewPartEntry->DiskEntry = DiskEntry;
1000
1001 NewPartEntry->IsPartitioned = FALSE;
1002 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
1003 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
1004 NewPartEntry->StartSector.QuadPart;
1005
1006 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
1007 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
1008 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
1009
1010 NewPartEntry->FormatState = Unformatted;
1011
1012 /* Insert the table into the list */
1013 InsertTailList(&PartEntry->ListEntry,
1014 &NewPartEntry->ListEntry);
1015 }
1016
1017 LastStartSector = PartEntry->StartSector.QuadPart;
1018 LastSectorCount = PartEntry->SectorCount.QuadPart;
1019 }
1020
1021 Entry = Entry->Flink;
1022 }
1023
1024 /* Check for trailing unpartitioned disk space */
1025 if ((LastStartSector + LastSectorCount) < DiskEntry->EndSector.QuadPart + 1)
1026 {
1027 LastUnusedSectorCount = AlignDown(DiskEntry->EndSector.QuadPart + 1 - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
1028
1029 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1030 {
1031 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
1032
1033 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
1035 sizeof(PARTENTRY));
1036 if (NewPartEntry == NULL)
1037 return;
1038
1039 NewPartEntry->DiskEntry = DiskEntry;
1040
1041 NewPartEntry->IsPartitioned = FALSE;
1042 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
1043 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
1044 NewPartEntry->StartSector.QuadPart;
1045
1046 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
1047 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
1048 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
1049
1050 NewPartEntry->FormatState = Unformatted;
1051
1052 /* Append the table to the list */
1054 &NewPartEntry->ListEntry);
1055 }
1056 }
1057
1058#ifdef DUMP_PARTITION_LIST
1059 DumpPartitionList(DiskEntry);
1060#endif
1061
1062 DPRINT("ScanForUnpartitionedGptDiskSpace() done\n");
1063}
1064
1065
1066VOID
1069 _In_ PDISKENTRY DiskEntry)
1070{
1071 ULONG LayoutBufferSize;
1072 PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer;
1075
1076 /* Allocate a layout buffer with 4 partition entries first */
1077 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
1078 ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX));
1079 DiskEntry->LayoutBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
1081 LayoutBufferSize);
1082 if (DiskEntry->LayoutBuffer == NULL)
1083 {
1084 DPRINT1("Failed to allocate the disk layout buffer!\n");
1085 return;
1086 }
1087
1088 for (;;)
1089 {
1090 DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
1092 NULL,
1093 NULL,
1094 NULL,
1095 &Iosb,
1097 NULL,
1098 0,
1099 DiskEntry->LayoutBuffer,
1100 LayoutBufferSize);
1101 if (NT_SUCCESS(Status))
1102 break;
1103
1105 {
1106 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
1107 return;
1108 }
1109
1110 LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION_EX);
1111 NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
1113 DiskEntry->LayoutBuffer,
1114 LayoutBufferSize);
1115 if (NewLayoutBuffer == NULL)
1116 {
1117 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1118 return;
1119 }
1120
1121 DiskEntry->LayoutBuffer = NewLayoutBuffer;
1122 }
1123
1124}
1125
1126
1127static
1128VOID
1131 ULONG DiskNumber)
1132{
1133 DISK_GEOMETRY DiskGeometry;
1134 SCSI_ADDRESS ScsiAddress;
1135 PDISKENTRY DiskEntry;
1139 PULONG Buffer;
1141 WCHAR Identifier[20];
1142 ULONG Checksum;
1144 ULONG i;
1145 PLIST_ENTRY ListEntry;
1146 PBIOSDISKENTRY BiosDiskEntry;
1147
1149 NULL,
1150 NULL,
1151 NULL,
1152 &Iosb,
1154 NULL,
1155 0,
1156 &DiskGeometry,
1157 sizeof(DISK_GEOMETRY));
1158 if (!NT_SUCCESS(Status))
1159 {
1160 return;
1161 }
1162
1163 if (DiskGeometry.MediaType != FixedMedia &&
1164 DiskGeometry.MediaType != RemovableMedia)
1165 {
1166 return;
1167 }
1168
1170 NULL,
1171 NULL,
1172 NULL,
1173 &Iosb,
1175 NULL,
1176 0,
1177 &ScsiAddress,
1178 sizeof(SCSI_ADDRESS));
1179 if (!NT_SUCCESS(Status))
1180 {
1181 return;
1182 }
1183
1184 Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(RtlGetProcessHeap(),
1185 0,
1186 DiskGeometry.BytesPerSector);
1187 if (Mbr == NULL)
1188 {
1189 return;
1190 }
1191
1192 FileOffset.QuadPart = 0;
1194 NULL,
1195 NULL,
1196 NULL,
1197 &Iosb,
1198 (PVOID)Mbr,
1199 DiskGeometry.BytesPerSector,
1200 &FileOffset,
1201 NULL);
1202 if (!NT_SUCCESS(Status))
1203 {
1204 RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
1205 DPRINT1("NtReadFile failed, status=%x\n", Status);
1206 return;
1207 }
1208 Signature = Mbr->Signature;
1209
1210 /* Calculate the MBR checksum */
1211 Checksum = 0;
1212 Buffer = (PULONG)Mbr;
1213 for (i = 0; i < 128; i++)
1214 {
1215 Checksum += Buffer[i];
1216 }
1217 Checksum = ~Checksum + 1;
1218
1220 L"%08x-%08x-A", Checksum, Signature);
1221 DPRINT("Identifier: %S\n", Identifier);
1222
1223 DiskEntry = RtlAllocateHeap(RtlGetProcessHeap(),
1225 sizeof(DISKENTRY));
1226 if (DiskEntry == NULL)
1227 {
1228 return;
1229 }
1230
1231// DiskEntry->Checksum = Checksum;
1232// DiskEntry->Signature = Signature;
1233 DiskEntry->BiosFound = FALSE;
1234
1235 /* Check the disk partition style */
1236 if (Mbr->Magic != MBR_MAGIC)
1237 {
1238 DPRINT("Partition style: RAW\n");
1239 DiskEntry->PartitionStyle = PARTITION_STYLE_RAW;
1240 }
1241 else
1242 {
1243 if (Mbr->Partition[0].PartitionType == PARTITION_GPT)
1244 {
1245 DPRINT("Partition style: GPT\n");
1247 }
1248 else
1249 {
1250 DPRINT("Partition style: MBR\n");
1252 }
1253 }
1254
1255 /* Free Mbr sector buffer */
1256 RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
1257
1258 ListEntry = BiosDiskListHead.Flink;
1259 while (ListEntry != &BiosDiskListHead)
1260 {
1261 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
1262 /* FIXME:
1263 * Compare the size from bios and the reported size from driver.
1264 * If we have more than one disk with a zero or with the same signatur
1265 * we must create new signatures and reboot. After the reboot,
1266 * it is possible to identify the disks.
1267 */
1268 if (BiosDiskEntry->Signature == Signature &&
1269 BiosDiskEntry->Checksum == Checksum &&
1270 !BiosDiskEntry->Recognized)
1271 {
1272 if (!DiskEntry->BiosFound)
1273 {
1274 DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
1275 DiskEntry->BiosFound = TRUE;
1276 BiosDiskEntry->Recognized = TRUE;
1277 }
1278 else
1279 {
1280 }
1281 }
1282 ListEntry = ListEntry->Flink;
1283 }
1284
1285 if (!DiskEntry->BiosFound)
1286 {
1287#if 0
1288 RtlFreeHeap(ProcessHeap, 0, DiskEntry);
1289 return;
1290#else
1291 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
1292#endif
1293 }
1294
1297
1298 DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
1299 DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
1300 DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
1301 DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
1302
1303 DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
1304 DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
1305 DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
1306 DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
1307
1308 DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
1309 (ULONGLONG)DiskGeometry.TracksPerCylinder *
1310 (ULONGLONG)DiskGeometry.SectorsPerTrack;
1311
1312// DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
1313// DiskEntry->CylinderAlignment = DiskGeometry.SectorsPerTrack * DiskGeometry.TracksPerCylinder;
1314 DiskEntry->SectorAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector;
1315 DiskEntry->CylinderAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector;
1316
1317 DPRINT1("SectorCount: %I64u\n", DiskEntry->SectorCount);
1318 DPRINT1("SectorAlignment: %lu\n", DiskEntry->SectorAlignment);
1319 DPRINT1("CylinderAlignment: %lu\n", DiskEntry->CylinderAlignment);
1320
1321 DiskEntry->DiskNumber = DiskNumber;
1322 DiskEntry->Port = ScsiAddress.PortNumber;
1323 DiskEntry->PathId = ScsiAddress.PathId;
1324 DiskEntry->TargetId = ScsiAddress.TargetId;
1325 DiskEntry->Lun = ScsiAddress.Lun;
1326
1327 GetDriverName(DiskEntry);
1328
1329 InsertAscendingList(&DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
1330
1331 ReadLayoutBuffer(FileHandle, DiskEntry);
1332
1333 DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
1334
1335#ifdef DUMP_PARTITION_TABLE
1336 DumpPartitionTable(DiskEntry);
1337#endif
1338
1339 if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR)
1340 {
1341 if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
1343 DiskEntry->LayoutBuffer->PartitionEntry[0].Mbr.PartitionType != 0)
1344 {
1345 if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
1346 {
1347 DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
1348 }
1349 else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
1350 {
1351 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1352 }
1353 else
1354 {
1355 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
1356 }
1357 }
1358 else
1359 {
1360 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1361 }
1362
1363 /* Calculate the number of usable sectors */
1364 /* Limit the number of usable sectors to 2^32 */
1365 DiskEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment;
1366 DiskEntry->EndSector.QuadPart = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1;
1367
1368 if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1369 {
1370 DiskEntry->NewDisk = TRUE;
1371 DiskEntry->LayoutBuffer->PartitionCount = 4;
1372
1373 for (i = 0; i < 4; i++)
1375 }
1376 else
1377 {
1378 for (i = 0; i < 4; i++)
1379 {
1380 AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
1381 }
1382
1383 for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
1384 {
1385 AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
1386 }
1387 }
1388
1390 }
1391 else if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT)
1392 {
1393 /* Calculate the number of usable sectors */
1394 DiskEntry->StartSector.QuadPart = AlignDown(DiskEntry->LayoutBuffer->Gpt.StartingUsableOffset.QuadPart / DiskEntry->BytesPerSector,
1395 DiskEntry->SectorAlignment) + (ULONGLONG)DiskEntry->SectorAlignment;
1396 DiskEntry->EndSector.QuadPart = AlignDown(DiskEntry->StartSector.QuadPart + (DiskEntry->LayoutBuffer->Gpt.UsableLength.QuadPart / DiskEntry->BytesPerSector) - 1,
1397 DiskEntry->SectorAlignment);
1398
1399 if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1400 {
1401 DiskEntry->NewDisk = TRUE;
1402 }
1403 else
1404 {
1405 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
1406 {
1407 AddGptPartitionToDisk(DiskNumber, DiskEntry, i);
1408 }
1409 }
1410
1412 }
1413}
1414
1415
1418{
1422 ULONG ReturnSize;
1424 ULONG DiskNumber;
1428
1429 CurrentDisk = NULL;
1431
1432// BootDisk = NULL;
1433// BootPartition = NULL;
1434
1435// TempDisk = NULL;
1436// TempPartition = NULL;
1437// FormatState = Start;
1438
1441
1443
1445 &Sdi,
1447 &ReturnSize);
1448 if (!NT_SUCCESS(Status))
1449 {
1450 return Status;
1451 }
1452
1453 for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
1454 {
1456 L"\\Device\\Harddisk%d\\Partition0",
1457 DiskNumber);
1458
1460 Buffer);
1461
1463 &Name,
1464 0,
1465 NULL,
1466 NULL);
1467
1471 &Iosb,
1474 if (NT_SUCCESS(Status))
1475 {
1476 AddDiskToList(FileHandle, DiskNumber);
1477
1479 }
1480 }
1481
1482// UpdateDiskSignatures(List);
1483
1484// AssignDriveLetters(List);
1485
1486 return STATUS_SUCCESS;
1487}
1488
1489
1490VOID
1492{
1493 PDISKENTRY DiskEntry;
1494 PBIOSDISKENTRY BiosDiskEntry;
1495 PPARTENTRY PartEntry;
1497
1498 CurrentDisk = NULL;
1500
1501 /* Release disk and partition info */
1502 while (!IsListEmpty(&DiskListHead))
1503 {
1505 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1506
1507 /* Release driver name */
1508 RtlFreeUnicodeString(&DiskEntry->DriverName);
1509
1510 /* Release primary partition list */
1511 while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
1512 {
1514 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1515
1516 RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
1517 }
1518
1519 /* Release logical partition list */
1520 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
1521 {
1523 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1524
1525 RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
1526 }
1527
1528 /* Release layout buffer */
1529 if (DiskEntry->LayoutBuffer != NULL)
1530 RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->LayoutBuffer);
1531
1532
1533 /* Release disk entry */
1534 RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry);
1535 }
1536
1537 /* Release the bios disk info */
1538 while (!IsListEmpty(&BiosDiskListHead))
1539 {
1541 BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
1542
1543 RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry);
1544 }
1545}
1546
1547
1548static
1549VOID
1552 _In_ PVOLENTRY VolumeEntry)
1553{
1554 DWORD dwBytesReturned = 0, dwLength, i;
1555 PVOLUME_DISK_EXTENTS pExtents;
1556 BOOL bResult;
1557 DWORD dwError;
1558
1559 dwLength = sizeof(VOLUME_DISK_EXTENTS);
1560 pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
1561 if (pExtents == NULL)
1562 return;
1563
1564 bResult = DeviceIoControl(VolumeHandle,
1566 NULL,
1567 0,
1568 pExtents,
1569 dwLength,
1570 &dwBytesReturned,
1571 NULL);
1572 if (!bResult)
1573 {
1574 dwError = GetLastError();
1575
1576 if (dwError != ERROR_MORE_DATA)
1577 {
1578 RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1579 return;
1580 }
1581 else
1582 {
1583 dwLength = sizeof(VOLUME_DISK_EXTENTS) + ((pExtents->NumberOfDiskExtents - 1) * sizeof(DISK_EXTENT));
1584 RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1585 pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
1586 if (pExtents == NULL)
1587 {
1588 return;
1589 }
1590
1591 bResult = DeviceIoControl(VolumeHandle,
1593 NULL,
1594 0,
1595 pExtents,
1596 dwLength,
1597 &dwBytesReturned,
1598 NULL);
1599 if (!bResult)
1600 {
1601 RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1602 return;
1603 }
1604 }
1605 }
1606
1607 for (i = 0; i < pExtents->NumberOfDiskExtents; i++)
1608 VolumeEntry->Size.QuadPart += pExtents->Extents[i].ExtentLength.QuadPart;
1609
1610 VolumeEntry->pExtents = pExtents;
1611}
1612
1613
1614static
1615VOID
1618 _In_ PVOLENTRY VolumeEntry)
1619{
1623
1626 &DeviceInfo,
1629 if (!NT_SUCCESS(Status))
1630 return;
1631
1632 switch (DeviceInfo.DeviceType)
1633 {
1634 case FILE_DEVICE_CD_ROM:
1636 VolumeEntry->VolumeType = VOLUME_TYPE_CDROM;
1637 break;
1638
1639 case FILE_DEVICE_DISK:
1641 if (DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA)
1642 VolumeEntry->VolumeType = VOLUME_TYPE_REMOVABLE;
1643 else
1644 VolumeEntry->VolumeType = VOLUME_TYPE_PARTITION;
1645 break;
1646
1647 default:
1648 VolumeEntry->VolumeType = VOLUME_TYPE_UNKNOWN;
1649 break;
1650 }
1651}
1652
1653
1654static
1655VOID
1657 ULONG ulVolumeNumber,
1658 PWSTR pszVolumeName)
1659{
1660 PVOLENTRY VolumeEntry;
1662
1663 DWORD dwError, dwLength;
1664 WCHAR szPathNames[MAX_PATH + 1];
1665 WCHAR szVolumeName[MAX_PATH + 1];
1666 WCHAR szFilesystem[MAX_PATH + 1];
1667
1668 DWORD CharCount = 0;
1669 size_t Index = 0;
1670
1675
1676 DPRINT("AddVolumeToList(%S)\n", pszVolumeName);
1677
1678 VolumeEntry = RtlAllocateHeap(RtlGetProcessHeap(),
1680 sizeof(VOLENTRY));
1681 if (VolumeEntry == NULL)
1682 return;
1683
1684 VolumeEntry->VolumeNumber = ulVolumeNumber;
1685 wcscpy(VolumeEntry->VolumeName, pszVolumeName);
1686
1687 Index = wcslen(pszVolumeName) - 1;
1688
1689 pszVolumeName[Index] = L'\0';
1690
1691 CharCount = QueryDosDeviceW(&pszVolumeName[4], VolumeEntry->DeviceName, ARRAYSIZE(VolumeEntry->DeviceName));
1692
1693 pszVolumeName[Index] = L'\\';
1694
1695 if (CharCount == 0)
1696 {
1697 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
1698 return;
1699 }
1700
1701 DPRINT("DeviceName: %S\n", VolumeEntry->DeviceName);
1702
1703 RtlInitUnicodeString(&Name, VolumeEntry->DeviceName);
1704
1706 &Name,
1707 0,
1708 NULL,
1709 NULL);
1710
1714 &Iosb,
1715 0,
1717 if (NT_SUCCESS(Status))
1718 {
1719 GetVolumeType(VolumeHandle, VolumeEntry);
1720 GetVolumeExtents(VolumeHandle, VolumeEntry);
1722 }
1723
1724 if (GetVolumeInformationW(pszVolumeName,
1725 szVolumeName,
1726 MAX_PATH + 1,
1727 NULL, // [out, optional] LPDWORD lpVolumeSerialNumber,
1728 NULL, // [out, optional] LPDWORD lpMaximumComponentLength,
1729 NULL, // [out, optional] LPDWORD lpFileSystemFlags,
1730 szFilesystem,
1731 MAX_PATH + 1))
1732 {
1733 VolumeEntry->pszLabel = RtlAllocateHeap(RtlGetProcessHeap(),
1734 0,
1735 (wcslen(szVolumeName) + 1) * sizeof(WCHAR));
1736 if (VolumeEntry->pszLabel)
1737 wcscpy(VolumeEntry->pszLabel, szVolumeName);
1738
1739 VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(),
1740 0,
1741 (wcslen(szFilesystem) + 1) * sizeof(WCHAR));
1742 if (VolumeEntry->pszFilesystem)
1743 wcscpy(VolumeEntry->pszFilesystem, szFilesystem);
1744 }
1745 else
1746 {
1747 dwError = GetLastError();
1748 if (dwError == ERROR_UNRECOGNIZED_VOLUME)
1749 {
1750 VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(),
1751 0,
1752 (3 + 1) * sizeof(WCHAR));
1753 if (VolumeEntry->pszFilesystem)
1754 wcscpy(VolumeEntry->pszFilesystem, L"RAW");
1755 }
1756 }
1757
1758 if (GetVolumePathNamesForVolumeNameW(pszVolumeName,
1759 szPathNames,
1760 ARRAYSIZE(szPathNames),
1761 &dwLength))
1762 {
1763 VolumeEntry->DriveLetter = szPathNames[0];
1764 }
1765
1767 &VolumeEntry->ListEntry);
1768}
1769
1770
1773{
1774 HANDLE hVolume = INVALID_HANDLE_VALUE;
1775 WCHAR szVolumeName[MAX_PATH];
1776 ULONG ulVolumeNumber = 0;
1777 BOOL Success;
1778
1780
1782
1783 hVolume = FindFirstVolumeW(szVolumeName, ARRAYSIZE(szVolumeName));
1784 if (hVolume == INVALID_HANDLE_VALUE)
1785 {
1786
1787 return STATUS_UNSUCCESSFUL;
1788 }
1789
1790 AddVolumeToList(ulVolumeNumber++, szVolumeName);
1791
1792 for (;;)
1793 {
1794 Success = FindNextVolumeW(hVolume, szVolumeName, ARRAYSIZE(szVolumeName));
1795 if (!Success)
1796 {
1797 break;
1798 }
1799
1800 AddVolumeToList(ulVolumeNumber++, szVolumeName);
1801 }
1802
1803 FindVolumeClose(hVolume);
1804
1805 return STATUS_SUCCESS;
1806}
1807
1808
1809VOID
1811{
1813 PVOLENTRY VolumeEntry;
1814
1816
1817 /* Release disk and partition info */
1818 while (!IsListEmpty(&VolumeListHead))
1819 {
1821 VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
1822
1823 if (VolumeEntry->pszLabel)
1824 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
1825
1826 if (VolumeEntry->pszFilesystem)
1827 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
1828
1829 if (VolumeEntry->pExtents)
1830 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
1831
1832 /* Release disk entry */
1833 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
1834 }
1835}
1836
1837
1840 _In_ PDISKENTRY DiskEntry)
1841{
1849 ULONG PartitionCount;
1850 PLIST_ENTRY ListEntry;
1851 PPARTENTRY PartEntry;
1853
1854 DPRINT("WriteMbrPartitions() Disk: %lu\n", DiskEntry->DiskNumber);
1855
1856 /* If the disk is not dirty, there is nothing to do */
1857 if (!DiskEntry->Dirty)
1858 return STATUS_SUCCESS;
1859
1861 L"\\Device\\Harddisk%lu\\Partition0",
1862 DiskEntry->DiskNumber);
1864
1866 &Name,
1868 NULL,
1869 NULL);
1870
1874 &Iosb,
1875 0,
1877 if (!NT_SUCCESS(Status))
1878 {
1879 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1880 return Status;
1881 }
1882
1883 //
1884 // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
1885 // the disk in MBR or GPT format in case the disk was not initialized!!
1886 // For this we must ask the user which format to use.
1887 //
1888
1889 /* Save the original partition count to be restored later (see comment below) */
1890 PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
1891
1892 /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
1893 BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
1894 ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION_EX));
1896 NULL,
1897 NULL,
1898 NULL,
1899 &Iosb,
1901 DiskEntry->LayoutBuffer,
1902 BufferSize,
1903 DiskEntry->LayoutBuffer,
1904 BufferSize);
1906
1907 /*
1908 * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
1909 * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
1910 * where such a table is expected to enumerate up to 4 partitions:
1911 * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
1912 * Due to this we need to restore the original PartitionCount number.
1913 */
1914 DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
1915
1916 /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
1917 if (!NT_SUCCESS(Status))
1918 {
1919 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
1920 return Status;
1921 }
1922
1923 /* Update the partition numbers */
1924
1925 /* Update the primary partition table */
1926 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
1927 ListEntry != &DiskEntry->PrimaryPartListHead;
1928 ListEntry = ListEntry->Flink)
1929 {
1930 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1931
1932 if (PartEntry->IsPartitioned)
1933 {
1935 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
1936 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
1937 }
1938 }
1939
1940 /* Update the logical partition table */
1941 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
1942 ListEntry != &DiskEntry->LogicalPartListHead;
1943 ListEntry = ListEntry->Flink)
1944 {
1945 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1946
1947 if (PartEntry->IsPartitioned)
1948 {
1950 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
1951 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
1952 }
1953 }
1954
1955 /* The layout has been successfully updated, the disk is not dirty anymore */
1956 DiskEntry->Dirty = FALSE;
1957
1958 return Status;
1959}
1960
1961
1964 _In_ PDISKENTRY DiskEntry)
1965{
1973
1974 DPRINT("WriteGptPartitions() Disk: %lu\n", DiskEntry->DiskNumber);
1975
1976 /* If the disk is not dirty, there is nothing to do */
1977 if (!DiskEntry->Dirty)
1978 return STATUS_SUCCESS;
1979
1981 L"\\Device\\Harddisk%lu\\Partition0",
1982 DiskEntry->DiskNumber);
1984
1986 &Name,
1988 NULL,
1989 NULL);
1990
1994 &Iosb,
1995 0,
1997 if (!NT_SUCCESS(Status))
1998 {
1999 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2000 return Status;
2001 }
2002
2003 //
2004 // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
2005 // the disk in MBR or GPT format in case the disk was not initialized!!
2006 // For this we must ask the user which format to use.
2007 //
2008
2009 /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
2010 BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
2011 ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION_EX));
2013 NULL,
2014 NULL,
2015 NULL,
2016 &Iosb,
2018 DiskEntry->LayoutBuffer,
2019 BufferSize,
2020 DiskEntry->LayoutBuffer,
2021 BufferSize);
2023
2024 /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT_EX call succeeded */
2025 if (!NT_SUCCESS(Status))
2026 {
2027 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT_EX failed (Status 0x%08lx)\n", Status);
2028 return Status;
2029 }
2030
2031 /* The layout has been successfully updated, the disk is not dirty anymore */
2032 DiskEntry->Dirty = FALSE;
2033
2034 return Status;
2035}
2036
2037
2038static
2039BOOLEAN
2042{
2043 if (PartitionInfo->StartingOffset.QuadPart == 0 &&
2044 PartitionInfo->PartitionLength.QuadPart == 0)
2045 {
2046 return TRUE;
2047 }
2048
2049 return FALSE;
2050}
2051
2052
2053static
2054BOOLEAN
2057 IN PDISKENTRY DiskEntry,
2058 IN PPARTENTRY PartEntry)
2059{
2060 if ((PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector) &&
2061 (PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector))
2062 {
2063 return TRUE;
2064 }
2065
2066 return FALSE;
2067}
2068
2069
2070ULONG
2072 _In_ PDISKENTRY DiskEntry)
2073{
2075 PPARTENTRY PartEntry;
2076 ULONG Count = 0;
2077
2078 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
2079 Entry != &DiskEntry->PrimaryPartListHead;
2080 Entry = Entry->Flink)
2081 {
2082 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2083 if (PartEntry->IsPartitioned)
2084 Count++;
2085 }
2086
2087 return Count;
2088}
2089
2090
2091static
2092ULONG
2094 _In_ PDISKENTRY DiskEntry)
2095{
2096 PLIST_ENTRY ListEntry;
2097 PPARTENTRY PartEntry;
2098 ULONG Count = 0;
2099
2100 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2101 ListEntry != &DiskEntry->LogicalPartListHead;
2102 ListEntry = ListEntry->Flink)
2103 {
2104 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2105 if (PartEntry->IsPartitioned)
2106 Count++;
2107 }
2108
2109 return Count;
2110}
2111
2112
2113static
2114BOOLEAN
2116 _In_ PDISKENTRY DiskEntry)
2117{
2118 PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer;
2119 ULONG NewPartitionCount;
2120 ULONG CurrentPartitionCount = 0;
2121 ULONG LayoutBufferSize;
2122 ULONG i;
2123
2124 DPRINT1("ReAllocateLayoutBuffer()\n");
2125
2126 NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
2127
2128 if (DiskEntry->LayoutBuffer)
2129 CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
2130
2131 DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
2132 CurrentPartitionCount, NewPartitionCount);
2133
2134 if (CurrentPartitionCount == NewPartitionCount)
2135 return TRUE;
2136
2137 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
2138 ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX));
2139 NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
2141 DiskEntry->LayoutBuffer,
2142 LayoutBufferSize);
2143 if (NewLayoutBuffer == NULL)
2144 {
2145 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
2146 return FALSE;
2147 }
2148
2149 NewLayoutBuffer->PartitionCount = NewPartitionCount;
2150
2151 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2152 if (NewPartitionCount > CurrentPartitionCount)
2153 {
2154 for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
2155 {
2156 NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
2157 }
2158 }
2159
2160 DiskEntry->LayoutBuffer = NewLayoutBuffer;
2161
2162 return TRUE;
2163}
2164
2165
2166VOID
2168 _In_ PDISKENTRY DiskEntry)
2169{
2172 PLIST_ENTRY ListEntry;
2173 PPARTENTRY PartEntry;
2174 LARGE_INTEGER HiddenSectors64;
2175 ULONG Index;
2177
2178 DPRINT("UpdateMbrDiskLayout()\n");
2179
2180 /* Resize the layout buffer if necessary */
2181 if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
2182 {
2183 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2184 return;
2185 }
2186
2187 DiskEntry->LayoutBuffer->PartitionStyle = PARTITION_STYLE_MBR;
2188
2189 /* Update the primary partition table */
2190 Index = 0;
2191 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2192 ListEntry != &DiskEntry->PrimaryPartListHead;
2193 ListEntry = ListEntry->Flink)
2194 {
2195 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2196
2197 if (PartEntry->IsPartitioned)
2198 {
2200
2201 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2202 PartEntry->PartitionIndex = Index;
2203
2204 /* Reset the current partition number only for newly-created (unmounted) partitions */
2205 if (PartEntry->New)
2206 PartEntry->PartitionNumber = 0;
2207
2209
2210 if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
2211 {
2212 DPRINT1("Updating primary partition entry %lu\n", Index);
2213
2214 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2215 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2216 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2217 PartitionInfo->Mbr.HiddenSectors = PartEntry->StartSector.LowPart;
2218 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2219 PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType;
2220 PartitionInfo->Mbr.BootIndicator = PartEntry->Mbr.BootIndicator;
2221 PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType);
2222 PartitionInfo->RewritePartition = TRUE;
2223 }
2224
2225 if (!IsContainerPartition(PartEntry->Mbr.PartitionType))
2227
2228 Index++;
2229 }
2230 }
2231
2232 ASSERT(Index <= 4);
2233
2234 /* Update the logical partition table */
2235 Index = 4;
2236 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2237 ListEntry != &DiskEntry->LogicalPartListHead;
2238 ListEntry = ListEntry->Flink)
2239 {
2240 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2241
2242 if (PartEntry->IsPartitioned)
2243 {
2245
2246 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2247 PartEntry->PartitionIndex = Index;
2248
2249 /* Reset the current partition number only for newly-created (unmounted) partitions */
2250 if (PartEntry->New)
2251 PartEntry->PartitionNumber = 0;
2252
2254
2255 DPRINT1("Updating logical partition entry %lu\n", Index);
2256
2257 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2258 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2259 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2260 PartitionInfo->Mbr.HiddenSectors = DiskEntry->SectorAlignment;
2261 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2262 PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType;
2263 PartitionInfo->Mbr.BootIndicator = FALSE;
2264 PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType);
2265 PartitionInfo->RewritePartition = TRUE;
2266
2267 /* Fill the link entry of the previous partition entry */
2268 if (LinkInfo != NULL)
2269 {
2271 LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2272 LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2273 HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
2274 LinkInfo->Mbr.HiddenSectors = HiddenSectors64.LowPart;
2275 LinkInfo->PartitionNumber = 0;
2277 LinkInfo->Mbr.BootIndicator = FALSE;
2278 LinkInfo->Mbr.RecognizedPartition = FALSE;
2279 LinkInfo->RewritePartition = TRUE;
2280 }
2281
2282 /* Save a pointer to the link entry of the current partition entry */
2283 LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
2284
2286 Index += 4;
2287 }
2288 }
2289
2290 /* Wipe unused primary partition entries */
2291 for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
2292 {
2293 DPRINT1("Primary partition entry %lu\n", Index);
2294
2295 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2296
2298 {
2299 DPRINT1("Wiping primary partition entry %lu\n", Index);
2300
2301 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2302 PartitionInfo->StartingOffset.QuadPart = 0;
2303 PartitionInfo->PartitionLength.QuadPart = 0;
2304 PartitionInfo->Mbr.HiddenSectors = 0;
2305 PartitionInfo->PartitionNumber = 0;
2306 PartitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
2307 PartitionInfo->Mbr.BootIndicator = FALSE;
2308 PartitionInfo->Mbr.RecognizedPartition = FALSE;
2309 PartitionInfo->RewritePartition = TRUE;
2310 }
2311 }
2312
2313 /* Wipe unused logical partition entries */
2314 for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
2315 {
2316 if (Index % 4 >= 2)
2317 {
2318 DPRINT1("Logical partition entry %lu\n", Index);
2319
2320 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2321
2323 {
2324 DPRINT1("Wiping partition entry %lu\n", Index);
2325
2326 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2327 PartitionInfo->StartingOffset.QuadPart = 0;
2328 PartitionInfo->PartitionLength.QuadPart = 0;
2329 PartitionInfo->Mbr.HiddenSectors = 0;
2330 PartitionInfo->PartitionNumber = 0;
2331 PartitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
2332 PartitionInfo->Mbr.BootIndicator = FALSE;
2333 PartitionInfo->Mbr.RecognizedPartition = FALSE;
2334 PartitionInfo->RewritePartition = TRUE;
2335 }
2336 }
2337 }
2338
2339 DiskEntry->Dirty = TRUE;
2340}
2341
2342
2343VOID
2345 _In_ PDISKENTRY DiskEntry,
2346 _In_ BOOL DeleteEntry)
2347{
2348 PLIST_ENTRY ListEntry;
2349 PPARTENTRY PartEntry;
2351 ULONG Count, Index;
2352
2353 DPRINT("UpdateGptDiskLayout()\n");
2354
2355 /* Count used partition entries */
2356 Count = 0;
2357 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2358 ListEntry != &DiskEntry->PrimaryPartListHead;
2359 ListEntry = ListEntry->Flink)
2360 {
2361 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2362
2363 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
2364 Count++;
2365 }
2366
2367 DPRINT("Used partition entries: %lu\n", Count);
2368
2369 if (DeleteEntry)
2370 Count++;
2371
2372 /* Reallocate the layout buffer */
2373 if (Count != DiskEntry->LayoutBuffer->PartitionCount)
2374 {
2375 PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer;
2376 ULONG NewLayoutBufferSize;
2377
2378 NewLayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
2380 NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
2382 DiskEntry->LayoutBuffer,
2383 NewLayoutBufferSize);
2384 if (NewLayoutBuffer == NULL)
2385 {
2386 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", NewLayoutBufferSize);
2387 return;
2388 }
2389
2390 NewLayoutBuffer->PartitionCount = Count;
2391 DiskEntry->LayoutBuffer = NewLayoutBuffer;
2392 }
2393
2394 /* Fill the new layout buffer */
2395 Index = 0;
2396 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2397 ListEntry != &DiskEntry->PrimaryPartListHead;
2398 ListEntry = ListEntry->Flink)
2399 {
2400 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2401
2402 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
2403 {
2404 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2405 PartEntry->PartitionIndex = Index;
2406
2407 DPRINT("Updating primary partition entry %lu\n", Index);
2408 PartitionInfo->PartitionStyle = PARTITION_STYLE_GPT;
2409 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2410 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2411 PartitionInfo->PartitionNumber = Index + 1;
2412 PartitionInfo->RewritePartition = TRUE;
2413 CopyMemory(&PartitionInfo->Gpt.PartitionType, &PartEntry->Gpt.PartitionType, sizeof(GUID));
2414 CopyMemory(&PartitionInfo->Gpt.PartitionId, &PartEntry->Gpt.PartitionId, sizeof(GUID));
2415 PartitionInfo->Gpt.Attributes = PartEntry->Gpt.Attributes;
2416 ZeroMemory(&PartitionInfo->Gpt.Name, 36 * sizeof(WCHAR)); /* ??? */
2417
2418 Index++;
2419 }
2420 }
2421
2422 if (DeleteEntry)
2423 {
2424 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2426 PartitionInfo->RewritePartition = TRUE;
2427 }
2428}
2429
2430
2433 _In_ PPARTENTRY PartEntry)
2434{
2435 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2436 PPARTENTRY PrevPartEntry;
2437 PLIST_ENTRY ListHead;
2438
2439 if (PartEntry->LogicalPartition)
2440 ListHead = &DiskEntry->LogicalPartListHead;
2441 else
2442 ListHead = &DiskEntry->PrimaryPartListHead;
2443
2444 if (PartEntry->ListEntry.Blink != ListHead)
2445 {
2446 PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
2447 PARTENTRY,
2448 ListEntry);
2449 if (!PrevPartEntry->IsPartitioned)
2450 {
2452 return PrevPartEntry;
2453 }
2454 }
2455
2456 return NULL;
2457}
2458
2459
2462 _In_ PPARTENTRY PartEntry)
2463{
2464 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2465 PPARTENTRY NextPartEntry;
2466 PLIST_ENTRY ListHead;
2467
2468 if (PartEntry->LogicalPartition)
2469 ListHead = &DiskEntry->LogicalPartListHead;
2470 else
2471 ListHead = &DiskEntry->PrimaryPartListHead;
2472
2473 if (PartEntry->ListEntry.Flink != ListHead)
2474 {
2475 NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
2476 PARTENTRY,
2477 ListEntry);
2478 if (!NextPartEntry->IsPartitioned)
2479 {
2481 return NextPartEntry;
2482 }
2483 }
2484
2485 return NULL;
2486}
2487
2488
2491 _In_ PPARTENTRY PartEntry)
2492{
2494 NTSTATUS LockStatus;
2498 HANDLE PartitionHandle;
2500
2501 /* Check whether the partition is valid and was mounted by the system */
2502 if (!PartEntry->IsPartitioned ||
2503 IsContainerPartition(PartEntry->Mbr.PartitionType) ||
2504 !IsRecognizedPartition(PartEntry->Mbr.PartitionType) ||
2505 PartEntry->FormatState == UnknownFormat ||
2506 // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means
2507 // it has been usually mounted with RawFS and thus needs to be dismounted.
2508/* !*PartEntry->FileSystem || */
2509 PartEntry->PartitionNumber == 0)
2510 {
2511 /* The partition is not mounted, so just return success */
2512 return STATUS_SUCCESS;
2513 }
2514
2515 ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED);
2516
2517 /* Open the volume */
2519 L"\\Device\\Harddisk%lu\\Partition%lu",
2520 PartEntry->DiskEntry->DiskNumber,
2521 PartEntry->PartitionNumber);
2523
2525 &Name,
2527 NULL,
2528 NULL);
2529
2530 Status = NtOpenFile(&PartitionHandle,
2536 if (!NT_SUCCESS(Status))
2537 {
2538 DPRINT1("ERROR: Cannot open volume %wZ for dismounting! (Status 0x%lx)\n", &Name, Status);
2539 return Status;
2540 }
2541
2542 /* Lock the volume */
2543 LockStatus = NtFsControlFile(PartitionHandle,
2544 NULL,
2545 NULL,
2546 NULL,
2549 NULL,
2550 0,
2551 NULL,
2552 0);
2553 if (!NT_SUCCESS(LockStatus))
2554 {
2555 DPRINT1("WARNING: Failed to lock volume! Operations may fail! (Status 0x%lx)\n", LockStatus);
2556 }
2557
2558 /* Dismount the volume */
2559 Status = NtFsControlFile(PartitionHandle,
2560 NULL,
2561 NULL,
2562 NULL,
2565 NULL,
2566 0,
2567 NULL,
2568 0);
2569 if (!NT_SUCCESS(Status))
2570 {
2571 DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
2572 }
2573
2574 /* Unlock the volume */
2575 LockStatus = NtFsControlFile(PartitionHandle,
2576 NULL,
2577 NULL,
2578 NULL,
2581 NULL,
2582 0,
2583 NULL,
2584 0);
2585 if (!NT_SUCCESS(LockStatus))
2586 {
2587 DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
2588 }
2589
2590 /* Close the volume */
2591 NtClose(PartitionHandle);
2592
2593 return Status;
2594}
2595
2596
2599 _In_ PPARTENTRY PartEntry)
2600{
2602 PVOLENTRY VolumeEntry;
2603 ULONG i;
2604
2605 if ((PartEntry == NULL) ||
2606 (PartEntry->DiskEntry == NULL))
2607 return NULL;
2608
2610 while (Entry != &VolumeListHead)
2611 {
2612 VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
2613
2614 if (VolumeEntry->pExtents == NULL)
2615 return NULL;
2616
2617 for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++)
2618 {
2619 if (VolumeEntry->pExtents->Extents[i].DiskNumber == PartEntry->DiskEntry->DiskNumber)
2620 {
2621 if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) &&
2622 (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector))
2623 return VolumeEntry;
2624 }
2625 }
2626
2627 Entry = Entry->Flink;
2628 }
2629
2630 return NULL;
2631}
2632
2633
2634VOID
2636 _In_ PVOLENTRY VolumeEntry)
2637{
2638 if (VolumeEntry == NULL)
2639 return;
2640
2641 if (VolumeEntry == CurrentVolume)
2643
2644 RemoveEntryList(&VolumeEntry->ListEntry);
2645
2646 if (VolumeEntry->pszLabel)
2647 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
2648
2649 if (VolumeEntry->pszFilesystem)
2650 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
2651
2652 if (VolumeEntry->pExtents)
2653 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
2654
2655 /* Release disk entry */
2656 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
2657}
2658
2659/* EOF */
unsigned char BOOLEAN
@ Identifier
Definition: asmpp.cpp:95
LONG NTSTATUS
Definition: precomp.h:26
HANDLE ProcessHeap
Definition: servman.c:15
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define DPRINT1
Definition: precomp.h:8
#define PARTITION_IFS
Definition: disk.h:78
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:71
#define PARTITION_XINT13
Definition: disk.h:82
#define PARTITION_FAT32
Definition: disk.h:80
#define PARTITION_FAT_12
Definition: disk.h:72
#define PARTITION_EXTENDED
Definition: disk.h:76
#define PARTITION_HUGE
Definition: disk.h:77
#define PARTITION_FAT_16
Definition: disk.h:75
#define PARTITION_GPT
Definition: disk.h:90
#define PARTITION_FAT32_XINT13
Definition: disk.h:81
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
wcscpy
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define BufferSize
Definition: mmc.h:75
LPWSTR Name
Definition: desk.c:124
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
@ VOLUME_TYPE_UNKNOWN
Definition: diskpart.h:101
@ VOLUME_TYPE_REMOVABLE
Definition: diskpart.h:100
@ VOLUME_TYPE_CDROM
Definition: diskpart.h:98
@ VOLUME_TYPE_PARTITION
Definition: diskpart.h:99
PDISKENTRY CurrentDisk
Definition: partlist.c:77
@ Preformatted
Definition: diskpart.h:92
@ LogicalPartition
Definition: disksup.c:48
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static DWORD DWORD * dwLength
Definition: fusion.c:86
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
BOOL WINAPI FindNextVolumeW(IN HANDLE handle, IN LPWSTR volume, IN DWORD len)
Definition: volume.c:1082
BOOL WINAPI GetVolumeInformationW(IN LPCWSTR lpRootPathName, IN LPWSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPWSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
Definition: volume.c:226
HANDLE WINAPI FindFirstVolumeW(IN LPWSTR volume, IN DWORD len)
Definition: volume.c:660
BOOL WINAPI FindVolumeClose(IN HANDLE hFindVolume)
Definition: volume.c:741
BOOL WINAPI GetVolumePathNamesForVolumeNameW(IN LPCWSTR lpszVolumeName, IN LPWSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
Definition: volume.c:1227
static const WCHAR Signature[]
Definition: parser.c:141
#define L(x)
Definition: resources.c:13
return Iosb
Definition: create.c:4403
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
@ SystemDeviceInformation
Definition: ntddk_ex.h:18
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _Out_ PHANDLE VolumeHandle
Definition: fltkernel.h:2283
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
@ FileFsDeviceInformation
Definition: from_kernel.h:222
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
union Alignment_ Alignment
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T) __WINE_ALLOC_SIZE(4) __WINE_DEALLOC(RtlFreeHeap
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define REG_SZ
Definition: layer.c:22
struct _BIOSDISKENTRY * PBIOSDISKENTRY
@ UnknownFormat
Definition: partlist.h:36
@ Unformatted
Definition: partlist.h:34
struct _BIOSDISKENTRY BIOSDISKENTRY
#define ZeroMemory
Definition: minwinbase.h:31
#define CopyMemory
Definition: minwinbase.h:29
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define ULL(a, b)
Definition: format_msg.c:27
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4210
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4211
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3953
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define RTL_REGISTRY_DEVICEMAP
Definition: nt_native.h:165
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define REG_FULL_RESOURCE_DESCRIPTOR
Definition: nt_native.h:1506
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:321
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:342
@ RemovableMedia
Definition: ntdddisk.h:382
@ FixedMedia
Definition: ntdddisk.h:383
#define IOCTL_DISK_SET_DRIVE_LAYOUT_EX
Definition: ntdddisk.h:208
struct _VOLUME_DISK_EXTENTS VOLUME_DISK_EXTENTS
struct _DISK_EXTENT DISK_EXTENT
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
Definition: ntddvol.h:44
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:53
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:47
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM
Definition: winioctl.h:48
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
#define CmResourceTypeDeviceSpecific
Definition: restypes.h:108
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define memset(x, y, z)
Definition: compat.h:39
IN HANDLE DstPath
Definition: fsutil.h:81
static VOID GetDriverName(IN PDISKENTRY DiskEntry)
Definition: partlist.c:105
VOID NTAPI DestroyPartitionList(IN PPARTLIST List)
Definition: partlist.c:2074
static BOOLEAN IsSamePrimaryLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo, _In_ PPARTENTRY PartEntry)
Definition: partlist.c:2492
ULONGLONG AlignDown(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:67
static NTSTATUS NTAPI DiskConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:237
#define ROOT_NAME
static VOID AddDiskToList(IN HANDLE FileHandle, IN ULONG DiskNumber, IN PPARTLIST List)
Definition: partlist.c:1445
static NTSTATUS NTAPI SystemConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:280
PPARTLIST NTAPI CreatePartitionList(VOID)
Definition: partlist.c:1988
static VOID EnumerateBiosDiskEntries(IN PPARTLIST PartList)
Definition: partlist.c:327
static BOOLEAN IsEmptyLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo)
Definition: partlist.c:2483
static BOOLEAN ReAllocateLayoutBuffer(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2537
#define GetLogicalPartitionCount(DiskEntry)
Definition: partlist.c:2530
#define GetPrimaryPartitionCount(DiskEntry)
Definition: partlist.c:2527
static NTSTATUS NTAPI DiskIdentifierQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:207
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
#define DPRINT
Definition: sndvol32.h:73
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
base of all file and directory entries
Definition: entries.h:83
BOOLEAN Recognized
Definition: diskpart.h:165
ULONG DiskNumber
Definition: partlist.h:162
ULONG Checksum
Definition: partlist.h:164
ULONG Signature
Definition: partlist.h:163
CM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
Definition: partlist.h:166
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: restypes.h:144
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@432 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@432::@441 DeviceSpecificData
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: restypes.h:100
ULARGE_INTEGER EndSector
Definition: diskpart.h:185
ULONG SectorAlignment
Definition: partlist.h:116
ULONG BiosDiskNumber
Definition: diskpart.h:188
ULARGE_INTEGER SectorCount
Definition: partlist.h:115
UNICODE_STRING DriverName
Definition: partlist.h:141
ULONG SectorsPerTrack
Definition: partlist.h:112
USHORT TargetId
Definition: diskpart.h:195
PPARTENTRY ExtendedPartition
Definition: partlist.h:153
LIST_ENTRY LogicalPartListHead
Definition: partlist.h:150
BOOLEAN NewDisk
Definition: partlist.h:138
ULONG DiskNumber
Definition: partlist.h:129
ULONG BytesPerSector
Definition: partlist.h:113
USHORT PathId
Definition: diskpart.h:194
BOOLEAN BiosFound
Definition: partlist.h:120
ULONGLONG Cylinders
Definition: partlist.h:110
USHORT Lun
Definition: diskpart.h:196
ULARGE_INTEGER StartSector
Definition: diskpart.h:184
USHORT Port
Definition: partlist.h:131
DWORD PartitionStyle
Definition: diskpart.h:202
ULONG TracksPerCylinder
Definition: partlist.h:111
LIST_ENTRY PrimaryPartListHead
Definition: partlist.h:149
ULONG CylinderAlignment
Definition: partlist.h:117
PDRIVE_LAYOUT_INFORMATION LayoutBuffer
Definition: partlist.h:143
ULONG DiskNumber
Definition: ntddvol.h:48
LARGE_INTEGER StartingOffset
Definition: ntddvol.h:49
LARGE_INTEGER ExtentLength
Definition: ntddvol.h:50
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:400
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
ULONG BytesPerSector
Definition: ntdddisk.h:404
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:421
DWORD64 Attributes
Definition: diskpart.h:114
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
BOOLEAN BootIndicator
Definition: diskpart.h:106
BOOLEAN IsPartitioned
Definition: partlist.h:82
BOOLEAN New
Definition: partlist.h:85
ULARGE_INTEGER SectorCount
Definition: partlist.h:70
struct _DISKENTRY * DiskEntry
Definition: partlist.h:66
BOOLEAN LogicalPartition
Definition: partlist.h:79
MBR_PARTITION_DATA Mbr
Definition: diskpart.h:128
FORMATSTATE FormatState
Definition: diskpart.h:139
GPT_PARTITION_DATA Gpt
Definition: diskpart.h:129
ULONG OnDiskPartitionNumber
Definition: partlist.h:74
LIST_ENTRY ListEntry
Definition: partlist.h:63
ULONG PartitionNumber
Definition: partlist.h:75
ULARGE_INTEGER StartSector
Definition: partlist.h:69
ULONG PartitionIndex
Definition: partlist.h:76
LARGE_INTEGER StartingOffset
Definition: imports.h:221
PARTITION_STYLE PartitionStyle
Definition: imports.h:220
PARTITION_INFORMATION_MBR Mbr
Definition: imports.h:226
LARGE_INTEGER PartitionLength
Definition: imports.h:222
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:408
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:409
BOOLEAN RewritePartition
Definition: ntdddisk.h:415
UCHAR BootCode[440]
Definition: partlist.h:216
PARTITION Partition[PARTITION_TBL_SIZE]
Definition: partlist.h:219
unsigned char PartitionType
Definition: partlist.h:206
unsigned char EndingSector
Definition: partlist.h:208
unsigned char BootFlags
Definition: partlist.h:202
unsigned char StartingHead
Definition: partlist.h:203
unsigned int StartingBlock
Definition: partlist.h:210
unsigned char EndingHead
Definition: partlist.h:207
unsigned char EndingCylinder
Definition: partlist.h:209
unsigned int SectorCount
Definition: partlist.h:211
unsigned char StartingSector
Definition: partlist.h:204
unsigned char StartingCylinder
Definition: partlist.h:205
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
UCHAR PathId
Definition: scsi_port.h:149
UCHAR TargetId
Definition: scsi_port.h:150
UCHAR PortNumber
Definition: scsi_port.h:148
$ULONG LowPart
Definition: ntbasedef.h:581
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
USHORT MaximumLength
Definition: env_spec_w32.h:370
PVOLUME_DISK_EXTENTS pExtents
Definition: diskpart.h:230
ULONG VolumeNumber
Definition: diskpart.h:219
PWSTR pszFilesystem
Definition: diskpart.h:226
WCHAR VolumeName[MAX_PATH]
Definition: diskpart.h:220
LIST_ENTRY ListEntry
Entry in VolumesList.
Definition: partlist.h:45
PWSTR pszLabel
Definition: diskpart.h:225
WCHAR DeviceName[MAX_PATH]
Definition: diskpart.h:221
WCHAR DriveLetter
Definition: diskpart.h:223
DISK_EXTENT Extents[1]
Definition: ntddvol.h:55
ULONG NumberOfDiskExtents
Definition: ntddvol.h:54
VOID UpdateMbrDiskLayout(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:2167
VOID RemoveVolume(_In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:2635
LIST_ENTRY VolumeListHead
Definition: partlist.c:75
static VOID GetVolumeType(_In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1616
struct _PARTITION * PPARTITION
static VOID AddGptPartitionToDisk(ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex)
Definition: partlist.c:618
#define PARTITION_LINUX
Definition: partlist.c:37
LIST_ENTRY BiosDiskListHead
Definition: partlist.c:74
PPARTENTRY GetPrevUnpartitionedEntry(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2432
VOID UpdateGptDiskLayout(_In_ PDISKENTRY DiskEntry, _In_ BOOL DeleteEntry)
Definition: partlist.c:2344
VOID DestroyVolumeList(VOID)
Definition: partlist.c:1810
struct _PARTITION_SECTOR * PPARTITION_SECTOR
static VOID AddMbrPartitionToDisk(ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex, BOOLEAN LogicalPartition)
Definition: partlist.c:508
#define PARTITION_TBL_SIZE
Definition: partlist.c:39
static VOID AddVolumeToList(ULONG ulVolumeNumber, PWSTR pszVolumeName)
Definition: partlist.c:1656
NTSTATUS CreateVolumeList(VOID)
Definition: partlist.c:1772
NTSTATUS WriteMbrPartitions(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1839
VOID ReadLayoutBuffer(_In_ HANDLE FileHandle, _In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1067
LIST_ENTRY DiskListHead
Definition: partlist.c:73
struct _PARTITION_SECTOR PARTITION_SECTOR
VOID ScanForUnpartitionedMbrDiskSpace(PDISKENTRY DiskEntry)
Definition: partlist.c:662
PVOLENTRY CurrentVolume
Definition: partlist.c:79
PPARTENTRY CurrentPartition
Definition: partlist.c:78
NTSTATUS WriteGptPartitions(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1963
PVOLENTRY GetVolumeFromPartition(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2598
PPARTENTRY GetNextUnpartitionedEntry(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2461
VOID ScanForUnpartitionedGptDiskSpace(PDISKENTRY DiskEntry)
Definition: partlist.c:923
#define MBR_MAGIC
Definition: partlist.c:41
static VOID GetVolumeExtents(_In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1550
struct _PARTITION PARTITION
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
NTSTATUS DismountVolume(_Inout_ PVOLINFO Volume, _In_ BOOLEAN Force)
Attempts to dismount the designated volume.
Definition: volutil.c:152
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2705
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
#define ERROR_UNRECOGNIZED_VOLUME
Definition: winerror.h:908
struct _CM_DISK_GEOMETRY_DEVICE_DATA * PCM_DISK_GEOMETRY_DEVICE_DATA
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180