diff --git a/base/setup/lib/utils/partlist.c b/base/setup/lib/utils/partlist.c index c045518cbfe0a..54e03b072c1f8 100644 --- a/base/setup/lib/utils/partlist.c +++ b/base/setup/lib/utils/partlist.c @@ -2009,6 +2009,7 @@ CreatePartitionList(VOID) InitializeListHead(&List->DiskListHead); InitializeListHead(&List->BiosDiskListHead); InitializeListHead(&List->VolumesList); + InitializeListHead(&List->PendingUnmountVolumesList); /* * Enumerate the disks seen by the BIOS; this will be used later @@ -2075,6 +2076,7 @@ DestroyPartitionList( PDISKENTRY DiskEntry; PBIOSDISKENTRY BiosDiskEntry; PPARTENTRY PartEntry; + PVOLENTRY VolumeEntry; PLIST_ENTRY Entry; /* Release disk and partition info */ @@ -2118,6 +2120,14 @@ DestroyPartitionList( RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry); } + /* Release the pending volumes info */ + while (!IsListEmpty(&List->PendingUnmountVolumesList)) + { + Entry = RemoveHeadList(&List->PendingUnmountVolumesList); + VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry); + RtlFreeHeap(ProcessHeap, 0, VolumeEntry); + } + /* Release list head */ RtlFreeHeap(ProcessHeap, 0, List); } @@ -2964,34 +2974,43 @@ DismountPartition( _In_ PPARTLIST List, _In_ PPARTENTRY PartEntry) { - NTSTATUS Status; PVOLENTRY Volume = PartEntry->Volume; ASSERT(PartEntry->DiskEntry->PartList == List); - /* Check whether the partition is valid and was mounted by the system */ - if (!PartEntry->IsPartitioned || - IsContainerPartition(PartEntry->PartitionType) || - !IsRecognizedPartition(PartEntry->PartitionType) || - !Volume || Volume->FormatState == UnknownFormat || + if (Volume) + { + /* Partition validation checks */ + ASSERT(Volume->PartEntry == PartEntry); + ASSERT(PartEntry->IsPartitioned); + ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED); + ASSERT(!IsContainerPartition(PartEntry->PartitionType)); + + /* Dismount the basic volume: unlink the volume from the list */ + PartEntry->Volume = NULL; + Volume->PartEntry = NULL; + RemoveEntryList(&Volume->ListEntry); + + /* Check whether the volume was mounted */ // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means - // it has been usually mounted with RawFS and thus needs to be dismounted. - PartEntry->PartitionNumber == 0) + // it has usually been mounted with RawFS and thus needs to be dismounted. + if (Volume->New || (Volume->FormatState == UnknownFormat)) + { + /* The volume is not mounted and can be deleted */ + RtlFreeHeap(ProcessHeap, 0, Volume); + Volume = NULL; + } + } + if (!Volume) { /* The partition is not mounted, so just return success */ return STATUS_SUCCESS; } - ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED); - ASSERT(Volume->PartEntry == PartEntry); - - /* Unlink the basic volume from the volumes list and dismount it */ - PartEntry->Volume = NULL; - Volume->PartEntry = NULL; - RemoveEntryList(&Volume->ListEntry); - Status = DismountVolume(&Volume->Info, TRUE); - RtlFreeHeap(ProcessHeap, 0, Volume); - return Status; + /* Dismount the basic volume, linking it into the list of volumes to unmount */ + // return DismountVolume(&Volume->Info, TRUE); // For when immediate operation mode is supported. + InsertTailList(&List->PendingUnmountVolumesList, &Volume->ListEntry); + return STATUS_SUCCESS; } BOOLEAN @@ -3758,6 +3777,21 @@ WritePartitionsToDisk( if (!List) return TRUE; + /* Unmount all the pending volumes */ + Status = STATUS_SUCCESS; + while (!IsListEmpty(&List->PendingUnmountVolumesList)) + { + NTSTATUS UnmountStatus; + Entry = RemoveHeadList(&List->PendingUnmountVolumesList); + Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry); + UnmountStatus = DismountVolume(&Volume->Info, TRUE); + if (!NT_SUCCESS(UnmountStatus)) + Status = UnmountStatus; + RtlFreeHeap(ProcessHeap, 0, Volume); + } + if (!NT_SUCCESS(Status)) + return FALSE; + /* Write all the partitions to all the disks */ for (Entry = List->DiskListHead.Flink; Entry != &List->DiskListHead; diff --git a/base/setup/lib/utils/partlist.h b/base/setup/lib/utils/partlist.h index fb20f1500c079..970321548a0b8 100644 --- a/base/setup/lib/utils/partlist.h +++ b/base/setup/lib/utils/partlist.h @@ -42,7 +42,7 @@ typedef enum _FORMATSTATE typedef struct _PARTENTRY PARTENTRY, *PPARTENTRY; typedef struct _VOLENTRY { - LIST_ENTRY ListEntry; ///< Entry in VolumesList + LIST_ENTRY ListEntry; ///< Entry in VolumesList or PendingUnmountVolumesList VOLINFO Info; FORMATSTATE FormatState; @@ -184,7 +184,8 @@ typedef struct _PARTLIST LIST_ENTRY BiosDiskListHead; /* (Basic) Volumes management */ - LIST_ENTRY VolumesList; + LIST_ENTRY VolumesList; ///< List of active volumes + LIST_ENTRY PendingUnmountVolumesList; ///< List of volumes to unmount } PARTLIST, *PPARTLIST;