[FMIFS] Do not keep all file system providers loaded

- Load the required provider only!
- Unload providers on last process detach
This commit is contained in:
Eric Kohl
2026-07-19 22:42:15 +02:00
parent 708d289dbf
commit 8d70dca549
4 changed files with 136 additions and 25 deletions
+4 -1
View File
@@ -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);
}
+4 -1
View File
@@ -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);
}
+117 -19
View File
@@ -5,7 +5,7 @@
* PURPOSE: Initialisation
*
* PROGRAMMERS: Emanuele Aliberti
* Hervé Poussineau ([email protected])
* Hervé Poussineau ([email protected])
*/
#include "precomp.h"
@@ -16,22 +16,46 @@
#include <ndk/cmfuncs.h>
#include <ndk/obfuncs.h>
static BOOLEAN FmIfsInitialized = FALSE;
#define NDEBUG
#include <debug.h>
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;
}
+11 -4
View File
@@ -5,7 +5,7 @@
* PURPOSE: Win32 FMIFS API Library Header
*
* PROGRAMMERS: Alex Ionescu ([email protected])
* Hervé Poussineau ([email protected])
* Herv Poussineau ([email protected])
*/
#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_ */