1 /* $Id: driver.c,v 1.40 2004/03/28 09:48:13 navaraf Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/driver.c
6 * PURPOSE: Loading and unloading of drivers
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * Filip Navara (xnavara@volny.cz)
13 /* INCLUDES *******************************************************************/
16 #include <ddk/ntddk.h>
17 #include <internal/io.h>
18 #include <internal/po.h>
19 #include <internal/ldr.h>
20 #include <internal/id.h>
21 #include <internal/pool.h>
22 #include <internal/se.h>
23 #include <internal/mm.h>
24 #include <internal/ke.h>
25 #include <internal/kd.h>
26 #include <rosrtl/string.h>
31 #include <internal/debug.h>
34 extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
37 LdrProcessModule(PVOID ModuleLoadBase
,
38 PUNICODE_STRING ModuleName
,
39 PMODULE_OBJECT
*ModuleObject
);
41 typedef struct _SERVICE_GROUP
43 LIST_ENTRY GroupListEntry
;
44 UNICODE_STRING GroupName
;
45 BOOLEAN ServicesRunning
;
46 } SERVICE_GROUP
, *PSERVICE_GROUP
;
48 typedef struct _SERVICE
50 LIST_ENTRY ServiceListEntry
;
51 UNICODE_STRING ServiceName
;
52 UNICODE_STRING RegistryPath
;
53 UNICODE_STRING ServiceGroup
;
54 UNICODE_STRING ImagePath
;
61 /* BOOLEAN ServiceRunning;*/ // needed ??
64 typedef struct _DRIVER_REINIT_ITEM
67 PDRIVER_OBJECT DriverObject
;
68 PDRIVER_REINITIALIZE ReinitRoutine
;
70 } DRIVER_REINIT_ITEM
, *PDRIVER_REINIT_ITEM
;
72 /* GLOBALS ********************************************************************/
74 static LIST_ENTRY DriverReinitListHead
;
75 static PLIST_ENTRY DriverReinitTailEntry
;
76 static KSPIN_LOCK DriverReinitListLock
;
78 static LIST_ENTRY GroupListHead
= {NULL
, NULL
};
79 static LIST_ENTRY ServiceListHead
= {NULL
, NULL
};
81 POBJECT_TYPE EXPORTED IoDriverObjectType
= NULL
;
83 #define TAG_DRIVER TAG('D', 'R', 'V', 'R')
84 #define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
86 #define DRIVER_REGISTRY_KEY_BASENAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
88 /* DECLARATIONS ***************************************************************/
95 POBJECT_ATTRIBUTES ObjectAttributes
);
98 IopDeleteDriver(PVOID ObjectBody
);
100 /* PRIVATE FUNCTIONS **********************************************************/
103 IopInitDriverImplementation(VOID
)
105 /* Register the process object type */
106 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
107 IoDriverObjectType
->Tag
= TAG('D', 'R', 'V', 'R');
108 IoDriverObjectType
->TotalObjects
= 0;
109 IoDriverObjectType
->TotalHandles
= 0;
110 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
111 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
112 IoDriverObjectType
->PagedPoolCharge
= 0;
113 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(DRIVER_OBJECT
);
114 IoDriverObjectType
->Dump
= NULL
;
115 IoDriverObjectType
->Open
= NULL
;
116 IoDriverObjectType
->Close
= NULL
;
117 IoDriverObjectType
->Delete
= IopDeleteDriver
;
118 IoDriverObjectType
->Parse
= NULL
;
119 IoDriverObjectType
->Security
= NULL
;
120 IoDriverObjectType
->QueryName
= NULL
;
121 IoDriverObjectType
->OkayToClose
= NULL
;
122 IoDriverObjectType
->Create
= IopCreateDriver
;
123 IoDriverObjectType
->DuplicationNotify
= NULL
;
124 RtlRosInitUnicodeStringFromLiteral(&IoDriverObjectType
->TypeName
, L
"Driver");
126 ObpCreateTypeObject(IoDriverObjectType
);
128 InitializeListHead(&DriverReinitListHead
);
129 KeInitializeSpinLock(&DriverReinitListLock
);
130 DriverReinitTailEntry
= NULL
;
134 IopInvalidDeviceRequest(
135 PDEVICE_OBJECT DeviceObject
,
138 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
139 Irp
->IoStatus
.Information
= 0;
140 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
141 return STATUS_NOT_IMPLEMENTED
;
149 POBJECT_ATTRIBUTES ObjectAttributes
)
151 PDRIVER_OBJECT Object
= ObjectBody
;
154 DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
155 ObjectBody
, Parent
, RemainingPath
);
157 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
158 return STATUS_UNSUCCESSFUL
;
160 /* Create driver extension */
161 Object
->DriverExtension
= (PDRIVER_EXTENSION
)
162 ExAllocatePoolWithTag(
164 sizeof(DRIVER_EXTENSION
),
165 TAG_DRIVER_EXTENSION
);
167 if (Object
->DriverExtension
== NULL
)
169 return STATUS_NO_MEMORY
;
172 RtlZeroMemory(Object
->DriverExtension
, sizeof(DRIVER_EXTENSION
));
174 Object
->Type
= InternalDriverType
;
176 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
177 Object
->MajorFunction
[i
] = IopInvalidDeviceRequest
;
179 return STATUS_SUCCESS
;
183 IopDeleteDriver(PVOID ObjectBody
)
185 PDRIVER_OBJECT Object
= ObjectBody
;
187 PPRIVATE_DRIVER_EXTENSIONS DriverExtension
, NextDriverExtension
;
189 DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody
);
191 ExFreePool(Object
->DriverExtension
);
193 OldIrql
= KeRaiseIrqlToDpcLevel();
195 for (DriverExtension
= Object
->DriverSection
;
196 DriverExtension
!= NULL
;
197 DriverExtension
= NextDriverExtension
)
199 NextDriverExtension
= DriverExtension
->Link
;
200 ExFreePool(DriverExtension
);
203 KfLowerIrql(OldIrql
);
207 IopCreateDriverObject(
208 PDRIVER_OBJECT
*DriverObject
,
209 PUNICODE_STRING ServiceName
,
211 PVOID DriverImageStart
,
212 ULONG DriverImageSize
)
214 PDRIVER_OBJECT Object
;
215 WCHAR NameBuffer
[MAX_PATH
];
216 UNICODE_STRING DriverName
;
217 OBJECT_ATTRIBUTES ObjectAttributes
;
220 DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n",
221 DriverObject
, ServiceName
, FileSystem
, DriverImageStart
, DriverImageSize
);
223 *DriverObject
= NULL
;
225 /* Create ModuleName string */
226 if (ServiceName
!= NULL
&& ServiceName
->Buffer
!= NULL
)
228 if (FileSystem
== TRUE
)
229 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
231 wcscpy(NameBuffer
, DRIVER_ROOT_NAME
);
232 wcscat(NameBuffer
, ServiceName
->Buffer
);
234 RtlInitUnicodeString(&DriverName
, NameBuffer
);
235 DPRINT("Driver name: '%wZ'\n", &DriverName
);
239 RtlInitUnicodeString(&DriverName
, NULL
);
242 /* Initialize ObjectAttributes for driver object */
243 InitializeObjectAttributes(
250 /* Create driver object */
251 Status
= ObCreateObject(
257 sizeof(DRIVER_OBJECT
),
262 if (!NT_SUCCESS(Status
))
267 Object
->DriverStart
= DriverImageStart
;
268 Object
->DriverSize
= DriverImageSize
;
270 *DriverObject
= Object
;
272 return STATUS_SUCCESS
;
276 * IopDisplayLoadingMessage
278 * Display 'Loading XXX...' message.
282 IopDisplayLoadingMessage(PWCHAR ServiceName
)
284 CHAR TextBuffer
[256];
285 sprintf(TextBuffer
, "Loading %S...\n", ServiceName
);
286 HalDisplayString(TextBuffer
);
290 * IopNormalizeImagePath
292 * Normalize an image path to contain complete path.
296 * The input path and on exit the result path. ImagePath.Buffer
297 * must be allocated by ExAllocatePool on input. Caller is responsible
298 * for freeing the buffer when it's no longer needed.
301 * Name of the service that ImagePath belongs to.
307 * The input image path isn't freed on error.
311 IopNormalizeImagePath(
312 IN OUT PUNICODE_STRING ImagePath
,
313 IN PUNICODE_STRING ServiceName
)
315 UNICODE_STRING InputImagePath
;
320 sizeof(UNICODE_STRING
));
322 if (InputImagePath
.Length
== 0)
324 ImagePath
->Length
= (33 * sizeof(WCHAR
)) + ServiceName
->Length
;
325 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
326 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
327 if (ImagePath
->Buffer
== NULL
)
328 return STATUS_NO_MEMORY
;
330 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\system32\\drivers\\");
331 wcscat(ImagePath
->Buffer
, ServiceName
->Buffer
);
332 wcscat(ImagePath
->Buffer
, L
".sys");
334 if (InputImagePath
.Buffer
[0] != L
'\\')
336 ImagePath
->Length
= (12 * sizeof(WCHAR
)) + InputImagePath
.Length
;
337 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
338 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
339 if (ImagePath
->Buffer
== NULL
)
340 return STATUS_NO_MEMORY
;
342 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\");
343 wcscat(ImagePath
->Buffer
, InputImagePath
.Buffer
);
344 RtlFreeUnicodeString(&InputImagePath
);
347 return STATUS_SUCCESS
;
351 * IopLoadServiceModule
353 * Load a module specified by registry settings for service.
357 * Name of the service to load.
364 IopLoadServiceModule(
365 IN PUNICODE_STRING ServiceName
,
366 OUT PMODULE_OBJECT
*ModuleObject
)
368 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
370 UNICODE_STRING ServiceImagePath
;
374 * Get information about the service.
377 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
379 RtlInitUnicodeString(&ServiceImagePath
, NULL
);
381 QueryTable
[0].Name
= L
"Start";
382 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
383 QueryTable
[0].EntryContext
= &ServiceStart
;
385 QueryTable
[1].Name
= L
"ImagePath";
386 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
387 QueryTable
[1].EntryContext
= &ServiceImagePath
;
389 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
390 ServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
392 if (!NT_SUCCESS(Status
))
394 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
398 IopDisplayLoadingMessage(ServiceName
->Buffer
);
401 * Normalize the image path for all later processing.
404 Status
= IopNormalizeImagePath(&ServiceImagePath
, ServiceName
);
406 if (!NT_SUCCESS(Status
))
408 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
416 *ModuleObject
= LdrGetModuleObject(&ServiceImagePath
);
418 if (*ModuleObject
== NULL
)
421 * Special case for boot modules that were loaded by boot loader.
424 if (ServiceStart
== 0)
427 CHAR SearchName
[256];
429 PLOADER_MODULE KeLoaderModules
=
430 (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
432 Status
= STATUS_UNSUCCESSFUL
;
436 * Improve this searching algorithm by using the image name
437 * stored in registry entry ImageName and use the whole path
438 * (requires change in FreeLoader).
441 _snprintf(SearchName
, sizeof(SearchName
), "%wZ.sys", ServiceName
);
442 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
444 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
445 if (!strcmp(ModuleName
, SearchName
))
447 /* Tell, that the module is already loaded */
448 KeLoaderModules
[i
].Reserved
= 1;
450 Status
= LdrProcessModule(
451 (PVOID
)KeLoaderModules
[i
].ModStart
,
461 * Case for rest of the drivers (except disabled)
464 else if (ServiceStart
< 4)
466 DPRINT("Loading module\n");
467 Status
= LdrLoadModule(&ServiceImagePath
, ModuleObject
);
472 DPRINT("Module already loaded\n");
473 Status
= STATUS_SUCCESS
;
476 RtlFreeUnicodeString(&ServiceImagePath
);
479 * Now check if the module was loaded successfully.
482 if (!NT_SUCCESS(Status
))
484 DPRINT("Module loading failed (Status %x)\n", Status
);
487 DPRINT("Module loading (Status %x)\n", Status
);
493 * IopInitializeDriverModule
495 * Initalize a loaded driver.
499 * Pointer to device node.
502 * Module object representing the driver. It can be retrieve by
503 * IopLoadServiceModule.
506 * Set to TRUE for file system drivers.
509 * On successful return this contains the driver object representing
514 IopInitializeDriverModule(
515 IN PDEVICE_NODE DeviceNode
,
516 IN PMODULE_OBJECT ModuleObject
,
517 IN BOOLEAN FileSystemDriver
,
518 OUT PDRIVER_OBJECT
*DriverObject
)
520 UNICODE_STRING RegistryKey
;
521 PDRIVER_INITIALIZE DriverEntry
= ModuleObject
->EntryPoint
;
524 Status
= IopCreateDriverObject(
526 &DeviceNode
->ServiceName
,
529 ModuleObject
->Length
);
531 if (!NT_SUCCESS(Status
))
533 DPRINT("IopCreateDriverObject failed (Status %x)\n", Status
);
537 if (DeviceNode
->ServiceName
.Buffer
)
539 RegistryKey
.Length
= DeviceNode
->ServiceName
.Length
+
540 sizeof(DRIVER_REGISTRY_KEY_BASENAME
);
541 RegistryKey
.MaximumLength
= RegistryKey
.Length
+ sizeof(UNICODE_NULL
);
542 RegistryKey
.Buffer
= ExAllocatePool(PagedPool
, RegistryKey
.MaximumLength
);
543 wcscpy(RegistryKey
.Buffer
, DRIVER_REGISTRY_KEY_BASENAME
);
544 wcscat(RegistryKey
.Buffer
, DeviceNode
->ServiceName
.Buffer
);
548 RtlInitUnicodeString(&RegistryKey
, NULL
);
551 DPRINT("RegistryKey: %wZ\n", &RegistryKey
);
552 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry
);
554 IopMarkLastReinitializeDriver();
556 Status
= DriverEntry(*DriverObject
, &RegistryKey
);
557 if (!NT_SUCCESS(Status
))
559 ExFreePool((*DriverObject
)->DriverExtension
);
560 ObMakeTemporaryObject(DriverObject
);
561 ObDereferenceObject(DriverObject
);
565 IopReinitializeDrivers();
567 return STATUS_SUCCESS
;
571 * IopAttachFilterDriversCallback
573 * Internal routine used by IopAttachFilterDrivers.
577 IopAttachFilterDriversCallback(
585 PDEVICE_NODE DeviceNode
= Context
;
586 UNICODE_STRING ServiceName
;
588 PMODULE_OBJECT ModuleObject
;
589 PDRIVER_OBJECT DriverObject
;
592 for (Filters
= ValueData
;
593 ((ULONG_PTR
)Filters
- (ULONG_PTR
)ValueData
) < ValueLength
&&
595 Filters
+= (ServiceName
.Length
/ sizeof(WCHAR
)) + 1)
597 DPRINT("Filter Driver: %S (%wZ)\n", Filters
, &DeviceNode
->InstancePath
);
598 ServiceName
.Buffer
= Filters
;
599 ServiceName
.MaximumLength
=
600 ServiceName
.Length
= wcslen(Filters
) * sizeof(WCHAR
);
602 /* Load and initialize the filter driver */
603 Status
= IopLoadServiceModule(&ServiceName
, &ModuleObject
);
604 if (!NT_SUCCESS(Status
))
607 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
608 if (!NT_SUCCESS(Status
))
611 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
612 if (!NT_SUCCESS(Status
))
616 return STATUS_SUCCESS
;
620 * IopAttachFilterDrivers
622 * Load filter drivers for specified device node.
626 * Set to TRUE for loading lower level filters or FALSE for upper
631 IopAttachFilterDrivers(
632 PDEVICE_NODE DeviceNode
,
635 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
637 UNICODE_STRING Class
;
638 WCHAR ClassBuffer
[40];
642 * First load the device filters
645 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
647 QueryTable
[0].Name
= L
"LowerFilters";
649 QueryTable
[0].Name
= L
"UpperFilters";
650 QueryTable
[0].EntryContext
= NULL
;
651 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
652 QueryTable
[1].QueryRoutine
= NULL
;
653 QueryTable
[1].Name
= NULL
;
655 KeyBuffer
= ExAllocatePool(
657 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
658 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
659 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
661 RtlQueryRegistryValues(
662 RTL_REGISTRY_ABSOLUTE
,
669 * Now get the class GUID
673 Class
.MaximumLength
= 40 * sizeof(WCHAR
);
674 Class
.Buffer
= ClassBuffer
;
675 QueryTable
[0].QueryRoutine
= NULL
;
676 QueryTable
[0].Name
= L
"ClassGUID";
677 QueryTable
[0].EntryContext
= &Class
;
678 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
680 Status
= RtlQueryRegistryValues(
681 RTL_REGISTRY_ABSOLUTE
,
687 ExFreePool(KeyBuffer
);
690 * Load the class filter driver
693 if (NT_SUCCESS(Status
))
695 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
697 QueryTable
[0].Name
= L
"LowerFilters";
699 QueryTable
[0].Name
= L
"UpperFilters";
700 QueryTable
[0].EntryContext
= NULL
;
701 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
703 KeyBuffer
= ExAllocatePool(PagedPool
, (58 * sizeof(WCHAR
)) + Class
.Length
);
704 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
705 wcscat(KeyBuffer
, ClassBuffer
);
707 RtlQueryRegistryValues(
708 RTL_REGISTRY_ABSOLUTE
,
714 ExFreePool(KeyBuffer
);
717 return STATUS_SUCCESS
;
720 static NTSTATUS STDCALL
721 IopCreateGroupListEntry(PWSTR ValueName
,
728 PSERVICE_GROUP Group
;
730 if (ValueType
== REG_SZ
)
732 DPRINT("GroupName: '%S'\n", (PWCHAR
)ValueData
);
734 Group
= ExAllocatePool(NonPagedPool
,
735 sizeof(SERVICE_GROUP
));
738 return(STATUS_INSUFFICIENT_RESOURCES
);
741 RtlZeroMemory(Group
, sizeof(SERVICE_GROUP
));
743 if (!RtlCreateUnicodeString(&Group
->GroupName
,
747 return(STATUS_INSUFFICIENT_RESOURCES
);
751 InsertTailList(&GroupListHead
,
752 &Group
->GroupListEntry
);
755 return(STATUS_SUCCESS
);
759 static NTSTATUS STDCALL
760 IopCreateServiceListEntry(PUNICODE_STRING ServiceName
)
762 RTL_QUERY_REGISTRY_TABLE QueryTable
[6];
766 DPRINT("ServiceName: '%wZ'\n", ServiceName
);
768 /* Allocate service entry */
769 Service
= (PSERVICE
)ExAllocatePool(NonPagedPool
, sizeof(SERVICE
));
772 DPRINT1("ExAllocatePool() failed\n");
773 return(STATUS_INSUFFICIENT_RESOURCES
);
775 RtlZeroMemory(Service
, sizeof(SERVICE
));
777 /* Get service data */
778 RtlZeroMemory(&QueryTable
,
781 QueryTable
[0].Name
= L
"Start";
782 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
783 QueryTable
[0].EntryContext
= &Service
->Start
;
785 QueryTable
[1].Name
= L
"Type";
786 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
787 QueryTable
[1].EntryContext
= &Service
->Type
;
789 QueryTable
[2].Name
= L
"ErrorControl";
790 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
791 QueryTable
[2].EntryContext
= &Service
->ErrorControl
;
793 QueryTable
[3].Name
= L
"Group";
794 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
795 QueryTable
[3].EntryContext
= &Service
->ServiceGroup
;
797 QueryTable
[4].Name
= L
"ImagePath";
798 QueryTable
[4].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
799 QueryTable
[4].EntryContext
= &Service
->ImagePath
;
801 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
806 if (!NT_SUCCESS(Status
) || Service
->Start
> 1)
808 RtlFreeUnicodeString(&Service
->ServiceGroup
);
809 RtlFreeUnicodeString(&Service
->ImagePath
);
814 /* Copy service name */
815 Service
->ServiceName
.Length
= ServiceName
->Length
;
816 Service
->ServiceName
.MaximumLength
= ServiceName
->Length
+ sizeof(WCHAR
);
817 Service
->ServiceName
.Buffer
= ExAllocatePool(NonPagedPool
,
818 Service
->ServiceName
.MaximumLength
);
819 RtlCopyMemory(Service
->ServiceName
.Buffer
,
821 ServiceName
->Length
);
822 Service
->ServiceName
.Buffer
[ServiceName
->Length
/ sizeof(WCHAR
)] = 0;
824 /* Build registry path */
825 Service
->RegistryPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
826 Service
->RegistryPath
.Buffer
= ExAllocatePool(NonPagedPool
,
827 MAX_PATH
* sizeof(WCHAR
));
828 wcscpy(Service
->RegistryPath
.Buffer
,
829 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
830 wcscat(Service
->RegistryPath
.Buffer
,
831 Service
->ServiceName
.Buffer
);
832 Service
->RegistryPath
.Length
= wcslen(Service
->RegistryPath
.Buffer
) * sizeof(WCHAR
);
834 DPRINT("ServiceName: '%wZ'\n", &Service
->ServiceName
);
835 DPRINT("RegistryPath: '%wZ'\n", &Service
->RegistryPath
);
836 DPRINT("ServiceGroup: '%wZ'\n", &Service
->ServiceGroup
);
837 DPRINT("ImagePath: '%wZ'\n", &Service
->ImagePath
);
838 DPRINT("Start %lx Type %lx ErrorControl %lx\n",
839 Service
->Start
, Service
->Type
, Service
->ErrorControl
);
841 /* Append service entry */
842 InsertTailList(&ServiceListHead
,
843 &Service
->ServiceListEntry
);
845 return(STATUS_SUCCESS
);
849 NTSTATUS INIT_FUNCTION
850 IoCreateDriverList(VOID
)
852 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
853 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
854 OBJECT_ATTRIBUTES ObjectAttributes
;
855 UNICODE_STRING ServicesKeyName
;
856 UNICODE_STRING SubKeyName
;
861 ULONG KeyInfoLength
= 0;
862 ULONG ReturnedLength
;
864 DPRINT("IoCreateDriverList() called\n");
866 /* Initialize basic variables */
867 InitializeListHead(&GroupListHead
);
868 InitializeListHead(&ServiceListHead
);
870 /* Build group order list */
871 RtlZeroMemory(&QueryTable
,
874 QueryTable
[0].Name
= L
"List";
875 QueryTable
[0].QueryRoutine
= IopCreateGroupListEntry
;
877 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
878 L
"ServiceGroupOrder",
882 if (!NT_SUCCESS(Status
))
885 /* Enumerate services and create the service list */
886 RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName
,
887 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
889 InitializeObjectAttributes(&ObjectAttributes
,
891 OBJ_CASE_INSENSITIVE
,
895 Status
= NtOpenKey(&KeyHandle
,
898 if (!NT_SUCCESS(Status
))
903 KeyInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
904 KeyInfo
= ExAllocatePool(NonPagedPool
, KeyInfoLength
);
908 return(STATUS_INSUFFICIENT_RESOURCES
);
914 Status
= NtEnumerateKey(KeyHandle
,
920 if (NT_SUCCESS(Status
))
922 if (KeyInfo
->NameLength
< MAX_PATH
* sizeof(WCHAR
))
925 SubKeyName
.Length
= KeyInfo
->NameLength
;
926 SubKeyName
.MaximumLength
= KeyInfo
->NameLength
+ sizeof(WCHAR
);
927 SubKeyName
.Buffer
= KeyInfo
->Name
;
928 SubKeyName
.Buffer
[SubKeyName
.Length
/ sizeof(WCHAR
)] = 0;
930 DPRINT("KeyName: '%wZ'\n", &SubKeyName
);
931 IopCreateServiceListEntry(&SubKeyName
);
935 if (!NT_SUCCESS(Status
))
944 DPRINT("IoCreateDriverList() done\n");
946 return(STATUS_SUCCESS
);
949 NTSTATUS INIT_FUNCTION
950 IoDestroyDriverList(VOID
)
952 PLIST_ENTRY GroupEntry
;
953 PLIST_ENTRY ServiceEntry
;
954 PSERVICE_GROUP CurrentGroup
;
955 PSERVICE CurrentService
;
957 DPRINT("IoDestroyDriverList() called\n");
959 /* Destroy group list */
960 GroupEntry
= GroupListHead
.Flink
;
961 while (GroupEntry
!= &GroupListHead
)
963 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
965 RtlFreeUnicodeString(&CurrentGroup
->GroupName
);
966 RemoveEntryList(GroupEntry
);
967 ExFreePool(CurrentGroup
);
969 GroupEntry
= GroupListHead
.Flink
;
972 /* Destroy service list */
973 ServiceEntry
= ServiceListHead
.Flink
;
974 while (ServiceEntry
!= &ServiceListHead
)
976 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
978 RtlFreeUnicodeString(&CurrentService
->ServiceName
);
979 RtlFreeUnicodeString(&CurrentService
->RegistryPath
);
980 RtlFreeUnicodeString(&CurrentService
->ServiceGroup
);
981 RtlFreeUnicodeString(&CurrentService
->ImagePath
);
982 RemoveEntryList(ServiceEntry
);
983 ExFreePool(CurrentService
);
985 ServiceEntry
= ServiceListHead
.Flink
;
988 DPRINT("IoDestroyDriverList() done\n");
990 return(STATUS_SUCCESS
);
994 MiFreeBootDriverMemory(PVOID StartAddress
, ULONG Length
)
998 for (i
= 0; i
< PAGE_ROUND_UP(Length
) / PAGE_SIZE
; i
++)
1000 MmDeleteVirtualMapping(NULL
, (char*)StartAddress
+ i
* PAGE_SIZE
, TRUE
, NULL
, NULL
);
1005 * IopInitializeBuiltinDriver
1007 * Initialize a driver that is already loaded in memory.
1011 IopInitializeBuiltinDriver(
1012 PDEVICE_NODE ModuleDeviceNode
,
1013 PVOID ModuleLoadBase
,
1017 PMODULE_OBJECT ModuleObject
;
1018 PDEVICE_NODE DeviceNode
;
1019 PDRIVER_OBJECT DriverObject
;
1021 CHAR TextBuffer
[256];
1022 PCHAR FileNameWithoutPath
;
1023 LPWSTR FileExtension
;
1025 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1026 FileName
, ModuleLoadBase
, ModuleLength
);
1029 * Display 'Initializing XXX...' message
1032 sprintf(TextBuffer
, "Initializing %s...\n", FileName
);
1033 HalDisplayString(TextBuffer
);
1036 * Determine the right device object
1039 if (ModuleDeviceNode
== NULL
)
1041 /* Use IopRootDeviceNode for now */
1042 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1043 if (!NT_SUCCESS(Status
))
1045 CPRINT("Driver load failed, status (%x)\n", Status
);
1050 DeviceNode
= ModuleDeviceNode
;
1054 * Generate filename without path (not needed by freeldr)
1057 FileNameWithoutPath
= strrchr(FileName
, '\\');
1058 if (FileNameWithoutPath
== NULL
)
1060 FileNameWithoutPath
= FileName
;
1067 RtlCreateUnicodeStringFromAsciiz(&DeviceNode
->ServiceName
,
1068 FileNameWithoutPath
);
1069 Status
= LdrProcessModule(ModuleLoadBase
, &DeviceNode
->ServiceName
,
1071 if (ModuleObject
== NULL
)
1073 if (ModuleDeviceNode
== NULL
)
1074 IopFreeDeviceNode(DeviceNode
);
1075 CPRINT("Driver load failed, status (%x)\n", Status
);
1076 return STATUS_UNSUCCESSFUL
;
1080 * Strip the file extension from ServiceName
1083 FileExtension
= wcsrchr(DeviceNode
->ServiceName
.Buffer
, '.');
1084 if (FileExtension
!= NULL
)
1086 DeviceNode
->ServiceName
.Length
-= wcslen(DeviceNode
->ServiceName
.Buffer
);
1087 FileExtension
[0] = 0;
1091 * Initialize the driver
1094 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
,
1097 if (!NT_SUCCESS(Status
))
1099 if (ModuleDeviceNode
== NULL
)
1100 IopFreeDeviceNode(DeviceNode
);
1101 CPRINT("Driver load failed, status (%x)\n", Status
);
1105 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1111 * IopInitializeBootDrivers
1113 * Initialize boot drivers and free memory for boot files.
1123 IopInitializeBootDrivers(VOID
)
1125 ULONG BootDriverCount
;
1131 PLOADER_MODULE KeLoaderModules
= (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
1134 DPRINT("IopInitializeBootDrivers()\n");
1136 BootDriverCount
= 0;
1137 for (i
= 2; i
< KeLoaderBlock
.ModsCount
; i
++)
1139 ModuleStart
= KeLoaderModules
[i
].ModStart
;
1140 ModuleSize
= KeLoaderModules
[i
].ModEnd
- ModuleStart
;
1141 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
1142 ModuleLoaded
= KeLoaderModules
[i
].Reserved
;
1143 Extension
= strrchr(ModuleName
, '.');
1144 if (Extension
== NULL
)
1148 * Pass symbol files to kernel debugger
1151 if (!_stricmp(Extension
, ".sym"))
1153 KDB_SYMBOLFILE_HOOK((PVOID
)ModuleStart
, ModuleName
, ModuleSize
);
1157 * Load builtin driver
1160 if (!_stricmp(Extension
, ".sys"))
1164 IopInitializeBuiltinDriver(NULL
, (PVOID
)ModuleStart
, ModuleName
,
1171 * Free memory for all boot files, except ntoskrnl.exe and hal.dll
1176 * Do not free the memory from symbol files, if the kernel debugger
1179 if (_stricmp(Extension
, ".sym"))
1182 MiFreeBootDriverMemory((PVOID
)KeLoaderModules
[i
].ModStart
,
1183 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
1187 if (BootDriverCount
== 0)
1189 DbgPrint("No boot drivers available.\n");
1195 * IopInitializeSystemDrivers
1197 * Load drivers marked as system start.
1207 IopInitializeSystemDrivers(VOID
)
1209 PLIST_ENTRY GroupEntry
;
1210 PLIST_ENTRY ServiceEntry
;
1211 PSERVICE_GROUP CurrentGroup
;
1212 PSERVICE CurrentService
;
1215 DPRINT("IopInitializeSystemDrivers()\n");
1217 GroupEntry
= GroupListHead
.Flink
;
1218 while (GroupEntry
!= &GroupListHead
)
1220 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1222 DPRINT("Group: %wZ\n", &CurrentGroup
->GroupName
);
1224 ServiceEntry
= ServiceListHead
.Flink
;
1225 while (ServiceEntry
!= &ServiceListHead
)
1227 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1229 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1230 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1231 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/))
1233 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1234 IopDisplayLoadingMessage(CurrentService
->ServiceName
.Buffer
);
1235 Status
= NtLoadDriver(&CurrentService
->RegistryPath
);
1236 if (!NT_SUCCESS(Status
))
1238 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status
);
1240 if (CurrentService
->ErrorControl
== 1)
1244 if (CurrentService
->ErrorControl
== 2)
1246 if (IsLastKnownGood
== FALSE
)
1248 /* Boot last known good configuration */
1251 if (CurrentService
->ErrorControl
== 3)
1253 if (IsLastKnownGood
== FALSE
)
1255 /* Boot last known good configuration */
1264 ServiceEntry
= ServiceEntry
->Flink
;
1267 GroupEntry
= GroupEntry
->Flink
;
1270 DPRINT("IopInitializeSystemDrivers() done\n");
1276 * Unloads a device driver.
1280 * Name of the service to unload (registry key).
1283 * Whether to unload Plug & Plug or only legacy drivers. If this
1284 * parameter is set to FALSE, the routine will unload only legacy
1291 * Guard the whole function by SEH.
1295 IopUnloadDriver(PUNICODE_STRING DriverServiceName
, BOOLEAN UnloadPnpDrivers
)
1297 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1298 UNICODE_STRING ImagePath
;
1299 UNICODE_STRING ServiceName
;
1300 UNICODE_STRING ObjectName
;
1301 PDRIVER_OBJECT DriverObject
;
1302 PMODULE_OBJECT ModuleObject
;
1306 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName
, UnloadPnpDrivers
);
1309 * Get the service name from the registry key name
1312 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1314 Start
= DriverServiceName
->Buffer
;
1318 RtlInitUnicodeString(&ServiceName
, Start
);
1321 * Construct the driver object name
1324 ObjectName
.Length
= (wcslen(Start
) + 8) * sizeof(WCHAR
);
1325 ObjectName
.MaximumLength
= ObjectName
.Length
+ sizeof(WCHAR
);
1326 ObjectName
.Buffer
= ExAllocatePool(NonPagedPool
, ObjectName
.MaximumLength
);
1327 wcscpy(ObjectName
.Buffer
, L
"\\Driver\\");
1328 memcpy(ObjectName
.Buffer
+ 8, Start
, (ObjectName
.Length
- 8) * sizeof(WCHAR
));
1329 ObjectName
.Buffer
[ObjectName
.Length
/sizeof(WCHAR
)] = 0;
1332 * Find the driver object
1335 Status
= ObReferenceObjectByName(&ObjectName
, 0, 0, 0, IoDriverObjectType
,
1336 KernelMode
, 0, (PVOID
*)&DriverObject
);
1338 if (!NT_SUCCESS(Status
))
1340 DPRINT("Can't locate driver object for %wZ\n", ObjectName
);
1345 * Free the buffer for driver object name
1348 ExFreePool(ObjectName
.Buffer
);
1351 * Get path of service...
1354 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1356 RtlInitUnicodeString(&ImagePath
, NULL
);
1358 QueryTable
[0].Name
= L
"ImagePath";
1359 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1360 QueryTable
[0].EntryContext
= &ImagePath
;
1362 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1363 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1365 if (!NT_SUCCESS(Status
))
1367 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1372 * Normalize the image path for all later processing.
1375 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1377 if (!NT_SUCCESS(Status
))
1379 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1384 * ... and check if it's loaded
1387 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1388 if (ModuleObject
== NULL
)
1390 return STATUS_UNSUCCESSFUL
;
1394 * Free the service path
1397 RtlFreeUnicodeString(&ImagePath
);
1400 * Unload the module and release the references to the device object
1403 if (DriverObject
->DriverUnload
)
1404 (*DriverObject
->DriverUnload
)(DriverObject
);
1405 ObDereferenceObject(DriverObject
);
1406 ObDereferenceObject(DriverObject
);
1407 LdrUnloadModule(ModuleObject
);
1409 return STATUS_SUCCESS
;
1413 IopMarkLastReinitializeDriver(VOID
)
1417 KeAcquireSpinLock(&DriverReinitListLock
,
1420 if (IsListEmpty(&DriverReinitListHead
))
1422 DriverReinitTailEntry
= NULL
;
1426 DriverReinitTailEntry
= DriverReinitListHead
.Blink
;
1429 KeReleaseSpinLock(&DriverReinitListLock
,
1435 IopReinitializeDrivers(VOID
)
1437 PDRIVER_REINIT_ITEM ReinitItem
;
1441 KeAcquireSpinLock(&DriverReinitListLock
,
1444 if (DriverReinitTailEntry
== NULL
)
1446 KeReleaseSpinLock(&DriverReinitListLock
,
1451 KeReleaseSpinLock(&DriverReinitListLock
,
1456 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1457 &DriverReinitListLock
);
1461 ReinitItem
= (PDRIVER_REINIT_ITEM
)CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1463 /* Increment reinitialization counter */
1464 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1466 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1467 ReinitItem
->Context
,
1468 ReinitItem
->DriverObject
->DriverExtension
->Count
);
1472 if (Entry
== DriverReinitTailEntry
)
1477 /* PUBLIC FUNCTIONS ***********************************************************/
1482 * Loads a device driver.
1486 * Name of the service to load (registry key).
1496 NtLoadDriver(IN PUNICODE_STRING DriverServiceName
)
1498 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1499 UNICODE_STRING ImagePath
;
1500 UNICODE_STRING ServiceName
;
1503 PDEVICE_NODE DeviceNode
;
1504 PMODULE_OBJECT ModuleObject
;
1505 PDRIVER_OBJECT DriverObject
;
1508 DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName
);
1511 * Check security privileges
1514 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, KeGetPreviousMode()))
1515 return STATUS_PRIVILEGE_NOT_HELD
;
1517 RtlInitUnicodeString(&ImagePath
, NULL
);
1520 * Get the service name from the registry key name.
1523 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1525 Start
= DriverServiceName
->Buffer
;
1529 RtlInitUnicodeString(&ServiceName
, Start
);
1535 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
1537 RtlInitUnicodeString(&ImagePath
, NULL
);
1539 QueryTable
[0].Name
= L
"Type";
1540 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1541 QueryTable
[0].EntryContext
= &Type
;
1543 QueryTable
[1].Name
= L
"ImagePath";
1544 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1545 QueryTable
[1].EntryContext
= &ImagePath
;
1547 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1548 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1550 if (!NT_SUCCESS(Status
))
1552 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
1553 RtlFreeUnicodeString(&ImagePath
);
1558 * Normalize the image path for all later processing.
1561 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1563 if (!NT_SUCCESS(Status
))
1565 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1569 DPRINT("FullImagePath: '%S'\n", ImagePath
.Buffer
);
1570 DPRINT("Type: %lx\n", Type
);
1573 * See, if the driver module isn't already loaded
1576 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1577 if (ModuleObject
!= NULL
)
1579 return STATUS_IMAGE_ALREADY_LOADED
;
1583 * Create device node
1586 /* Use IopRootDeviceNode for now */
1587 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1589 if (!NT_SUCCESS(Status
))
1591 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status
);
1596 * Load the driver module
1599 Status
= LdrLoadModule(&ImagePath
, &ModuleObject
);
1601 if (!NT_SUCCESS(Status
))
1603 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status
);
1604 IopFreeDeviceNode(DeviceNode
);
1609 * Set a service name for the device node
1612 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1614 Start
= DriverServiceName
->Buffer
;
1617 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, Start
);
1620 * Initialize the driver module
1623 Status
= IopInitializeDriverModule(
1626 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1627 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */),
1630 if (!NT_SUCCESS(Status
))
1632 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status
);
1633 LdrUnloadModule(ModuleObject
);
1634 IopFreeDeviceNode(DeviceNode
);
1638 IopInitializeDevice(DeviceNode
, DriverObject
);
1646 * Unloads a legacy device driver.
1650 * Name of the service to unload (registry key).
1660 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName
)
1662 return IopUnloadDriver(DriverServiceName
, FALSE
);
1666 * IoRegisterDriverReinitialization
1673 IoRegisterDriverReinitialization(
1674 PDRIVER_OBJECT DriverObject
,
1675 PDRIVER_REINITIALIZE ReinitRoutine
,
1678 PDRIVER_REINIT_ITEM ReinitItem
;
1680 ReinitItem
= ExAllocatePool(NonPagedPool
, sizeof(DRIVER_REINIT_ITEM
));
1681 if (ReinitItem
== NULL
)
1684 ReinitItem
->DriverObject
= DriverObject
;
1685 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1686 ReinitItem
->Context
= Context
;
1688 ExInterlockedInsertTailList(
1689 &DriverReinitListHead
,
1690 &ReinitItem
->ItemEntry
,
1691 &DriverReinitListLock
);
1695 * IoAllocateDriverObjectExtension
1702 IoAllocateDriverObjectExtension(
1703 PDRIVER_OBJECT DriverObject
,
1704 PVOID ClientIdentificationAddress
,
1705 ULONG DriverObjectExtensionSize
,
1706 PVOID
*DriverObjectExtension
)
1709 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1710 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension
;
1712 NewDriverExtension
= ExAllocatePoolWithTag(
1714 sizeof(PRIVATE_DRIVER_EXTENSIONS
) - sizeof(CHAR
) +
1715 DriverObjectExtensionSize
,
1716 TAG_DRIVER_EXTENSION
);
1718 if (NewDriverExtension
== NULL
)
1720 return STATUS_INSUFFICIENT_RESOURCES
;
1723 OldIrql
= KeRaiseIrqlToDpcLevel();
1725 NewDriverExtension
->Link
= DriverObject
->DriverSection
;
1726 NewDriverExtension
->ClientIdentificationAddress
= ClientIdentificationAddress
;
1728 for (DriverExtensions
= DriverObject
->DriverSection
;
1729 DriverExtensions
!= NULL
;
1730 DriverExtensions
= DriverExtensions
->Link
)
1732 if (DriverExtensions
->ClientIdentificationAddress
==
1733 ClientIdentificationAddress
)
1735 KfLowerIrql(OldIrql
);
1736 return STATUS_OBJECT_NAME_COLLISION
;
1740 DriverObject
->DriverSection
= NewDriverExtension
;
1742 KfLowerIrql(OldIrql
);
1744 *DriverObjectExtension
= &NewDriverExtension
->Extension
;
1746 return STATUS_SUCCESS
;
1750 * IoGetDriverObjectExtension
1757 IoGetDriverObjectExtension(
1758 PDRIVER_OBJECT DriverObject
,
1759 PVOID ClientIdentificationAddress
)
1762 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1764 OldIrql
= KeRaiseIrqlToDpcLevel();
1766 for (DriverExtensions
= DriverObject
->DriverSection
;
1767 DriverExtensions
!= NULL
&&
1768 DriverExtensions
->ClientIdentificationAddress
!=
1769 ClientIdentificationAddress
;
1770 DriverExtensions
= DriverExtensions
->Link
)
1773 KfLowerIrql(OldIrql
);
1775 if (DriverExtensions
== NULL
)
1778 return &DriverExtensions
->Extension
;