ReactOS 0.4.16-dev-1946-g52006dd
library.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS WdfLdr driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: WdfLdr driver - library functions
5 * COPYRIGHT: Copyright 2019 Max Korostil <mrmks04@yandex.ru>
6 * Copyright 2021 Victor Perevertkin <victor.perevertkin@reactos.org>
7 * Copyright 2024 Justin Miller <justin.miller@reactos.org>
8 */
9
10#include "wdfloader.h"
11
12VOID
15{
17
18 if (!LibModule)
19 {
20 DPRINT_ERROR(("LibModule is NULL\n"));
21 return;
22 }
23
25 {
28 }
29
31 {
34 }
35
39
41}
42
54 _In_opt_ PWDF_LIBRARY_INFO LibraryInfo,
57{
60
63 {
64 DPRINT_ERROR(("Invalid parameters: ServicePath=%p, OutLibraryModule=%p\n",
67 }
68
70
73 {
74 DPRINT_ERROR(("Failed to allocate library module structure\n"));
76 }
77
79 LibModule->ImplicitlyLoaded = (LibraryInfo == NULL);
82
85
88 {
89 DPRINT_ERROR(("ExInitializeResourceLite failed with status 0x%x\n", status));
90 goto Failure;
91 }
92
94
95 /* Only set library information if provided */
96 if (LibraryInfo)
97 {
98 LibModule->LibraryInfo = LibraryInfo;
99 LibModule->Version = LibraryInfo->Version;
100 DPRINT_VERBOSE(("Library info provided: Version %d.%d.%d\n",
101 LibraryInfo->Version.Major,
102 LibraryInfo->Version.Minor,
103 LibraryInfo->Version.Build));
104 }
105
108 WDFLDR_TAG);
110 {
111 DPRINT_ERROR(("Failed to allocate service path buffer\n"));
113 goto Failure;
114 }
115
119
121 if (!NT_SUCCESS(status))
122 {
123 DPRINT_ERROR(("Failed to get image name from service path\n"));
124 goto Failure;
125 }
126
131 {
132 // Insert into loaded modules list. The LoadedModulesListLock is held here
134
136
137 DPRINT_VERBOSE(("Successfully created library module %wZ (Image: %wZ, Base: %p, Size: 0x%x)\n",
142
144 return STATUS_SUCCESS;
145 }
146
147 DPRINT_ERROR(("GetImageInfo failed with status 0x%x\n", status));
148
149Failure:
150 if (LibModule)
151 {
153 }
154
156 return status;
157}
158
170{
172
173 if (ObjectName == NULL)
174 {
175 return STATUS_SUCCESS;
176 }
177
181 &deviceObject);
182
183 if (NT_SUCCESS(status))
184 {
186 }
187
188 return status;
189}
190
194VOID
197{
199 {
202 }
203}
204
209{
210 BOOLEAN loadNeeded = FALSE;
212
215
216 if (pLibModule == NULL)
217 {
218 // Client driver is loaded before the library, we need to create it here
219 status = LibraryCreate(NULL, ServicePath, &pLibModule);
220 if (NT_SUCCESS(status))
221 {
222 loadNeeded = TRUE;
223 }
224 }
225 else
226 {
228 }
229
230 // Reference the library
231 if (pLibModule)
233
235
236 // We've just created a library, time to load the actual driver
237 if (loadNeeded)
238 {
239 // This will call WdfRegisterLibrary (as part of KMDF's DriverEntry)
240 status = ZwLoadDriver((PUNICODE_STRING)ServicePath);
241 if (NT_SUCCESS(status) && !pLibModule->LibraryInfo)
242 {
243 __DBGPRINT(("ZwLoadDriver(%wZ) succeeded but Libray information was returned\n",
244 ServicePath));
246 }
247 else if (!NT_SUCCESS(status))
248 {
249 __DBGPRINT(("ZwLoadDriver(%wZ) failed with status %x\n", ServicePath, status));
250 }
251
252 if (!NT_SUCCESS(status))
253 {
254 LibraryDereference(pLibModule);
255 // Cleanup created library
256 ASSERT(pLibModule->LibraryInfo == NULL);
257 LibraryDereference(pLibModule);
258 pLibModule = NULL;
259 }
260 }
261
262 *LibModule = pLibModule;
263 return status;
264}
265
266VOID
269{
273}
274
278VOID
279NTAPI
282{
283 LONG refCount;
285
287 DPRINT_VERBOSE(("Released reference to library %wZ, RefCount=%d\n",
288 &LibModule->ServicePath, refCount));
289
290 if (refCount <= 0)
291 {
292 DPRINT(("Library %wZ reference count reached zero, unloading\n", &LibModule->ServicePath));
294 }
295
297}
298
299VOID
302{
303 BOOLEAN cleanupNeeded = FALSE;
304
307 {
309 {
311 InitializeListHead(&LibModule->LibraryListEntry); // Indicate removal process
312 cleanupNeeded = TRUE;
313 }
314 }
316
317 if (cleanupNeeded)
318 {
321 else
324 }
325}
326
327VOID
330{
332
333 /* This occurs because of how WDF ClassDrivers behave. */
335 return;
336
338
340 if (!NT_SUCCESS(status))
341 {
342 __DBGPRINT(("LibraryDecommission failed %X\n", status));
343 }
344
346
347 __DBGPRINT(("Unloading library %wZ\n", &LibModule->ServicePath));
348
350
352 if (!NT_SUCCESS(status))
353 {
354 __DBGPRINT(("unload of %wZ returned 0x%x (this may not be a true error if someone else attempted to stop"
355 " the service first)\n",
357 status));
358 }
359
360 // Free the library module directly - caller handles the cleanup sequence
362}
363
367{
370}
371
372VOID
375{
378}
379
380static
381VOID
383 _In_ PCLIENT_MODULE ClientModule)
384{
385 if (ClientModule->ImageName.Buffer)
386 {
387 RtlFreeUnicodeString(&ClientModule->ImageName);
388 }
389
390 ExFreePoolWithTag(ClientModule, WDFLDR_TAG);
391}
392
409 _Out_ PCLIENT_MODULE* OutClientModule)
410{
411 PCLIENT_MODULE clientModule;
413
414 clientModule = ExAllocatePoolWithTag(NonPagedPool, sizeof(*clientModule), WDFLDR_TAG);
415
416 if (clientModule == NULL)
417 {
418 __DBGPRINT(("ERROR: ExAllocatePoolWithTag failed\n"));
419 __DBGPRINT(("ERROR: Client module NOT linked\n"));
420
422 }
423
424 *clientModule = (CLIENT_MODULE){
425 .Context = Context,
426 .Info = BindInfo
427 };
428
429 InitializeListHead(&clientModule->ClassListHead);
430 InitializeListHead(&clientModule->LibListEntry);
431
432 status = GetImageName(ServicePath, &clientModule->ImageName);
433 if (NT_SUCCESS(status))
434 {
435 __DBGPRINT(("Client Image Name: %wZ\n", &clientModule->ImageName));
436
437 status = GetImageInfo(&clientModule->ImageName,
438 &clientModule->ImageAddr,
439 &clientModule->ImageSize);
440 if (!NT_SUCCESS(status))
441 {
442 __DBGPRINT(("GetImageInfo failed with status 0x%x\n", status));
443 __DBGPRINT(("ERROR: Client module NOT linked\n"));
444 ClientFree(clientModule);
445
446 return status;
447 }
448 }
449
454
455 *OutClientModule = clientModule;
456 return STATUS_SUCCESS;
457}
458
459static
460VOID
463{
465
466 __DBGPRINT(("Dereference module %wZ, %d references left\n", &LibModule->ServicePath, refs));
467
468 if (refs <= 0)
469 {
471 }
472}
473
478{
480
481 // search in library clients entry to remove
482 BOOLEAN found = FALSE;
483 PCLIENT_MODULE clientModule;
486 entry = entry->Flink)
487 {
488 clientModule = CONTAINING_RECORD(entry, CLIENT_MODULE, LibListEntry);
489 if (clientModule->Info == BindInfo)
490 {
491 found = TRUE;
492 break;
493 }
494 }
495
496 if (found)
497 {
498 RemoveEntryList(&clientModule->LibListEntry);
500 }
501
503
504 if (found)
505 {
506 InitializeListHead(&clientModule->LibListEntry);
507 ClientFree(clientModule);
508 return TRUE;
509 }
510
511 __DBGPRINT(("ERROR: Client module %p, bind %p NOT found\n", LibModule, BindInfo));
512 return FALSE;
513}
514
519{
521 UNICODE_STRING needleName;
522
523 GetNameFromPath(ServicePath, &needleName);
524
527 entry = entry->Flink)
528 {
529 UNICODE_STRING haystackName;
530 PLIBRARY_MODULE currentLib = CONTAINING_RECORD(entry, LIBRARY_MODULE, LibraryListEntry);
531 GetNameFromPath(&currentLib->ServicePath, &haystackName);
532
533 if (RtlEqualUnicodeString(&needleName, &haystackName, TRUE))
534 {
535 foundModule = currentLib;
536 break;
537 }
538 }
539
540 return foundModule;
541}
542
545NTAPI
549{
553
555
557 {
559 }
560
561 *Library = NULL;
562
564 if (!NT_SUCCESS(status))
565 {
567 {
568 DbgPrint("WdfLdr: FindModuleByClientService - ");
569 DbgPrint("WdfLdr: FindModuleByClientService: GetImageName for %wZ failed with status 0x%x\n", RegistryPath, status);
570 }
571 goto Exit;
572 }
573
574 /* Search through loaded modules by comparing image names only */
577 entry = entry->Flink)
578 {
579 PLIBRARY_MODULE currentLib = CONTAINING_RECORD(entry, LIBRARY_MODULE, LibraryListEntry);
580
581 if (RtlEqualUnicodeString(&imageName, &currentLib->ImageName, TRUE))
582 {
583 foundModule = currentLib;
584 break;
585 }
586 }
587
590
592 if (imageName.Buffer)
593 {
595 }
596
598 return status;
599}
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define _Requires_lock_held_(lock)
#define _Requires_exclusive_lock_held_(lock)
#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 RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
MxDeviceObject deviceObject
VOID GetNameFromPath(_In_ PCUNICODE_STRING Path, _Out_ PUNICODE_STRING Name)
Definition: fxtelemetry.cpp:54
_Must_inspect_result_ NTSTATUS GetImageName(_In_ PFX_DRIVER_GLOBALS DriverGlobals, _Out_ PUNICODE_STRING ImageName)
#define DbgPrint
Definition: hal.h:12
#define KeGetCurrentThread
Definition: hal.h:55
uint32_t entry
Definition: isohybrid.c:63
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
static VOID LibraryClientDereference(_In_ PLIBRARY_MODULE LibModule)
Definition: library.c:461
NTSTATUS LibraryOpen(_Inout_ PLIBRARY_MODULE LibModule, _In_ PCUNICODE_STRING ObjectName)
Opens KMDF library's driver object by its name and fills some library structure data.
Definition: library.c:167
NTSTATUS LibraryFindOrLoad(_In_ PCUNICODE_STRING ServicePath, _Out_ PLIBRARY_MODULE *LibModule)
Definition: library.c:206
VOID LibraryDereference(_In_ PLIBRARY_MODULE LibModule)
Definition: library.c:300
VOID LibraryReleaseClientLock(_In_ PLIBRARY_MODULE LibModule)
Definition: library.c:373
UNICODE_STRING imageName
Definition: library.c:551
DPRINT_TRACE_ENTRY()
PLIBRARY_MODULE LibModule
Definition: library.c:59
PLIBRARY_MODULE foundModule
Definition: library.c:552
_In_ PCUNICODE_STRING ServicePath
Definition: library.c:55
status
Definition: library.c:86
VOID LibraryClose(_Inout_ PLIBRARY_MODULE LibModule)
Dereferences KMDF library's device object.
Definition: library.c:195
VOID NTAPI LibraryReleaseReference(_In_ PLIBRARY_MODULE LibModule)
Release a reference to a library module.
Definition: library.c:280
DPRINT_TRACE_EXIT()
BOOLEAN LibraryUnlinkClient(_In_ PLIBRARY_MODULE LibModule, _In_ PWDF_BIND_INFO BindInfo)
Definition: library.c:475
static VOID ClientFree(_In_ PCLIENT_MODULE ClientModule)
Definition: library.c:382
VOID LibraryReference(_In_ PLIBRARY_MODULE LibModule)
Definition: library.c:267
VOID LibraryFree(_In_ PLIBRARY_MODULE LibModule)
Definition: library.c:13
NTSTATUS LibraryLinkInClient(_In_ PLIBRARY_MODULE LibModule, _In_ PUNICODE_STRING ServicePath, _In_ PWDF_BIND_INFO BindInfo, _In_ PVOID Context, _Out_ PCLIENT_MODULE *OutClientModule)
Create client module and add it to library client list.
Definition: library.c:404
_In_ PCUNICODE_STRING _Out_ PLIBRARY_MODULE * OutLibraryModule
Definition: library.c:57
BOOLEAN LibraryAcquireClientLock(_In_ PLIBRARY_MODULE LibModule)
Definition: library.c:365
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
NTSYSAPI NTSTATUS NTAPI ZwUnloadDriver(_In_ PUNICODE_STRING DriverServiceName)
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define FILE_READ_DATA
Definition: nt_native.h:628
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
@ SynchronizationEvent
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
#define STATUS_NOT_SAFE_MODE_DRIVER
Definition: ntstatus.h:1034
long LONG
Definition: pedump.c:60
VOID FxLdrAcquireLoadedModuleLock(VOID)
Definition: common.c:13
VOID FxLdrReleaseLoadedModuleLock(VOID)
Definition: common.c:20
NTSTATUS GetImageInfo(_In_ PCUNICODE_STRING ImageName, _Out_ PVOID *ImageBase, _Out_ PULONG ImageSize)
Definition: common.c:182
BOOLEAN ServiceCheckBootStart(_In_ PUNICODE_STRING Service)
Definition: registry.c:194
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define DPRINT
Definition: sndvol32.h:73
static void Exit(void)
Definition: sock.c:1330
PVOID ImageAddr
Definition: wdfloader.h:160
LIST_ENTRY LibListEntry
Definition: wdfloader.h:157
UNICODE_STRING ImageName
Definition: wdfloader.h:162
PWDF_BIND_INFO Info
Definition: wdfloader.h:163
ULONG ImageSize
Definition: wdfloader.h:161
LIST_ENTRY ClassListHead
Definition: wdfloader.h:164
PVOID ImageAddress
Definition: wdfloader.h:115
PKTHREAD LoaderThread
Definition: wdfloader.h:124
PDRIVER_OBJECT LibraryDriverObject
Definition: wdfloader.h:118
LONG ClientRefCount
Definition: wdfloader.h:110
UNICODE_STRING ServicePath
Definition: wdfloader.h:113
KEVENT LoaderEvent
Definition: wdfloader.h:123
LONG LibraryRefCount
Definition: wdfloader.h:108
BOOLEAN IsBootDriver
Definition: wdfloader.h:111
ERESOURCE ClientsListLock
Definition: wdfloader.h:121
PFILE_OBJECT LibraryFileObject
Definition: wdfloader.h:117
LIST_ENTRY LibraryListEntry
Definition: wdfloader.h:109
LIST_ENTRY ClassListHead
Definition: wdfloader.h:125
PWDF_LIBRARY_INFO LibraryInfo
Definition: wdfloader.h:119
BOOLEAN ImplicitlyLoaded
Definition: wdfloader.h:112
LIST_ENTRY ClientsListHead
Definition: wdfloader.h:120
UNICODE_STRING ImageName
Definition: wdfloader.h:114
WDF_VERSION Version
Definition: wdfloader.h:122
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
UINT32 DiagFlags
Definition: wdfloader.h:91
ERESOURCE LoadedModulesListLock
Definition: wdfloader.h:72
LIST_ENTRY LoadedModulesList
Definition: wdfloader.h:73
PFNLIBRARYDECOMMISSION LibraryDecommission
Definition: fxldr.h:142
Definition: ps.c:97
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID LibraryUnload()
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
WDF_BIND_INFO BindInfo
WDFLDR_DIAGS WdfLdrDiags
Definition: wdfldr.c:27
WDF_LDR_GLOBALS WdfLdrGlobals
Definition: wdfldr.c:28
struct _CLIENT_MODULE CLIENT_MODULE
#define DIAGFLAG_ENABLED
Definition: wdfloader.h:79
NTSTATUS LibraryCreate(_In_opt_ PWDF_LIBRARY_INFO LibraryInfo, _In_ PCUNICODE_STRING ServicePath, _Out_ PLIBRARY_MODULE *OutLibraryModule)
PLIBRARY_MODULE FindLibraryByServicePathLocked(_In_ PCUNICODE_STRING ServicePath)
#define WDFLDR_TAG
Definition: wdfloader.h:17
#define DPRINT_ERROR(_x_)
Definition: wdfloader.h:39
#define __DBGPRINT(_x_)
Definition: wdfloader.h:62
NTSTATUS NTAPI FindModuleByClientService(_In_ PUNICODE_STRING RegistryPath, _Out_ PLIBRARY_MODULE *Library)
#define DPRINT_VERBOSE(_x_)
Definition: wdfloader.h:31
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
#define ObDereferenceObject
Definition: obfuncs.h:203