From 8d70dca549aa0b4ff496e8a185778ab9ae18d454 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 19 Jul 2026 22:42:15 +0200 Subject: [PATCH] [FMIFS] Do not keep all file system providers loaded - Load the required provider only! - Unload providers on last process detach --- dll/win32/fmifs/chkdsk.c | 5 +- dll/win32/fmifs/format.c | 5 +- dll/win32/fmifs/init.c | 136 ++++++++++++++++++++++++++++++++------ dll/win32/fmifs/precomp.h | 15 +++-- 4 files changed, 136 insertions(+), 25 deletions(-) diff --git a/dll/win32/fmifs/chkdsk.c b/dll/win32/fmifs/chkdsk.c index 68dbf15071e..8c6ecadc702 100644 --- a/dll/win32/fmifs/chkdsk.c +++ b/dll/win32/fmifs/chkdsk.c @@ -34,7 +34,7 @@ Chkdsk( WCHAR DriveName[MAX_PATH]; WCHAR VolumeName[MAX_PATH]; - Provider = GetProvider(Format); + Provider = LoadProvider(Format); if (!Provider) { /* Unknown file system */ @@ -88,6 +88,9 @@ Chkdsk( RtlFreeUnicodeString(&usDriveRoot); Quit: + if (Provider) + UnloadProvider(Provider); + /* Report result */ Callback(DONE, Status, &Success); } diff --git a/dll/win32/fmifs/format.c b/dll/win32/fmifs/format.c index 1531cbbdb92..daf6ba79b66 100644 --- a/dll/win32/fmifs/format.c +++ b/dll/win32/fmifs/format.c @@ -58,7 +58,7 @@ FormatEx( // TODO: Convert filesystem Format into ULIB format string. // - Provider = GetProvider(Format); + Provider = LoadProvider(Format); if (!Provider) { /* Unknown file system */ @@ -130,6 +130,9 @@ FormatEx( RtlFreeUnicodeString(&usDriveRoot); Quit: + if (Provider) + UnloadProvider(Provider); + /* Report result */ Callback(DONE, 0, &Success); } diff --git a/dll/win32/fmifs/init.c b/dll/win32/fmifs/init.c index b03e83a6775..2fb13fbe9af 100644 --- a/dll/win32/fmifs/init.c +++ b/dll/win32/fmifs/init.c @@ -5,7 +5,7 @@ * PURPOSE: Initialisation * * PROGRAMMERS: Emanuele Aliberti - * Hervé Poussineau (hpoussin@reactos.org) + * Hervé Poussineau (hpoussin@reactos.org) */ #include "precomp.h" @@ -16,22 +16,46 @@ #include #include -static BOOLEAN FmIfsInitialized = FALSE; +#define NDEBUG +#include + +static ULONG FmIfsAttached = 0; LIST_ENTRY ProviderListHead; PIFS_PROVIDER -GetProvider( +LoadProvider( IN PWCHAR FileSystem) { PLIST_ENTRY ListEntry; PIFS_PROVIDER Provider; + DPRINT("LoadProvider(%S)\n", FileSystem); + ListEntry = ProviderListHead.Flink; while (ListEntry != &ProviderListHead) { Provider = CONTAINING_RECORD(ListEntry, IFS_PROVIDER, ListEntry); if (_wcsicmp(Provider->Name, FileSystem) == 0) + { + DPRINT("Found it!\n"); + if (!Provider->hModule) + { + Provider->hModule = LoadLibraryW(Provider->DllFile); + if (!Provider->hModule) + { + DPRINT("Dll Loading failed!\n"); + return NULL; + } + + /* Get function pointers */ + Provider->Chkdsk = (PULIB_CHKDSK)GetProcAddress(Provider->hModule, "Chkdsk"); + //Provider->ChkdskEx = (PULIB_CHKDSKEX)GetProcAddress(Provider->hModule, "ChkdskEx"); + //Provider->Extend = (PULIB_EXTEND)GetProcAddress(Provider->hModule, "Extend"); + Provider->Format = (PULIB_FORMAT)GetProcAddress(Provider->hModule, "Format"); + //Provider->FormatEx = (PULIB_FORMATEX)GetProcAddress(Provider->hModule, "FormatEx"); + } return Provider; + } ListEntry = ListEntry->Flink; } @@ -39,6 +63,26 @@ GetProvider( return NULL; } +BOOLEAN +UnloadProvider( + PIFS_PROVIDER Provider) +{ + DPRINT("UnloadProvider(%S)\n", Provider->Name); + + if (Provider->hModule) + { + FreeLibrary(Provider->hModule); + Provider->hModule = NULL; + + Provider->Chkdsk = NULL; + Provider->ChkdskEx = NULL; + Provider->Extend = NULL; + Provider->Format = NULL; + Provider->FormatEx = NULL; + } + + return TRUE; +} static BOOLEAN @@ -47,43 +91,73 @@ AddProvider( IN PWCHAR DllFile) { PIFS_PROVIDER Provider = NULL; - ULONG RequiredSize; + ULONG ProcCount = 0; HMODULE hMod = NULL; BOOLEAN ret = FALSE; + DPRINT("AddProvider(%wZ %S)\n", FileSystem, DllFile); + hMod = LoadLibraryW(DllFile); if (!hMod) goto cleanup; - RequiredSize = FIELD_OFFSET(IFS_PROVIDER, Name) - + FileSystem->Length + sizeof(UNICODE_NULL); + if (GetProcAddress(hMod, "Chkdsk")) + ProcCount++; + if (GetProcAddress(hMod, "ChkdskEx")) + ProcCount++; + if (GetProcAddress(hMod, "Extend")) + ProcCount++; + if (GetProcAddress(hMod, "Format")) + ProcCount++; + if (GetProcAddress(hMod, "FormatEx")) + ProcCount++; + + DPRINT("ProcCount %lu\n", ProcCount); + if (ProcCount == 0) + goto cleanup; + Provider = (PIFS_PROVIDER)RtlAllocateHeap( RtlGetProcessHeap(), - 0, - RequiredSize); + HEAP_ZERO_MEMORY, + sizeof(IFS_PROVIDER)); if (!Provider) goto cleanup; - RtlZeroMemory(Provider, RequiredSize); - /* Get function pointers */ - Provider->Chkdsk = (PULIB_CHKDSK)GetProcAddress(hMod, "Chkdsk"); - //Provider->ChkdskEx = (PULIB_CHKDSKEX)GetProcAddress(hMod, "ChkdskEx"); - //Provider->Extend = (PULIB_EXTEND)GetProcAddress(hMod, "Extend"); - Provider->Format = (PULIB_FORMAT)GetProcAddress(hMod, "Format"); - //Provider->FormatEx = (PULIB_FORMATEX)GetProcAddress(hMod, "FormatEx"); + Provider->Name = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + FileSystem->Length + sizeof(UNICODE_NULL)); + if (!Provider->Name) + goto cleanup; RtlCopyMemory(Provider->Name, FileSystem->Buffer, FileSystem->Length); + Provider->DllFile = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + (wcslen(DllFile) + 1) * sizeof(WCHAR)); + if (!Provider->DllFile) + goto cleanup; + + wcscpy(Provider->DllFile, DllFile); + InsertTailList(&ProviderListHead, &Provider->ListEntry); ret = TRUE; + DPRINT("AddProvider success\n"); + cleanup: + if (hMod) + FreeLibrary(hMod); + if (!ret) { - if (hMod) - FreeLibrary(hMod); if (Provider) + { + if (Provider->Name) + RtlFreeHeap(RtlGetProcessHeap(), 0, Provider->Name); + if (Provider->DllFile) + RtlFreeHeap(RtlGetProcessHeap(), 0, Provider->DllFile); RtlFreeHeap(RtlGetProcessHeap(), 0, Provider); + } } return ret; } @@ -155,6 +229,27 @@ InitializeFmIfsOnce(VOID) return TRUE; } +static +VOID +UninitializeFmIfsOnce(VOID) +{ + PLIST_ENTRY ListEntry; + PIFS_PROVIDER Provider; + + while (!IsListEmpty(&ProviderListHead)) + { + ListEntry = RemoveTailList(&ProviderListHead); + Provider = CONTAINING_RECORD(ListEntry, IFS_PROVIDER, ListEntry); + if (Provider->Name) + RtlFreeHeap(RtlGetProcessHeap(), 0, Provider->Name); + if (Provider->DllFile) + RtlFreeHeap(RtlGetProcessHeap(), 0, Provider->DllFile); + if (Provider->hModule) + FreeLibrary(Provider->hModule); + RtlFreeHeap(RtlGetProcessHeap(), 0, Provider); + } +} + /* FMIFS.8 */ BOOLEAN NTAPI @@ -166,12 +261,12 @@ InitializeFmIfs( switch (dwReason) { case DLL_PROCESS_ATTACH: - if (FmIfsInitialized == FALSE) + if (FmIfsAttached == 0) { if (InitializeFmIfsOnce() == FALSE) return FALSE; - FmIfsInitialized = TRUE; + FmIfsAttached++; } break; @@ -182,6 +277,9 @@ InitializeFmIfs( break; case DLL_PROCESS_DETACH: + FmIfsAttached--; + if (FmIfsAttached == 0) + UninitializeFmIfsOnce(); break; } diff --git a/dll/win32/fmifs/precomp.h b/dll/win32/fmifs/precomp.h index 1a31415b696..78f8f99299c 100644 --- a/dll/win32/fmifs/precomp.h +++ b/dll/win32/fmifs/precomp.h @@ -5,7 +5,7 @@ * PURPOSE: Win32 FMIFS API Library Header * * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - * Hervé Poussineau (hpoussin@reactos.org) + * Herv� Poussineau (hpoussin@reactos.org) */ #ifndef _FMIFS_PCH_ @@ -33,18 +33,25 @@ typedef struct _IFS_PROVIDER { LIST_ENTRY ListEntry; + PWSTR Name; + PWSTR DllFile; + + HMODULE hModule; PULIB_CHKDSK Chkdsk; PVOID ChkdskEx; PVOID Extend; PULIB_FORMAT Format; PVOID FormatEx; - WCHAR Name[1]; } IFS_PROVIDER, *PIFS_PROVIDER; /* init.c */ PIFS_PROVIDER -GetProvider( - IN PWCHAR FileSytem); +LoadProvider( + _In_ PWCHAR FileSytem); + +BOOLEAN +UnloadProvider( + _In_ PIFS_PROVIDER Provider); #endif /* _FMIFS_PCH_ */