1 /* $Id: driver.c,v 1.51 2004/09/07 11:48:16 ekohl 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 *******************************************************************/
17 #include <internal/debug.h>
20 extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
23 LdrProcessModule(PVOID ModuleLoadBase
,
24 PUNICODE_STRING ModuleName
,
25 PMODULE_OBJECT
*ModuleObject
);
27 typedef struct _SERVICE_GROUP
29 LIST_ENTRY GroupListEntry
;
30 UNICODE_STRING GroupName
;
31 BOOLEAN ServicesRunning
;
32 } SERVICE_GROUP
, *PSERVICE_GROUP
;
34 typedef struct _SERVICE
36 LIST_ENTRY ServiceListEntry
;
37 UNICODE_STRING ServiceName
;
38 UNICODE_STRING RegistryPath
;
39 UNICODE_STRING ServiceGroup
;
40 UNICODE_STRING ImagePath
;
47 /* BOOLEAN ServiceRunning;*/ // needed ??
50 typedef struct _DRIVER_REINIT_ITEM
53 PDRIVER_OBJECT DriverObject
;
54 PDRIVER_REINITIALIZE ReinitRoutine
;
56 } DRIVER_REINIT_ITEM
, *PDRIVER_REINIT_ITEM
;
58 /* GLOBALS ********************************************************************/
60 static LIST_ENTRY DriverReinitListHead
;
61 static PLIST_ENTRY DriverReinitTailEntry
;
62 static KSPIN_LOCK DriverReinitListLock
;
64 static LIST_ENTRY GroupListHead
= {NULL
, NULL
};
65 static LIST_ENTRY ServiceListHead
= {NULL
, NULL
};
67 POBJECT_TYPE EXPORTED IoDriverObjectType
= NULL
;
69 #define TAG_DRIVER TAG('D', 'R', 'V', 'R')
70 #define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
72 /* DECLARATIONS ***************************************************************/
79 POBJECT_ATTRIBUTES ObjectAttributes
);
82 IopDeleteDriver(PVOID ObjectBody
);
84 /* PRIVATE FUNCTIONS **********************************************************/
87 IopInitDriverImplementation(VOID
)
89 /* Register the process object type */
90 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
91 IoDriverObjectType
->Tag
= TAG('D', 'R', 'V', 'R');
92 IoDriverObjectType
->TotalObjects
= 0;
93 IoDriverObjectType
->TotalHandles
= 0;
94 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
95 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
96 IoDriverObjectType
->PagedPoolCharge
= 0;
97 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(DRIVER_OBJECT
);
98 IoDriverObjectType
->Dump
= NULL
;
99 IoDriverObjectType
->Open
= NULL
;
100 IoDriverObjectType
->Close
= NULL
;
101 IoDriverObjectType
->Delete
= IopDeleteDriver
;
102 IoDriverObjectType
->Parse
= NULL
;
103 IoDriverObjectType
->Security
= NULL
;
104 IoDriverObjectType
->QueryName
= NULL
;
105 IoDriverObjectType
->OkayToClose
= NULL
;
106 IoDriverObjectType
->Create
= IopCreateDriver
;
107 IoDriverObjectType
->DuplicationNotify
= NULL
;
108 RtlRosInitUnicodeStringFromLiteral(&IoDriverObjectType
->TypeName
, L
"Driver");
110 ObpCreateTypeObject(IoDriverObjectType
);
112 InitializeListHead(&DriverReinitListHead
);
113 KeInitializeSpinLock(&DriverReinitListLock
);
114 DriverReinitTailEntry
= NULL
;
118 IopInvalidDeviceRequest(
119 PDEVICE_OBJECT DeviceObject
,
122 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
123 Irp
->IoStatus
.Information
= 0;
124 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
125 return STATUS_INVALID_DEVICE_REQUEST
;
133 POBJECT_ATTRIBUTES ObjectAttributes
)
135 PDRIVER_OBJECT Object
= ObjectBody
;
138 DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
139 ObjectBody
, Parent
, RemainingPath
);
141 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
142 return STATUS_UNSUCCESSFUL
;
144 /* Create driver extension */
145 Object
->DriverExtension
= (PDRIVER_EXTENSION
)
146 ExAllocatePoolWithTag(
148 sizeof(DRIVER_EXTENSION
),
149 TAG_DRIVER_EXTENSION
);
151 if (Object
->DriverExtension
== NULL
)
153 return STATUS_NO_MEMORY
;
156 RtlZeroMemory(Object
->DriverExtension
, sizeof(DRIVER_EXTENSION
));
158 Object
->Type
= InternalDriverType
;
160 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
161 Object
->MajorFunction
[i
] = IopInvalidDeviceRequest
;
163 return STATUS_SUCCESS
;
167 IopDeleteDriver(PVOID ObjectBody
)
169 PDRIVER_OBJECT Object
= ObjectBody
;
171 PPRIVATE_DRIVER_EXTENSIONS DriverExtension
, NextDriverExtension
;
173 DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody
);
175 ExFreePool(Object
->DriverExtension
);
177 OldIrql
= KeRaiseIrqlToDpcLevel();
179 for (DriverExtension
= Object
->DriverSection
;
180 DriverExtension
!= NULL
;
181 DriverExtension
= NextDriverExtension
)
183 NextDriverExtension
= DriverExtension
->Link
;
184 ExFreePool(DriverExtension
);
187 KfLowerIrql(OldIrql
);
191 IopCreateDriverObject(
192 PDRIVER_OBJECT
*DriverObject
,
193 PUNICODE_STRING ServiceName
,
195 PVOID DriverImageStart
,
196 ULONG DriverImageSize
)
198 PDRIVER_OBJECT Object
;
199 WCHAR NameBuffer
[MAX_PATH
];
200 UNICODE_STRING DriverName
;
201 OBJECT_ATTRIBUTES ObjectAttributes
;
204 DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n",
205 DriverObject
, ServiceName
, FileSystem
, DriverImageStart
, DriverImageSize
);
207 *DriverObject
= NULL
;
209 /* Create ModuleName string */
210 if (ServiceName
!= NULL
&& ServiceName
->Buffer
!= NULL
)
212 if (FileSystem
== TRUE
)
213 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
215 wcscpy(NameBuffer
, DRIVER_ROOT_NAME
);
216 wcscat(NameBuffer
, ServiceName
->Buffer
);
218 RtlInitUnicodeString(&DriverName
, NameBuffer
);
219 DPRINT("Driver name: '%wZ'\n", &DriverName
);
223 RtlInitUnicodeString(&DriverName
, NULL
);
226 /* Initialize ObjectAttributes for driver object */
227 InitializeObjectAttributes(
234 /* Create driver object */
235 Status
= ObCreateObject(
241 sizeof(DRIVER_OBJECT
),
246 if (!NT_SUCCESS(Status
))
251 Object
->DriverStart
= DriverImageStart
;
252 Object
->DriverSize
= DriverImageSize
;
254 *DriverObject
= Object
;
256 return STATUS_SUCCESS
;
260 * IopDisplayLoadingMessage
262 * Display 'Loading XXX...' message.
266 IopDisplayLoadingMessage(PWCHAR ServiceName
)
268 CHAR TextBuffer
[256];
269 sprintf(TextBuffer
, "Loading %S...\n", ServiceName
);
270 HalDisplayString(TextBuffer
);
274 * IopNormalizeImagePath
276 * Normalize an image path to contain complete path.
280 * The input path and on exit the result path. ImagePath.Buffer
281 * must be allocated by ExAllocatePool on input. Caller is responsible
282 * for freeing the buffer when it's no longer needed.
285 * Name of the service that ImagePath belongs to.
291 * The input image path isn't freed on error.
295 IopNormalizeImagePath(
296 IN OUT PUNICODE_STRING ImagePath
,
297 IN PUNICODE_STRING ServiceName
)
299 UNICODE_STRING InputImagePath
;
304 sizeof(UNICODE_STRING
));
306 if (InputImagePath
.Length
== 0)
308 ImagePath
->Length
= (33 * sizeof(WCHAR
)) + ServiceName
->Length
;
309 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
310 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
311 if (ImagePath
->Buffer
== NULL
)
312 return STATUS_NO_MEMORY
;
314 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\system32\\drivers\\");
315 wcscat(ImagePath
->Buffer
, ServiceName
->Buffer
);
316 wcscat(ImagePath
->Buffer
, L
".sys");
318 if (InputImagePath
.Buffer
[0] != L
'\\')
320 ImagePath
->Length
= (12 * sizeof(WCHAR
)) + InputImagePath
.Length
;
321 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
322 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
323 if (ImagePath
->Buffer
== NULL
)
324 return STATUS_NO_MEMORY
;
326 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\");
327 wcscat(ImagePath
->Buffer
, InputImagePath
.Buffer
);
328 RtlFreeUnicodeString(&InputImagePath
);
331 return STATUS_SUCCESS
;
335 * IopLoadServiceModule
337 * Load a module specified by registry settings for service.
341 * Name of the service to load.
348 IopLoadServiceModule(
349 IN PUNICODE_STRING ServiceName
,
350 OUT PMODULE_OBJECT
*ModuleObject
)
352 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
354 UNICODE_STRING ServiceImagePath
;
357 DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName
, ModuleObject
);
360 * Get information about the service.
363 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
365 RtlInitUnicodeString(&ServiceImagePath
, NULL
);
367 QueryTable
[0].Name
= L
"Start";
368 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
369 QueryTable
[0].EntryContext
= &ServiceStart
;
371 QueryTable
[1].Name
= L
"ImagePath";
372 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
373 QueryTable
[1].EntryContext
= &ServiceImagePath
;
375 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
376 ServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
378 if (!NT_SUCCESS(Status
))
380 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
384 IopDisplayLoadingMessage(ServiceName
->Buffer
);
387 * Normalize the image path for all later processing.
390 Status
= IopNormalizeImagePath(&ServiceImagePath
, ServiceName
);
392 if (!NT_SUCCESS(Status
))
394 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
402 *ModuleObject
= LdrGetModuleObject(&ServiceImagePath
);
404 if (*ModuleObject
== NULL
)
406 Status
= STATUS_UNSUCCESSFUL
;
409 * Special case for boot modules that were loaded by boot loader.
412 if (ServiceStart
== 0)
415 CHAR SearchName
[256];
417 PLOADER_MODULE KeLoaderModules
=
418 (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
422 * Improve this searching algorithm by using the image name
423 * stored in registry entry ImageName and use the whole path
424 * (requires change in FreeLoader).
427 _snprintf(SearchName
, sizeof(SearchName
), "%wZ.sys", ServiceName
);
428 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
430 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
431 if (!_stricmp(ModuleName
, SearchName
))
433 DPRINT("Initializing boot module\n");
435 /* Tell, that the module is already loaded */
436 KeLoaderModules
[i
].Reserved
= 1;
438 Status
= LdrProcessModule(
439 (PVOID
)KeLoaderModules
[i
].ModStart
,
449 * Case for rest of the drivers (except disabled)
452 else if (ServiceStart
< 4)
454 DPRINT("Loading module\n");
455 Status
= LdrLoadModule(&ServiceImagePath
, ModuleObject
);
460 DPRINT("Module already loaded\n");
461 Status
= STATUS_SUCCESS
;
464 RtlFreeUnicodeString(&ServiceImagePath
);
467 * Now check if the module was loaded successfully.
470 if (!NT_SUCCESS(Status
))
472 DPRINT("Module loading failed (Status %x)\n", Status
);
475 DPRINT("Module loading (Status %x)\n", Status
);
481 * IopInitializeDriverModule
483 * Initalize a loaded driver.
487 * Pointer to device node.
490 * Module object representing the driver. It can be retrieve by
491 * IopLoadServiceModule.
494 * Set to TRUE for file system drivers.
497 * On successful return this contains the driver object representing
502 IopInitializeDriverModule(
503 IN PDEVICE_NODE DeviceNode
,
504 IN PMODULE_OBJECT ModuleObject
,
505 IN BOOLEAN FileSystemDriver
,
506 OUT PDRIVER_OBJECT
*DriverObject
)
508 UNICODE_STRING RegistryKey
;
509 PDRIVER_INITIALIZE DriverEntry
= ModuleObject
->EntryPoint
;
511 WCHAR ServicesKeyName
[] = L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
513 Status
= IopCreateDriverObject(
515 &DeviceNode
->ServiceName
,
518 ModuleObject
->Length
);
520 if (!NT_SUCCESS(Status
))
522 DPRINT("IopCreateDriverObject failed (Status %x)\n", Status
);
526 if (DeviceNode
->ServiceName
.Buffer
)
528 RegistryKey
.Length
= DeviceNode
->ServiceName
.Length
+
529 sizeof(ServicesKeyName
);
530 RegistryKey
.MaximumLength
= RegistryKey
.Length
+ sizeof(UNICODE_NULL
);
531 RegistryKey
.Buffer
= ExAllocatePool(PagedPool
, RegistryKey
.MaximumLength
);
532 wcscpy(RegistryKey
.Buffer
, ServicesKeyName
);
533 wcscat(RegistryKey
.Buffer
, DeviceNode
->ServiceName
.Buffer
);
537 RtlInitUnicodeString(&RegistryKey
, NULL
);
540 DPRINT("RegistryKey: %wZ\n", &RegistryKey
);
541 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry
);
543 IopMarkLastReinitializeDriver();
545 Status
= DriverEntry(*DriverObject
, &RegistryKey
);
546 if (!NT_SUCCESS(Status
))
548 ObMakeTemporaryObject(*DriverObject
);
549 ObDereferenceObject(*DriverObject
);
553 IopReinitializeDrivers();
555 return STATUS_SUCCESS
;
559 * IopAttachFilterDriversCallback
561 * Internal routine used by IopAttachFilterDrivers.
565 IopAttachFilterDriversCallback(
573 PDEVICE_NODE DeviceNode
= Context
;
574 UNICODE_STRING ServiceName
;
576 PMODULE_OBJECT ModuleObject
;
577 PDRIVER_OBJECT DriverObject
;
580 for (Filters
= ValueData
;
581 ((ULONG_PTR
)Filters
- (ULONG_PTR
)ValueData
) < ValueLength
&&
583 Filters
+= (ServiceName
.Length
/ sizeof(WCHAR
)) + 1)
585 DPRINT("Filter Driver: %S (%wZ)\n", Filters
, &DeviceNode
->InstancePath
);
586 ServiceName
.Buffer
= Filters
;
587 ServiceName
.MaximumLength
=
588 ServiceName
.Length
= wcslen(Filters
) * sizeof(WCHAR
);
590 /* Load and initialize the filter driver */
591 Status
= IopLoadServiceModule(&ServiceName
, &ModuleObject
);
592 if (!NT_SUCCESS(Status
))
595 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
596 if (!NT_SUCCESS(Status
))
599 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
600 if (!NT_SUCCESS(Status
))
604 return STATUS_SUCCESS
;
608 * IopAttachFilterDrivers
610 * Load filter drivers for specified device node.
614 * Set to TRUE for loading lower level filters or FALSE for upper
619 IopAttachFilterDrivers(
620 PDEVICE_NODE DeviceNode
,
623 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
625 UNICODE_STRING Class
;
626 WCHAR ClassBuffer
[40];
630 * First load the device filters
633 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
635 QueryTable
[0].Name
= L
"LowerFilters";
637 QueryTable
[0].Name
= L
"UpperFilters";
638 QueryTable
[0].EntryContext
= NULL
;
639 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
640 QueryTable
[1].QueryRoutine
= NULL
;
641 QueryTable
[1].Name
= NULL
;
643 KeyBuffer
= ExAllocatePool(
645 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
646 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
647 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
649 RtlQueryRegistryValues(
650 RTL_REGISTRY_ABSOLUTE
,
657 * Now get the class GUID
661 Class
.MaximumLength
= 40 * sizeof(WCHAR
);
662 Class
.Buffer
= ClassBuffer
;
663 QueryTable
[0].QueryRoutine
= NULL
;
664 QueryTable
[0].Name
= L
"ClassGUID";
665 QueryTable
[0].EntryContext
= &Class
;
666 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
668 Status
= RtlQueryRegistryValues(
669 RTL_REGISTRY_ABSOLUTE
,
675 ExFreePool(KeyBuffer
);
678 * Load the class filter driver
681 if (NT_SUCCESS(Status
))
683 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
685 QueryTable
[0].Name
= L
"LowerFilters";
687 QueryTable
[0].Name
= L
"UpperFilters";
688 QueryTable
[0].EntryContext
= NULL
;
689 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
691 KeyBuffer
= ExAllocatePool(PagedPool
, (58 * sizeof(WCHAR
)) + Class
.Length
);
692 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
693 wcscat(KeyBuffer
, ClassBuffer
);
695 RtlQueryRegistryValues(
696 RTL_REGISTRY_ABSOLUTE
,
702 ExFreePool(KeyBuffer
);
705 return STATUS_SUCCESS
;
708 static NTSTATUS STDCALL
709 IopCreateGroupListEntry(PWSTR ValueName
,
716 PSERVICE_GROUP Group
;
718 if (ValueType
== REG_SZ
)
720 DPRINT("GroupName: '%S'\n", (PWCHAR
)ValueData
);
722 Group
= ExAllocatePool(NonPagedPool
,
723 sizeof(SERVICE_GROUP
));
726 return(STATUS_INSUFFICIENT_RESOURCES
);
729 RtlZeroMemory(Group
, sizeof(SERVICE_GROUP
));
731 if (!RtlCreateUnicodeString(&Group
->GroupName
,
735 return(STATUS_INSUFFICIENT_RESOURCES
);
739 InsertTailList(&GroupListHead
,
740 &Group
->GroupListEntry
);
743 return(STATUS_SUCCESS
);
747 static NTSTATUS STDCALL
748 IopCreateServiceListEntry(PUNICODE_STRING ServiceName
)
750 RTL_QUERY_REGISTRY_TABLE QueryTable
[6];
754 DPRINT("ServiceName: '%wZ'\n", ServiceName
);
756 /* Allocate service entry */
757 Service
= (PSERVICE
)ExAllocatePool(NonPagedPool
, sizeof(SERVICE
));
760 DPRINT1("ExAllocatePool() failed\n");
761 return(STATUS_INSUFFICIENT_RESOURCES
);
763 RtlZeroMemory(Service
, sizeof(SERVICE
));
765 /* Get service data */
766 RtlZeroMemory(&QueryTable
,
769 QueryTable
[0].Name
= L
"Start";
770 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
771 QueryTable
[0].EntryContext
= &Service
->Start
;
773 QueryTable
[1].Name
= L
"Type";
774 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
775 QueryTable
[1].EntryContext
= &Service
->Type
;
777 QueryTable
[2].Name
= L
"ErrorControl";
778 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
779 QueryTable
[2].EntryContext
= &Service
->ErrorControl
;
781 QueryTable
[3].Name
= L
"Group";
782 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
783 QueryTable
[3].EntryContext
= &Service
->ServiceGroup
;
785 QueryTable
[4].Name
= L
"ImagePath";
786 QueryTable
[4].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
787 QueryTable
[4].EntryContext
= &Service
->ImagePath
;
789 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
794 if (!NT_SUCCESS(Status
) || Service
->Start
> 1)
796 RtlFreeUnicodeString(&Service
->ServiceGroup
);
797 RtlFreeUnicodeString(&Service
->ImagePath
);
802 /* Copy service name */
803 Service
->ServiceName
.Length
= ServiceName
->Length
;
804 Service
->ServiceName
.MaximumLength
= ServiceName
->Length
+ sizeof(WCHAR
);
805 Service
->ServiceName
.Buffer
= ExAllocatePool(NonPagedPool
,
806 Service
->ServiceName
.MaximumLength
);
807 RtlCopyMemory(Service
->ServiceName
.Buffer
,
809 ServiceName
->Length
);
810 Service
->ServiceName
.Buffer
[ServiceName
->Length
/ sizeof(WCHAR
)] = 0;
812 /* Build registry path */
813 Service
->RegistryPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
814 Service
->RegistryPath
.Buffer
= ExAllocatePool(NonPagedPool
,
815 MAX_PATH
* sizeof(WCHAR
));
816 wcscpy(Service
->RegistryPath
.Buffer
,
817 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
818 wcscat(Service
->RegistryPath
.Buffer
,
819 Service
->ServiceName
.Buffer
);
820 Service
->RegistryPath
.Length
= wcslen(Service
->RegistryPath
.Buffer
) * sizeof(WCHAR
);
822 DPRINT("ServiceName: '%wZ'\n", &Service
->ServiceName
);
823 DPRINT("RegistryPath: '%wZ'\n", &Service
->RegistryPath
);
824 DPRINT("ServiceGroup: '%wZ'\n", &Service
->ServiceGroup
);
825 DPRINT("ImagePath: '%wZ'\n", &Service
->ImagePath
);
826 DPRINT("Start %lx Type %lx ErrorControl %lx\n",
827 Service
->Start
, Service
->Type
, Service
->ErrorControl
);
829 /* Append service entry */
830 InsertTailList(&ServiceListHead
,
831 &Service
->ServiceListEntry
);
833 return(STATUS_SUCCESS
);
837 NTSTATUS INIT_FUNCTION
838 IoCreateDriverList(VOID
)
840 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
841 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
842 OBJECT_ATTRIBUTES ObjectAttributes
;
843 UNICODE_STRING ServicesKeyName
;
844 UNICODE_STRING SubKeyName
;
849 ULONG KeyInfoLength
= 0;
850 ULONG ReturnedLength
;
852 DPRINT("IoCreateDriverList() called\n");
854 /* Initialize basic variables */
855 InitializeListHead(&GroupListHead
);
856 InitializeListHead(&ServiceListHead
);
858 /* Build group order list */
859 RtlZeroMemory(&QueryTable
,
862 QueryTable
[0].Name
= L
"List";
863 QueryTable
[0].QueryRoutine
= IopCreateGroupListEntry
;
865 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
866 L
"ServiceGroupOrder",
870 if (!NT_SUCCESS(Status
))
873 /* Enumerate services and create the service list */
874 RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName
,
875 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
877 InitializeObjectAttributes(&ObjectAttributes
,
879 OBJ_CASE_INSENSITIVE
,
883 Status
= NtOpenKey(&KeyHandle
,
886 if (!NT_SUCCESS(Status
))
891 KeyInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
892 KeyInfo
= ExAllocatePool(NonPagedPool
, KeyInfoLength
);
896 return(STATUS_INSUFFICIENT_RESOURCES
);
902 Status
= NtEnumerateKey(KeyHandle
,
908 if (NT_SUCCESS(Status
))
910 if (KeyInfo
->NameLength
< MAX_PATH
* sizeof(WCHAR
))
913 SubKeyName
.Length
= KeyInfo
->NameLength
;
914 SubKeyName
.MaximumLength
= KeyInfo
->NameLength
+ sizeof(WCHAR
);
915 SubKeyName
.Buffer
= KeyInfo
->Name
;
916 SubKeyName
.Buffer
[SubKeyName
.Length
/ sizeof(WCHAR
)] = 0;
918 DPRINT("KeyName: '%wZ'\n", &SubKeyName
);
919 IopCreateServiceListEntry(&SubKeyName
);
923 if (!NT_SUCCESS(Status
))
932 DPRINT("IoCreateDriverList() done\n");
934 return(STATUS_SUCCESS
);
937 NTSTATUS INIT_FUNCTION
938 IoDestroyDriverList(VOID
)
940 PLIST_ENTRY GroupEntry
;
941 PLIST_ENTRY ServiceEntry
;
942 PSERVICE_GROUP CurrentGroup
;
943 PSERVICE CurrentService
;
945 DPRINT("IoDestroyDriverList() called\n");
947 /* Destroy group list */
948 GroupEntry
= GroupListHead
.Flink
;
949 while (GroupEntry
!= &GroupListHead
)
951 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
953 RtlFreeUnicodeString(&CurrentGroup
->GroupName
);
954 RemoveEntryList(GroupEntry
);
955 ExFreePool(CurrentGroup
);
957 GroupEntry
= GroupListHead
.Flink
;
960 /* Destroy service list */
961 ServiceEntry
= ServiceListHead
.Flink
;
962 while (ServiceEntry
!= &ServiceListHead
)
964 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
966 RtlFreeUnicodeString(&CurrentService
->ServiceName
);
967 RtlFreeUnicodeString(&CurrentService
->RegistryPath
);
968 RtlFreeUnicodeString(&CurrentService
->ServiceGroup
);
969 RtlFreeUnicodeString(&CurrentService
->ImagePath
);
970 RemoveEntryList(ServiceEntry
);
971 ExFreePool(CurrentService
);
973 ServiceEntry
= ServiceListHead
.Flink
;
976 DPRINT("IoDestroyDriverList() done\n");
978 return(STATUS_SUCCESS
);
982 MiFreeBootDriverMemory(PVOID StartAddress
, ULONG Length
)
986 for (i
= 0; i
< PAGE_ROUND_UP(Length
) / PAGE_SIZE
; i
++)
988 MmDeleteVirtualMapping(NULL
, (char*)StartAddress
+ i
* PAGE_SIZE
, TRUE
, NULL
, NULL
);
993 * IopInitializeBuiltinDriver
995 * Initialize a driver that is already loaded in memory.
999 IopInitializeBuiltinDriver(
1000 PDEVICE_NODE ModuleDeviceNode
,
1001 PVOID ModuleLoadBase
,
1005 PMODULE_OBJECT ModuleObject
;
1006 PDEVICE_NODE DeviceNode
;
1007 PDRIVER_OBJECT DriverObject
;
1009 CHAR TextBuffer
[256];
1010 PCHAR FileNameWithoutPath
;
1011 LPWSTR FileExtension
;
1013 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1014 FileName
, ModuleLoadBase
, ModuleLength
);
1017 * Display 'Initializing XXX...' message
1020 sprintf(TextBuffer
, "Initializing %s...\n", FileName
);
1021 HalDisplayString(TextBuffer
);
1024 * Determine the right device object
1027 if (ModuleDeviceNode
== NULL
)
1029 /* Use IopRootDeviceNode for now */
1030 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1031 if (!NT_SUCCESS(Status
))
1033 CPRINT("Driver load failed, status (%x)\n", Status
);
1038 DeviceNode
= ModuleDeviceNode
;
1042 * Generate filename without path (not needed by freeldr)
1045 FileNameWithoutPath
= strrchr(FileName
, '\\');
1046 if (FileNameWithoutPath
== NULL
)
1048 FileNameWithoutPath
= FileName
;
1055 RtlCreateUnicodeStringFromAsciiz(&DeviceNode
->ServiceName
,
1056 FileNameWithoutPath
);
1057 Status
= LdrProcessModule(ModuleLoadBase
, &DeviceNode
->ServiceName
,
1059 if (ModuleObject
== NULL
)
1061 if (ModuleDeviceNode
== NULL
)
1062 IopFreeDeviceNode(DeviceNode
);
1063 CPRINT("Driver load failed, status (%x)\n", Status
);
1064 return STATUS_UNSUCCESSFUL
;
1068 * Strip the file extension from ServiceName
1071 FileExtension
= wcsrchr(DeviceNode
->ServiceName
.Buffer
, '.');
1072 if (FileExtension
!= NULL
)
1074 DeviceNode
->ServiceName
.Length
-= wcslen(FileExtension
) * sizeof(WCHAR
);
1075 FileExtension
[0] = 0;
1079 * Initialize the driver
1082 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
,
1085 if (!NT_SUCCESS(Status
))
1087 if (ModuleDeviceNode
== NULL
)
1088 IopFreeDeviceNode(DeviceNode
);
1089 CPRINT("Driver load failed, status (%x)\n", Status
);
1093 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1099 * IopInitializeBootDrivers
1101 * Initialize boot drivers and free memory for boot files.
1111 IopInitializeBootDrivers(VOID
)
1113 ULONG BootDriverCount
;
1119 PLOADER_MODULE KeLoaderModules
= (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
1122 DPRINT("IopInitializeBootDrivers()\n");
1124 BootDriverCount
= 0;
1125 for (i
= 2; i
< KeLoaderBlock
.ModsCount
; i
++)
1127 ModuleStart
= KeLoaderModules
[i
].ModStart
;
1128 ModuleSize
= KeLoaderModules
[i
].ModEnd
- ModuleStart
;
1129 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
1130 ModuleLoaded
= KeLoaderModules
[i
].Reserved
;
1131 Extension
= strrchr(ModuleName
, '.');
1132 if (Extension
== NULL
)
1136 * Pass symbol files to kernel debugger
1139 if (!_stricmp(Extension
, ".sym"))
1141 KDB_SYMBOLFILE_HOOK((PVOID
)ModuleStart
, ModuleName
, ModuleSize
);
1145 * Load builtin driver
1148 if (!_stricmp(Extension
, ".sys"))
1152 IopInitializeBuiltinDriver(NULL
, (PVOID
)ModuleStart
, ModuleName
,
1159 * Free memory for all boot files, except ntoskrnl.exe and hal.dll
1164 * Do not free the memory from symbol files, if the kernel debugger
1167 if (_stricmp(Extension
, ".sym"))
1170 MiFreeBootDriverMemory((PVOID
)KeLoaderModules
[i
].ModStart
,
1171 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
1175 if (BootDriverCount
== 0)
1177 DbgPrint("No boot drivers available.\n");
1183 * IopInitializeSystemDrivers
1185 * Load drivers marked as system start.
1195 IopInitializeSystemDrivers(VOID
)
1197 PLIST_ENTRY GroupEntry
;
1198 PLIST_ENTRY ServiceEntry
;
1199 PSERVICE_GROUP CurrentGroup
;
1200 PSERVICE CurrentService
;
1203 DPRINT("IopInitializeSystemDrivers()\n");
1205 GroupEntry
= GroupListHead
.Flink
;
1206 while (GroupEntry
!= &GroupListHead
)
1208 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1210 DPRINT("Group: %wZ\n", &CurrentGroup
->GroupName
);
1212 ServiceEntry
= ServiceListHead
.Flink
;
1213 while (ServiceEntry
!= &ServiceListHead
)
1215 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1217 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1218 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1219 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/))
1221 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1222 IopDisplayLoadingMessage(CurrentService
->ServiceName
.Buffer
);
1223 Status
= NtLoadDriver(&CurrentService
->RegistryPath
);
1224 if (!NT_SUCCESS(Status
))
1226 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status
);
1228 if (CurrentService
->ErrorControl
== 1)
1232 if (CurrentService
->ErrorControl
== 2)
1234 if (IsLastKnownGood
== FALSE
)
1236 /* Boot last known good configuration */
1239 if (CurrentService
->ErrorControl
== 3)
1241 if (IsLastKnownGood
== FALSE
)
1243 /* Boot last known good configuration */
1252 ServiceEntry
= ServiceEntry
->Flink
;
1255 GroupEntry
= GroupEntry
->Flink
;
1258 DPRINT("IopInitializeSystemDrivers() done\n");
1264 * Unloads a device driver.
1268 * Name of the service to unload (registry key).
1271 * Whether to unload Plug & Plug or only legacy drivers. If this
1272 * parameter is set to FALSE, the routine will unload only legacy
1279 * Guard the whole function by SEH.
1283 IopUnloadDriver(PUNICODE_STRING DriverServiceName
, BOOLEAN UnloadPnpDrivers
)
1285 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1286 UNICODE_STRING ImagePath
;
1287 UNICODE_STRING ServiceName
;
1288 UNICODE_STRING ObjectName
;
1289 PDRIVER_OBJECT DriverObject
;
1290 PMODULE_OBJECT ModuleObject
;
1294 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName
, UnloadPnpDrivers
);
1297 * Get the service name from the registry key name
1300 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1302 Start
= DriverServiceName
->Buffer
;
1306 RtlInitUnicodeString(&ServiceName
, Start
);
1309 * Construct the driver object name
1312 ObjectName
.Length
= (wcslen(Start
) + 8) * sizeof(WCHAR
);
1313 ObjectName
.MaximumLength
= ObjectName
.Length
+ sizeof(WCHAR
);
1314 ObjectName
.Buffer
= ExAllocatePool(NonPagedPool
, ObjectName
.MaximumLength
);
1315 wcscpy(ObjectName
.Buffer
, L
"\\Driver\\");
1316 memcpy(ObjectName
.Buffer
+ 8, Start
, (ObjectName
.Length
- 8) * sizeof(WCHAR
));
1317 ObjectName
.Buffer
[ObjectName
.Length
/sizeof(WCHAR
)] = 0;
1320 * Find the driver object
1323 Status
= ObReferenceObjectByName(&ObjectName
, 0, 0, 0, IoDriverObjectType
,
1324 KernelMode
, 0, (PVOID
*)&DriverObject
);
1326 if (!NT_SUCCESS(Status
))
1328 DPRINT("Can't locate driver object for %wZ\n", ObjectName
);
1333 * Free the buffer for driver object name
1336 ExFreePool(ObjectName
.Buffer
);
1339 * Get path of service...
1342 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1344 RtlInitUnicodeString(&ImagePath
, NULL
);
1346 QueryTable
[0].Name
= L
"ImagePath";
1347 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1348 QueryTable
[0].EntryContext
= &ImagePath
;
1350 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1351 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1353 if (!NT_SUCCESS(Status
))
1355 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1360 * Normalize the image path for all later processing.
1363 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1365 if (!NT_SUCCESS(Status
))
1367 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1372 * ... and check if it's loaded
1375 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1376 if (ModuleObject
== NULL
)
1378 return STATUS_UNSUCCESSFUL
;
1382 * Free the service path
1385 RtlFreeUnicodeString(&ImagePath
);
1388 * Unload the module and release the references to the device object
1391 if (DriverObject
->DriverUnload
)
1392 (*DriverObject
->DriverUnload
)(DriverObject
);
1393 ObDereferenceObject(DriverObject
);
1394 ObDereferenceObject(DriverObject
);
1395 LdrUnloadModule(ModuleObject
);
1397 return STATUS_SUCCESS
;
1401 IopMarkLastReinitializeDriver(VOID
)
1405 KeAcquireSpinLock(&DriverReinitListLock
,
1408 if (IsListEmpty(&DriverReinitListHead
))
1410 DriverReinitTailEntry
= NULL
;
1414 DriverReinitTailEntry
= DriverReinitListHead
.Blink
;
1417 KeReleaseSpinLock(&DriverReinitListLock
,
1423 IopReinitializeDrivers(VOID
)
1425 PDRIVER_REINIT_ITEM ReinitItem
;
1429 KeAcquireSpinLock(&DriverReinitListLock
,
1432 if (DriverReinitTailEntry
== NULL
)
1434 KeReleaseSpinLock(&DriverReinitListLock
,
1439 KeReleaseSpinLock(&DriverReinitListLock
,
1444 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1445 &DriverReinitListLock
);
1449 ReinitItem
= (PDRIVER_REINIT_ITEM
)CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1451 /* Increment reinitialization counter */
1452 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1454 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1455 ReinitItem
->Context
,
1456 ReinitItem
->DriverObject
->DriverExtension
->Count
);
1460 if (Entry
== DriverReinitTailEntry
)
1465 /* PUBLIC FUNCTIONS ***********************************************************/
1474 IN PUNICODE_STRING DriverName
, OPTIONAL
1475 IN PDRIVER_INITIALIZE InitializationFunction
1479 return STATUS_NOT_IMPLEMENTED
;
1488 IN PDRIVER_OBJECT DriverObject
1498 * Loads a device driver.
1502 * Name of the service to load (registry key).
1512 NtLoadDriver(IN PUNICODE_STRING DriverServiceName
)
1514 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1515 UNICODE_STRING ImagePath
;
1516 UNICODE_STRING ServiceName
;
1519 PDEVICE_NODE DeviceNode
;
1520 PMODULE_OBJECT ModuleObject
;
1521 PDRIVER_OBJECT DriverObject
;
1524 DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName
);
1527 * Check security privileges
1530 /* FIXME: Uncomment when privileges will be correctly implemented. */
1532 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, KeGetPreviousMode()))
1534 DPRINT("Privilege not held\n");
1535 return STATUS_PRIVILEGE_NOT_HELD
;
1539 RtlInitUnicodeString(&ImagePath
, NULL
);
1542 * Get the service name from the registry key name.
1545 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1547 Start
= DriverServiceName
->Buffer
;
1551 RtlInitUnicodeString(&ServiceName
, Start
);
1557 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
1559 RtlInitUnicodeString(&ImagePath
, NULL
);
1561 QueryTable
[0].Name
= L
"Type";
1562 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1563 QueryTable
[0].EntryContext
= &Type
;
1565 QueryTable
[1].Name
= L
"ImagePath";
1566 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1567 QueryTable
[1].EntryContext
= &ImagePath
;
1569 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1570 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1572 if (!NT_SUCCESS(Status
))
1574 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
1575 RtlFreeUnicodeString(&ImagePath
);
1580 * Normalize the image path for all later processing.
1583 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1585 if (!NT_SUCCESS(Status
))
1587 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1591 DPRINT("FullImagePath: '%S'\n", ImagePath
.Buffer
);
1592 DPRINT("Type: %lx\n", Type
);
1595 * See, if the driver module isn't already loaded
1598 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1599 if (ModuleObject
!= NULL
)
1601 DPRINT("Image already loaded\n");
1602 return STATUS_IMAGE_ALREADY_LOADED
;
1606 * Create device node
1609 /* Use IopRootDeviceNode for now */
1610 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1612 if (!NT_SUCCESS(Status
))
1614 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status
);
1619 * Load the driver module
1622 Status
= LdrLoadModule(&ImagePath
, &ModuleObject
);
1624 if (!NT_SUCCESS(Status
))
1626 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status
);
1627 IopFreeDeviceNode(DeviceNode
);
1632 * Set a service name for the device node
1635 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1637 Start
= DriverServiceName
->Buffer
;
1640 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, Start
);
1643 * Initialize the driver module
1646 Status
= IopInitializeDriverModule(
1649 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1650 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */),
1653 if (!NT_SUCCESS(Status
))
1655 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status
);
1656 LdrUnloadModule(ModuleObject
);
1657 IopFreeDeviceNode(DeviceNode
);
1661 IopInitializeDevice(DeviceNode
, DriverObject
);
1669 * Unloads a legacy device driver.
1673 * Name of the service to unload (registry key).
1683 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName
)
1685 return IopUnloadDriver(DriverServiceName
, FALSE
);
1689 * IoRegisterDriverReinitialization
1696 IoRegisterDriverReinitialization(
1697 PDRIVER_OBJECT DriverObject
,
1698 PDRIVER_REINITIALIZE ReinitRoutine
,
1701 PDRIVER_REINIT_ITEM ReinitItem
;
1703 ReinitItem
= ExAllocatePool(NonPagedPool
, sizeof(DRIVER_REINIT_ITEM
));
1704 if (ReinitItem
== NULL
)
1707 ReinitItem
->DriverObject
= DriverObject
;
1708 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1709 ReinitItem
->Context
= Context
;
1711 ExInterlockedInsertTailList(
1712 &DriverReinitListHead
,
1713 &ReinitItem
->ItemEntry
,
1714 &DriverReinitListLock
);
1718 * IoAllocateDriverObjectExtension
1725 IoAllocateDriverObjectExtension(
1726 PDRIVER_OBJECT DriverObject
,
1727 PVOID ClientIdentificationAddress
,
1728 ULONG DriverObjectExtensionSize
,
1729 PVOID
*DriverObjectExtension
)
1732 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1733 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension
;
1735 NewDriverExtension
= ExAllocatePoolWithTag(
1737 sizeof(PRIVATE_DRIVER_EXTENSIONS
) - sizeof(CHAR
) +
1738 DriverObjectExtensionSize
,
1739 TAG_DRIVER_EXTENSION
);
1741 if (NewDriverExtension
== NULL
)
1743 return STATUS_INSUFFICIENT_RESOURCES
;
1746 OldIrql
= KeRaiseIrqlToDpcLevel();
1748 NewDriverExtension
->Link
= DriverObject
->DriverSection
;
1749 NewDriverExtension
->ClientIdentificationAddress
= ClientIdentificationAddress
;
1751 for (DriverExtensions
= DriverObject
->DriverSection
;
1752 DriverExtensions
!= NULL
;
1753 DriverExtensions
= DriverExtensions
->Link
)
1755 if (DriverExtensions
->ClientIdentificationAddress
==
1756 ClientIdentificationAddress
)
1758 KfLowerIrql(OldIrql
);
1759 return STATUS_OBJECT_NAME_COLLISION
;
1763 DriverObject
->DriverSection
= NewDriverExtension
;
1765 KfLowerIrql(OldIrql
);
1767 *DriverObjectExtension
= &NewDriverExtension
->Extension
;
1769 return STATUS_SUCCESS
;
1773 * IoGetDriverObjectExtension
1780 IoGetDriverObjectExtension(
1781 PDRIVER_OBJECT DriverObject
,
1782 PVOID ClientIdentificationAddress
)
1785 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1787 OldIrql
= KeRaiseIrqlToDpcLevel();
1789 for (DriverExtensions
= DriverObject
->DriverSection
;
1790 DriverExtensions
!= NULL
&&
1791 DriverExtensions
->ClientIdentificationAddress
!=
1792 ClientIdentificationAddress
;
1793 DriverExtensions
= DriverExtensions
->Link
)
1796 KfLowerIrql(OldIrql
);
1798 if (DriverExtensions
== NULL
)
1801 return &DriverExtensions
->Extension
;