1 /* $Id: driver.c,v 1.56 2004/12/09 14:20:06 royce 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
;
34 } SERVICE_GROUP
, *PSERVICE_GROUP
;
36 typedef struct _SERVICE
38 LIST_ENTRY ServiceListEntry
;
39 UNICODE_STRING ServiceName
;
40 UNICODE_STRING RegistryPath
;
41 UNICODE_STRING ServiceGroup
;
42 UNICODE_STRING ImagePath
;
49 /* BOOLEAN ServiceRunning;*/ // needed ??
52 typedef struct _DRIVER_REINIT_ITEM
55 PDRIVER_OBJECT DriverObject
;
56 PDRIVER_REINITIALIZE ReinitRoutine
;
58 } DRIVER_REINIT_ITEM
, *PDRIVER_REINIT_ITEM
;
60 /* GLOBALS ********************************************************************/
62 static LIST_ENTRY DriverReinitListHead
;
63 static PLIST_ENTRY DriverReinitTailEntry
;
64 static KSPIN_LOCK DriverReinitListLock
;
66 static LIST_ENTRY GroupListHead
= {NULL
, NULL
};
67 static LIST_ENTRY ServiceListHead
= {NULL
, NULL
};
69 static UNICODE_STRING IopHardwareDatabaseKey
=
70 ROS_STRING_INITIALIZER(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
72 POBJECT_TYPE EXPORTED IoDriverObjectType
= NULL
;
74 #define TAG_DRIVER TAG('D', 'R', 'V', 'R')
75 #define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
77 /* DECLARATIONS ***************************************************************/
84 POBJECT_ATTRIBUTES ObjectAttributes
);
87 IopDeleteDriver(PVOID ObjectBody
);
89 /* PRIVATE FUNCTIONS **********************************************************/
92 IopInitDriverImplementation(VOID
)
94 /* Register the process object type */
95 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
96 IoDriverObjectType
->Tag
= TAG('D', 'R', 'V', 'R');
97 IoDriverObjectType
->TotalObjects
= 0;
98 IoDriverObjectType
->TotalHandles
= 0;
99 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
100 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
101 IoDriverObjectType
->PagedPoolCharge
= 0;
102 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(DRIVER_OBJECT
);
103 IoDriverObjectType
->Dump
= NULL
;
104 IoDriverObjectType
->Open
= NULL
;
105 IoDriverObjectType
->Close
= NULL
;
106 IoDriverObjectType
->Delete
= IopDeleteDriver
;
107 IoDriverObjectType
->Parse
= NULL
;
108 IoDriverObjectType
->Security
= NULL
;
109 IoDriverObjectType
->QueryName
= NULL
;
110 IoDriverObjectType
->OkayToClose
= NULL
;
111 IoDriverObjectType
->Create
= IopCreateDriver
;
112 IoDriverObjectType
->DuplicationNotify
= NULL
;
113 RtlRosInitUnicodeStringFromLiteral(&IoDriverObjectType
->TypeName
, L
"Driver");
115 ObpCreateTypeObject(IoDriverObjectType
);
117 InitializeListHead(&DriverReinitListHead
);
118 KeInitializeSpinLock(&DriverReinitListLock
);
119 DriverReinitTailEntry
= NULL
;
123 IopInvalidDeviceRequest(
124 PDEVICE_OBJECT DeviceObject
,
127 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
128 Irp
->IoStatus
.Information
= 0;
129 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
130 return STATUS_INVALID_DEVICE_REQUEST
;
138 POBJECT_ATTRIBUTES ObjectAttributes
)
140 PDRIVER_OBJECT Object
= ObjectBody
;
143 DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
144 ObjectBody
, Parent
, RemainingPath
);
146 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
147 return STATUS_UNSUCCESSFUL
;
149 /* Create driver extension */
150 Object
->DriverExtension
= (PDRIVER_EXTENSION
)
151 ExAllocatePoolWithTag(
153 sizeof(DRIVER_EXTENSION
),
154 TAG_DRIVER_EXTENSION
);
156 if (Object
->DriverExtension
== NULL
)
158 return STATUS_NO_MEMORY
;
161 RtlZeroMemory(Object
->DriverExtension
, sizeof(DRIVER_EXTENSION
));
163 Object
->Type
= InternalDriverType
;
165 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
166 Object
->MajorFunction
[i
] = IopInvalidDeviceRequest
;
168 Object
->HardwareDatabase
= &IopHardwareDatabaseKey
;
170 return STATUS_SUCCESS
;
174 IopDeleteDriver(PVOID ObjectBody
)
176 PDRIVER_OBJECT Object
= ObjectBody
;
178 PPRIVATE_DRIVER_EXTENSIONS DriverExtension
, NextDriverExtension
;
180 DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody
);
182 ExFreePool(Object
->DriverExtension
);
184 OldIrql
= KeRaiseIrqlToDpcLevel();
186 for (DriverExtension
= Object
->DriverSection
;
187 DriverExtension
!= NULL
;
188 DriverExtension
= NextDriverExtension
)
190 NextDriverExtension
= DriverExtension
->Link
;
191 ExFreePool(DriverExtension
);
194 KfLowerIrql(OldIrql
);
198 IopCreateDriverObject(
199 PDRIVER_OBJECT
*DriverObject
,
200 PUNICODE_STRING ServiceName
,
202 PVOID DriverImageStart
,
203 ULONG DriverImageSize
)
205 PDRIVER_OBJECT Object
;
206 WCHAR NameBuffer
[MAX_PATH
];
207 UNICODE_STRING DriverName
;
208 OBJECT_ATTRIBUTES ObjectAttributes
;
211 DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n",
212 DriverObject
, ServiceName
, FileSystem
, DriverImageStart
, DriverImageSize
);
214 *DriverObject
= NULL
;
216 /* Create ModuleName string */
217 if (ServiceName
!= NULL
&& ServiceName
->Buffer
!= NULL
)
219 if (FileSystem
== TRUE
)
220 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
222 wcscpy(NameBuffer
, DRIVER_ROOT_NAME
);
223 wcscat(NameBuffer
, ServiceName
->Buffer
);
225 RtlInitUnicodeString(&DriverName
, NameBuffer
);
226 DPRINT("Driver name: '%wZ'\n", &DriverName
);
230 RtlInitUnicodeString(&DriverName
, NULL
);
233 /* Initialize ObjectAttributes for driver object */
234 InitializeObjectAttributes(
241 /* Create driver object */
242 Status
= ObCreateObject(
248 sizeof(DRIVER_OBJECT
),
253 if (!NT_SUCCESS(Status
))
258 Object
->DriverStart
= DriverImageStart
;
259 Object
->DriverSize
= DriverImageSize
;
261 *DriverObject
= Object
;
263 return STATUS_SUCCESS
;
267 * IopDisplayLoadingMessage
269 * Display 'Loading XXX...' message.
273 IopDisplayLoadingMessage(PWCHAR ServiceName
)
275 CHAR TextBuffer
[256];
276 sprintf(TextBuffer
, "Loading %S...\n", ServiceName
);
277 HalDisplayString(TextBuffer
);
281 * IopNormalizeImagePath
283 * Normalize an image path to contain complete path.
287 * The input path and on exit the result path. ImagePath.Buffer
288 * must be allocated by ExAllocatePool on input. Caller is responsible
289 * for freeing the buffer when it's no longer needed.
292 * Name of the service that ImagePath belongs to.
298 * The input image path isn't freed on error.
302 IopNormalizeImagePath(
303 IN OUT PUNICODE_STRING ImagePath
,
304 IN PUNICODE_STRING ServiceName
)
306 UNICODE_STRING InputImagePath
;
311 sizeof(UNICODE_STRING
));
313 if (InputImagePath
.Length
== 0)
315 ImagePath
->Length
= (33 * sizeof(WCHAR
)) + ServiceName
->Length
;
316 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
317 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
318 if (ImagePath
->Buffer
== NULL
)
319 return STATUS_NO_MEMORY
;
321 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\system32\\drivers\\");
322 wcscat(ImagePath
->Buffer
, ServiceName
->Buffer
);
323 wcscat(ImagePath
->Buffer
, L
".sys");
325 if (InputImagePath
.Buffer
[0] != L
'\\')
327 ImagePath
->Length
= (12 * sizeof(WCHAR
)) + InputImagePath
.Length
;
328 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
329 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
330 if (ImagePath
->Buffer
== NULL
)
331 return STATUS_NO_MEMORY
;
333 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\");
334 wcscat(ImagePath
->Buffer
, InputImagePath
.Buffer
);
335 RtlFreeUnicodeString(&InputImagePath
);
338 return STATUS_SUCCESS
;
342 * IopLoadServiceModule
344 * Load a module specified by registry settings for service.
348 * Name of the service to load.
355 IopLoadServiceModule(
356 IN PUNICODE_STRING ServiceName
,
357 OUT PMODULE_OBJECT
*ModuleObject
)
359 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
361 UNICODE_STRING ServiceImagePath
;
364 DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName
, ModuleObject
);
367 * Get information about the service.
370 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
372 RtlInitUnicodeString(&ServiceImagePath
, NULL
);
374 QueryTable
[0].Name
= L
"Start";
375 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
376 QueryTable
[0].EntryContext
= &ServiceStart
;
378 QueryTable
[1].Name
= L
"ImagePath";
379 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
380 QueryTable
[1].EntryContext
= &ServiceImagePath
;
382 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
383 ServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
385 if (!NT_SUCCESS(Status
))
387 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
391 IopDisplayLoadingMessage(ServiceName
->Buffer
);
394 * Normalize the image path for all later processing.
397 Status
= IopNormalizeImagePath(&ServiceImagePath
, ServiceName
);
399 if (!NT_SUCCESS(Status
))
401 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
409 *ModuleObject
= LdrGetModuleObject(&ServiceImagePath
);
411 if (*ModuleObject
== NULL
)
413 Status
= STATUS_UNSUCCESSFUL
;
416 * Special case for boot modules that were loaded by boot loader.
419 if (ServiceStart
== 0)
422 CHAR SearchName
[256];
424 PLOADER_MODULE KeLoaderModules
=
425 (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
429 * Improve this searching algorithm by using the image name
430 * stored in registry entry ImageName and use the whole path
431 * (requires change in FreeLoader).
434 _snprintf(SearchName
, sizeof(SearchName
), "%wZ.sys", ServiceName
);
435 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
437 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
438 if (!_stricmp(ModuleName
, SearchName
))
440 DPRINT("Initializing boot module\n");
442 /* Tell, that the module is already loaded */
443 KeLoaderModules
[i
].Reserved
= 1;
445 Status
= LdrProcessModule(
446 (PVOID
)KeLoaderModules
[i
].ModStart
,
456 * Case for rest of the drivers (except disabled)
459 else if (ServiceStart
< 4)
461 DPRINT("Loading module\n");
462 Status
= LdrLoadModule(&ServiceImagePath
, ModuleObject
);
467 DPRINT("Module already loaded\n");
468 Status
= STATUS_SUCCESS
;
471 RtlFreeUnicodeString(&ServiceImagePath
);
474 * Now check if the module was loaded successfully.
477 if (!NT_SUCCESS(Status
))
479 DPRINT("Module loading failed (Status %x)\n", Status
);
482 DPRINT("Module loading (Status %x)\n", Status
);
488 * IopInitializeDriverModule
490 * Initalize a loaded driver.
494 * Pointer to device node.
497 * Module object representing the driver. It can be retrieve by
498 * IopLoadServiceModule.
501 * Set to TRUE for file system drivers.
504 * On successful return this contains the driver object representing
509 IopInitializeDriverModule(
510 IN PDEVICE_NODE DeviceNode
,
511 IN PMODULE_OBJECT ModuleObject
,
512 IN BOOLEAN FileSystemDriver
,
513 OUT PDRIVER_OBJECT
*DriverObject
)
515 UNICODE_STRING RegistryKey
;
516 PDRIVER_INITIALIZE DriverEntry
= ModuleObject
->EntryPoint
;
518 WCHAR ServicesKeyName
[] = L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
520 Status
= IopCreateDriverObject(
522 &DeviceNode
->ServiceName
,
525 ModuleObject
->Length
);
527 if (!NT_SUCCESS(Status
))
529 DPRINT("IopCreateDriverObject failed (Status %x)\n", Status
);
533 if (DeviceNode
->ServiceName
.Buffer
)
535 RegistryKey
.Length
= DeviceNode
->ServiceName
.Length
+
536 sizeof(ServicesKeyName
);
537 RegistryKey
.MaximumLength
= RegistryKey
.Length
+ sizeof(UNICODE_NULL
);
538 RegistryKey
.Buffer
= ExAllocatePool(PagedPool
, RegistryKey
.MaximumLength
);
539 wcscpy(RegistryKey
.Buffer
, ServicesKeyName
);
540 wcscat(RegistryKey
.Buffer
, DeviceNode
->ServiceName
.Buffer
);
544 RtlInitUnicodeString(&RegistryKey
, NULL
);
547 DPRINT("RegistryKey: %wZ\n", &RegistryKey
);
548 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry
);
550 IopMarkLastReinitializeDriver();
552 Status
= DriverEntry(*DriverObject
, &RegistryKey
);
553 if (!NT_SUCCESS(Status
))
555 ObMakeTemporaryObject(*DriverObject
);
556 ObDereferenceObject(*DriverObject
);
560 IopReinitializeDrivers();
562 return STATUS_SUCCESS
;
566 * IopAttachFilterDriversCallback
568 * Internal routine used by IopAttachFilterDrivers.
572 IopAttachFilterDriversCallback(
580 PDEVICE_NODE DeviceNode
= Context
;
581 UNICODE_STRING ServiceName
;
583 PMODULE_OBJECT ModuleObject
;
584 PDRIVER_OBJECT DriverObject
;
587 for (Filters
= ValueData
;
588 ((ULONG_PTR
)Filters
- (ULONG_PTR
)ValueData
) < ValueLength
&&
590 Filters
+= (ServiceName
.Length
/ sizeof(WCHAR
)) + 1)
592 DPRINT("Filter Driver: %S (%wZ)\n", Filters
, &DeviceNode
->InstancePath
);
593 ServiceName
.Buffer
= Filters
;
594 ServiceName
.MaximumLength
=
595 ServiceName
.Length
= wcslen(Filters
) * sizeof(WCHAR
);
597 /* Load and initialize the filter driver */
598 Status
= IopLoadServiceModule(&ServiceName
, &ModuleObject
);
599 if (!NT_SUCCESS(Status
))
602 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
603 if (!NT_SUCCESS(Status
))
606 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
607 if (!NT_SUCCESS(Status
))
611 return STATUS_SUCCESS
;
615 * IopAttachFilterDrivers
617 * Load filter drivers for specified device node.
621 * Set to TRUE for loading lower level filters or FALSE for upper
626 IopAttachFilterDrivers(
627 PDEVICE_NODE DeviceNode
,
630 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
632 UNICODE_STRING Class
;
633 WCHAR ClassBuffer
[40];
637 * First load the device filters
640 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
642 QueryTable
[0].Name
= L
"LowerFilters";
644 QueryTable
[0].Name
= L
"UpperFilters";
645 QueryTable
[0].EntryContext
= NULL
;
646 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
647 QueryTable
[1].QueryRoutine
= NULL
;
648 QueryTable
[1].Name
= NULL
;
650 KeyBuffer
= ExAllocatePool(
652 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
653 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
654 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
656 RtlQueryRegistryValues(
657 RTL_REGISTRY_ABSOLUTE
,
664 * Now get the class GUID
668 Class
.MaximumLength
= 40 * sizeof(WCHAR
);
669 Class
.Buffer
= ClassBuffer
;
670 QueryTable
[0].QueryRoutine
= NULL
;
671 QueryTable
[0].Name
= L
"ClassGUID";
672 QueryTable
[0].EntryContext
= &Class
;
673 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
675 Status
= RtlQueryRegistryValues(
676 RTL_REGISTRY_ABSOLUTE
,
682 ExFreePool(KeyBuffer
);
685 * Load the class filter driver
688 if (NT_SUCCESS(Status
))
690 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
692 QueryTable
[0].Name
= L
"LowerFilters";
694 QueryTable
[0].Name
= L
"UpperFilters";
695 QueryTable
[0].EntryContext
= NULL
;
696 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
698 KeyBuffer
= ExAllocatePool(PagedPool
, (58 * sizeof(WCHAR
)) + Class
.Length
);
699 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
700 wcscat(KeyBuffer
, ClassBuffer
);
702 RtlQueryRegistryValues(
703 RTL_REGISTRY_ABSOLUTE
,
709 ExFreePool(KeyBuffer
);
712 return STATUS_SUCCESS
;
715 static NTSTATUS STDCALL
716 IopGetGroupOrderList(PWSTR ValueName
,
723 PSERVICE_GROUP Group
;
725 DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
726 ValueName
, ValueType
, ValueData
, ValueLength
, Context
, EntryContext
);
728 if (ValueType
== REG_BINARY
&&
730 ValueLength
>= sizeof(DWORD
) &&
731 ValueLength
>= (*(PULONG
)ValueData
+ 1) * sizeof(DWORD
))
733 Group
= (PSERVICE_GROUP
)Context
;
734 Group
->TagCount
= ((PULONG
)ValueData
)[0];
735 if (Group
->TagCount
> 0)
737 if (ValueLength
>= (Group
->TagCount
+ 1) * sizeof(DWORD
))
739 Group
->TagArray
= ExAllocatePool(NonPagedPool
, Group
->TagCount
* sizeof(DWORD
));
740 if (Group
->TagArray
== NULL
)
743 return STATUS_INSUFFICIENT_RESOURCES
;
745 memcpy(Group
->TagArray
, (PULONG
)ValueData
+ 1, Group
->TagCount
* sizeof(DWORD
));
750 return STATUS_UNSUCCESSFUL
;
754 return STATUS_SUCCESS
;
757 static NTSTATUS STDCALL
758 IopCreateGroupListEntry(PWSTR ValueName
,
765 PSERVICE_GROUP Group
;
766 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
770 if (ValueType
== REG_SZ
)
772 DPRINT("GroupName: '%S'\n", (PWCHAR
)ValueData
);
774 Group
= ExAllocatePool(NonPagedPool
,
775 sizeof(SERVICE_GROUP
));
778 return(STATUS_INSUFFICIENT_RESOURCES
);
781 RtlZeroMemory(Group
, sizeof(SERVICE_GROUP
));
783 if (!RtlCreateUnicodeString(&Group
->GroupName
,
787 return(STATUS_INSUFFICIENT_RESOURCES
);
790 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
791 QueryTable
[0].Name
= (PWSTR
)ValueData
;
792 QueryTable
[0].QueryRoutine
= IopGetGroupOrderList
;
794 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
799 DPRINT("%x %d %S\n", Status
, Group
->TagCount
, (PWSTR
)ValueData
);
801 InsertTailList(&GroupListHead
,
802 &Group
->GroupListEntry
);
805 return(STATUS_SUCCESS
);
809 static NTSTATUS STDCALL
810 IopCreateServiceListEntry(PUNICODE_STRING ServiceName
)
812 RTL_QUERY_REGISTRY_TABLE QueryTable
[7];
816 DPRINT("ServiceName: '%wZ'\n", ServiceName
);
818 /* Allocate service entry */
819 Service
= (PSERVICE
)ExAllocatePool(NonPagedPool
, sizeof(SERVICE
));
822 DPRINT1("ExAllocatePool() failed\n");
823 return(STATUS_INSUFFICIENT_RESOURCES
);
825 RtlZeroMemory(Service
, sizeof(SERVICE
));
827 /* Get service data */
828 RtlZeroMemory(&QueryTable
,
831 QueryTable
[0].Name
= L
"Start";
832 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
833 QueryTable
[0].EntryContext
= &Service
->Start
;
835 QueryTable
[1].Name
= L
"Type";
836 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
837 QueryTable
[1].EntryContext
= &Service
->Type
;
839 QueryTable
[2].Name
= L
"ErrorControl";
840 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
841 QueryTable
[2].EntryContext
= &Service
->ErrorControl
;
843 QueryTable
[3].Name
= L
"Group";
844 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
845 QueryTable
[3].EntryContext
= &Service
->ServiceGroup
;
847 QueryTable
[4].Name
= L
"ImagePath";
848 QueryTable
[4].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
849 QueryTable
[4].EntryContext
= &Service
->ImagePath
;
851 QueryTable
[5].Name
= L
"Tag";
852 QueryTable
[5].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
853 QueryTable
[5].EntryContext
= &Service
->Tag
;
855 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
860 if (!NT_SUCCESS(Status
) || Service
->Start
> 1)
862 RtlFreeUnicodeString(&Service
->ServiceGroup
);
863 RtlFreeUnicodeString(&Service
->ImagePath
);
868 /* Copy service name */
869 Service
->ServiceName
.Length
= ServiceName
->Length
;
870 Service
->ServiceName
.MaximumLength
= ServiceName
->Length
+ sizeof(WCHAR
);
871 Service
->ServiceName
.Buffer
= ExAllocatePool(NonPagedPool
,
872 Service
->ServiceName
.MaximumLength
);
873 RtlCopyMemory(Service
->ServiceName
.Buffer
,
875 ServiceName
->Length
);
876 Service
->ServiceName
.Buffer
[ServiceName
->Length
/ sizeof(WCHAR
)] = 0;
878 /* Build registry path */
879 Service
->RegistryPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
880 Service
->RegistryPath
.Buffer
= ExAllocatePool(NonPagedPool
,
881 MAX_PATH
* sizeof(WCHAR
));
882 wcscpy(Service
->RegistryPath
.Buffer
,
883 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
884 wcscat(Service
->RegistryPath
.Buffer
,
885 Service
->ServiceName
.Buffer
);
886 Service
->RegistryPath
.Length
= wcslen(Service
->RegistryPath
.Buffer
) * sizeof(WCHAR
);
888 DPRINT("ServiceName: '%wZ'\n", &Service
->ServiceName
);
889 DPRINT("RegistryPath: '%wZ'\n", &Service
->RegistryPath
);
890 DPRINT("ServiceGroup: '%wZ'\n", &Service
->ServiceGroup
);
891 DPRINT("ImagePath: '%wZ'\n", &Service
->ImagePath
);
892 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
893 Service
->Start
, Service
->Type
, Service
->Tag
, Service
->ErrorControl
);
895 /* Append service entry */
896 InsertTailList(&ServiceListHead
,
897 &Service
->ServiceListEntry
);
899 return(STATUS_SUCCESS
);
903 NTSTATUS INIT_FUNCTION
904 IoCreateDriverList(VOID
)
906 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
907 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
908 OBJECT_ATTRIBUTES ObjectAttributes
;
909 UNICODE_STRING ServicesKeyName
;
910 UNICODE_STRING SubKeyName
;
915 ULONG KeyInfoLength
= 0;
916 ULONG ReturnedLength
;
918 DPRINT("IoCreateDriverList() called\n");
920 /* Initialize basic variables */
921 InitializeListHead(&GroupListHead
);
922 InitializeListHead(&ServiceListHead
);
924 /* Build group order list */
925 RtlZeroMemory(&QueryTable
,
928 QueryTable
[0].Name
= L
"List";
929 QueryTable
[0].QueryRoutine
= IopCreateGroupListEntry
;
931 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
932 L
"ServiceGroupOrder",
936 if (!NT_SUCCESS(Status
))
939 /* Enumerate services and create the service list */
940 RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName
,
941 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
943 InitializeObjectAttributes(&ObjectAttributes
,
945 OBJ_CASE_INSENSITIVE
,
949 Status
= NtOpenKey(&KeyHandle
,
952 if (!NT_SUCCESS(Status
))
957 KeyInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
958 KeyInfo
= ExAllocatePool(NonPagedPool
, KeyInfoLength
);
962 return(STATUS_INSUFFICIENT_RESOURCES
);
968 Status
= NtEnumerateKey(KeyHandle
,
974 if (NT_SUCCESS(Status
))
976 if (KeyInfo
->NameLength
< MAX_PATH
* sizeof(WCHAR
))
979 SubKeyName
.Length
= KeyInfo
->NameLength
;
980 SubKeyName
.MaximumLength
= KeyInfo
->NameLength
+ sizeof(WCHAR
);
981 SubKeyName
.Buffer
= KeyInfo
->Name
;
982 SubKeyName
.Buffer
[SubKeyName
.Length
/ sizeof(WCHAR
)] = 0;
984 DPRINT("KeyName: '%wZ'\n", &SubKeyName
);
985 IopCreateServiceListEntry(&SubKeyName
);
989 if (!NT_SUCCESS(Status
))
998 DPRINT("IoCreateDriverList() done\n");
1000 return(STATUS_SUCCESS
);
1003 NTSTATUS INIT_FUNCTION
1004 IoDestroyDriverList(VOID
)
1006 PLIST_ENTRY GroupEntry
;
1007 PLIST_ENTRY ServiceEntry
;
1008 PSERVICE_GROUP CurrentGroup
;
1009 PSERVICE CurrentService
;
1011 DPRINT("IoDestroyDriverList() called\n");
1013 /* Destroy group list */
1014 GroupEntry
= GroupListHead
.Flink
;
1015 while (GroupEntry
!= &GroupListHead
)
1017 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1019 RtlFreeUnicodeString(&CurrentGroup
->GroupName
);
1020 RemoveEntryList(GroupEntry
);
1021 if (CurrentGroup
->TagArray
)
1023 ExFreePool(CurrentGroup
->TagArray
);
1025 ExFreePool(CurrentGroup
);
1027 GroupEntry
= GroupListHead
.Flink
;
1030 /* Destroy service list */
1031 ServiceEntry
= ServiceListHead
.Flink
;
1032 while (ServiceEntry
!= &ServiceListHead
)
1034 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1036 RtlFreeUnicodeString(&CurrentService
->ServiceName
);
1037 RtlFreeUnicodeString(&CurrentService
->RegistryPath
);
1038 RtlFreeUnicodeString(&CurrentService
->ServiceGroup
);
1039 RtlFreeUnicodeString(&CurrentService
->ImagePath
);
1040 RemoveEntryList(ServiceEntry
);
1041 ExFreePool(CurrentService
);
1043 ServiceEntry
= ServiceListHead
.Flink
;
1046 DPRINT("IoDestroyDriverList() done\n");
1048 return(STATUS_SUCCESS
);
1051 VOID STATIC INIT_FUNCTION
1052 MiFreeBootDriverMemory(PVOID StartAddress
, ULONG Length
)
1056 for (i
= 0; i
< PAGE_ROUND_UP(Length
) / PAGE_SIZE
; i
++)
1058 MmDeleteVirtualMapping(NULL
, (char*)StartAddress
+ i
* PAGE_SIZE
, TRUE
, NULL
, NULL
);
1063 * IopInitializeBuiltinDriver
1065 * Initialize a driver that is already loaded in memory.
1068 NTSTATUS FASTCALL INIT_FUNCTION
1069 IopInitializeBuiltinDriver(
1070 PDEVICE_NODE ModuleDeviceNode
,
1071 PVOID ModuleLoadBase
,
1075 PMODULE_OBJECT ModuleObject
;
1076 PDEVICE_NODE DeviceNode
;
1077 PDRIVER_OBJECT DriverObject
;
1079 CHAR TextBuffer
[256];
1080 PCHAR FileNameWithoutPath
;
1081 LPWSTR FileExtension
;
1083 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1084 FileName
, ModuleLoadBase
, ModuleLength
);
1087 * Display 'Initializing XXX...' message
1090 sprintf(TextBuffer
, "Initializing %s...\n", FileName
);
1091 HalDisplayString(TextBuffer
);
1094 * Determine the right device object
1097 if (ModuleDeviceNode
== NULL
)
1099 /* Use IopRootDeviceNode for now */
1100 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1101 if (!NT_SUCCESS(Status
))
1103 CPRINT("Driver load failed, status (%x)\n", Status
);
1108 DeviceNode
= ModuleDeviceNode
;
1112 * Generate filename without path (not needed by freeldr)
1115 FileNameWithoutPath
= strrchr(FileName
, '\\');
1116 if (FileNameWithoutPath
== NULL
)
1118 FileNameWithoutPath
= FileName
;
1125 RtlCreateUnicodeStringFromAsciiz(&DeviceNode
->ServiceName
,
1126 FileNameWithoutPath
);
1127 Status
= LdrProcessModule(ModuleLoadBase
, &DeviceNode
->ServiceName
,
1129 if (ModuleObject
== NULL
)
1131 if (ModuleDeviceNode
== NULL
)
1132 IopFreeDeviceNode(DeviceNode
);
1133 CPRINT("Driver load failed, status (%x)\n", Status
);
1134 return STATUS_UNSUCCESSFUL
;
1138 * Strip the file extension from ServiceName
1141 FileExtension
= wcsrchr(DeviceNode
->ServiceName
.Buffer
, '.');
1142 if (FileExtension
!= NULL
)
1144 DeviceNode
->ServiceName
.Length
-= wcslen(FileExtension
) * sizeof(WCHAR
);
1145 FileExtension
[0] = 0;
1149 * Initialize the driver
1152 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
,
1155 if (!NT_SUCCESS(Status
))
1157 if (ModuleDeviceNode
== NULL
)
1158 IopFreeDeviceNode(DeviceNode
);
1159 CPRINT("Driver load failed, status (%x)\n", Status
);
1163 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1169 * IopInitializeBootDrivers
1171 * Initialize boot drivers and free memory for boot files.
1181 IopInitializeBootDrivers(VOID
)
1183 ULONG BootDriverCount
;
1189 PLOADER_MODULE KeLoaderModules
= (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
1191 UNICODE_STRING DriverName
;
1194 DPRINT("IopInitializeBootDrivers()\n");
1196 BootDriverCount
= 0;
1197 for (i
= 0; i
< KeLoaderBlock
.ModsCount
; i
++)
1199 ModuleStart
= KeLoaderModules
[i
].ModStart
;
1200 ModuleSize
= KeLoaderModules
[i
].ModEnd
- ModuleStart
;
1201 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
1202 ModuleLoaded
= KeLoaderModules
[i
].Reserved
;
1203 Extension
= strrchr(ModuleName
, '.');
1204 if (Extension
== NULL
)
1207 if (!_stricmp(Extension
, ".sym"))
1209 /* Pass symbol files to kernel debugger */
1210 KDB_SYMBOLFILE_HOOK((PVOID
)ModuleStart
, ModuleName
, ModuleSize
);
1212 else if (!_stricmp(Extension
, ".exe") || !_stricmp(Extension
, ".dll"))
1214 /* Log *.exe and *.dll files */
1215 RtlCreateUnicodeStringFromAsciiz(&DriverName
, ModuleName
);
1216 IopBootLog(&DriverName
, TRUE
);
1217 RtlFreeUnicodeString(&DriverName
);
1219 else if (!_stricmp(Extension
, ".sys"))
1221 /* Initialize and log boot start driver */
1224 Status
= IopInitializeBuiltinDriver(NULL
,
1228 RtlCreateUnicodeStringFromAsciiz(&DriverName
, ModuleName
);
1229 IopBootLog(&DriverName
, NT_SUCCESS(Status
) ? TRUE
: FALSE
);
1230 RtlFreeUnicodeString(&DriverName
);
1236 * Free memory for all boot files, except ntoskrnl.exe, hal.dll
1237 * and symbol files, if the kernel debugger is active
1239 if (_stricmp(Extension
, ".exe") && _stricmp(Extension
, ".dll")
1240 #if defined(DBG) || defined(KDBG)
1241 && _stricmp(Extension
, ".sym")
1245 MiFreeBootDriverMemory((PVOID
)KeLoaderModules
[i
].ModStart
,
1246 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
1250 if (BootDriverCount
== 0)
1252 DbgPrint("No boot drivers available.\n");
1257 static INIT_FUNCTION NTSTATUS
1258 IopLoadDriver(PSERVICE Service
)
1260 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1262 IopDisplayLoadingMessage(Service
->ServiceName
.Buffer
);
1263 Status
= NtLoadDriver(&Service
->RegistryPath
);
1264 IopBootLog(&Service
->ImagePath
, NT_SUCCESS(Status
) ? TRUE
: FALSE
);
1265 if (!NT_SUCCESS(Status
))
1267 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status
);
1269 if (Service
->ErrorControl
== 1)
1273 else if (Service
->ErrorControl
== 2)
1275 if (IsLastKnownGood
== FALSE
)
1277 /* Boot last known good configuration */
1280 else if (Service
->ErrorControl
== 3)
1282 if (IsLastKnownGood
== FALSE
)
1284 /* Boot last known good configuration */
1298 * IopInitializeSystemDrivers
1300 * Load drivers marked as system start.
1310 IopInitializeSystemDrivers(VOID
)
1312 PLIST_ENTRY GroupEntry
;
1313 PLIST_ENTRY ServiceEntry
;
1314 PSERVICE_GROUP CurrentGroup
;
1315 PSERVICE CurrentService
;
1319 DPRINT("IopInitializeSystemDrivers()\n");
1321 GroupEntry
= GroupListHead
.Flink
;
1322 while (GroupEntry
!= &GroupListHead
)
1324 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1326 DPRINT("Group: %wZ\n", &CurrentGroup
->GroupName
);
1328 /* Load all drivers with a valid tag */
1329 for (i
= 0; i
< CurrentGroup
->TagCount
; i
++)
1331 ServiceEntry
= ServiceListHead
.Flink
;
1332 while (ServiceEntry
!= &ServiceListHead
)
1334 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1336 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1337 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1338 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/) &&
1339 (CurrentService
->Tag
== CurrentGroup
->TagArray
[i
]))
1341 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1342 Status
= IopLoadDriver(CurrentService
);
1344 ServiceEntry
= ServiceEntry
->Flink
;
1348 /* Load all drivers without a tag or with an invalid tag */
1349 ServiceEntry
= ServiceListHead
.Flink
;
1350 while (ServiceEntry
!= &ServiceListHead
)
1352 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1353 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1354 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1355 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/))
1357 for (i
= 0; i
< CurrentGroup
->TagCount
; i
++)
1359 if (CurrentGroup
->TagArray
[i
] == CurrentService
->Tag
)
1364 if (i
>= CurrentGroup
->TagCount
)
1366 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1367 Status
= IopLoadDriver(CurrentService
);
1370 ServiceEntry
= ServiceEntry
->Flink
;
1373 GroupEntry
= GroupEntry
->Flink
;
1376 DPRINT("IopInitializeSystemDrivers() done\n");
1382 * Unloads a device driver.
1386 * Name of the service to unload (registry key).
1389 * Whether to unload Plug & Plug or only legacy drivers. If this
1390 * parameter is set to FALSE, the routine will unload only legacy
1397 * Guard the whole function by SEH.
1401 IopUnloadDriver(PUNICODE_STRING DriverServiceName
, BOOLEAN UnloadPnpDrivers
)
1403 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1404 UNICODE_STRING ImagePath
;
1405 UNICODE_STRING ServiceName
;
1406 UNICODE_STRING ObjectName
;
1407 PDRIVER_OBJECT DriverObject
;
1408 PMODULE_OBJECT ModuleObject
;
1412 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName
, UnloadPnpDrivers
);
1415 * Get the service name from the registry key name
1418 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1420 Start
= DriverServiceName
->Buffer
;
1424 RtlInitUnicodeString(&ServiceName
, Start
);
1427 * Construct the driver object name
1430 ObjectName
.Length
= (wcslen(Start
) + 8) * sizeof(WCHAR
);
1431 ObjectName
.MaximumLength
= ObjectName
.Length
+ sizeof(WCHAR
);
1432 ObjectName
.Buffer
= ExAllocatePool(NonPagedPool
, ObjectName
.MaximumLength
);
1433 wcscpy(ObjectName
.Buffer
, L
"\\Driver\\");
1434 memcpy(ObjectName
.Buffer
+ 8, Start
, (ObjectName
.Length
- 8) * sizeof(WCHAR
));
1435 ObjectName
.Buffer
[ObjectName
.Length
/sizeof(WCHAR
)] = 0;
1438 * Find the driver object
1441 Status
= ObReferenceObjectByName(&ObjectName
, 0, 0, 0, IoDriverObjectType
,
1442 KernelMode
, 0, (PVOID
*)&DriverObject
);
1444 if (!NT_SUCCESS(Status
))
1446 DPRINT("Can't locate driver object for %wZ\n", ObjectName
);
1451 * Free the buffer for driver object name
1454 ExFreePool(ObjectName
.Buffer
);
1457 * Get path of service...
1460 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1462 RtlInitUnicodeString(&ImagePath
, NULL
);
1464 QueryTable
[0].Name
= L
"ImagePath";
1465 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1466 QueryTable
[0].EntryContext
= &ImagePath
;
1468 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1469 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1471 if (!NT_SUCCESS(Status
))
1473 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1478 * Normalize the image path for all later processing.
1481 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1483 if (!NT_SUCCESS(Status
))
1485 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1490 * ... and check if it's loaded
1493 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1494 if (ModuleObject
== NULL
)
1496 return STATUS_UNSUCCESSFUL
;
1500 * Free the service path
1503 RtlFreeUnicodeString(&ImagePath
);
1506 * Unload the module and release the references to the device object
1509 if (DriverObject
->DriverUnload
)
1510 (*DriverObject
->DriverUnload
)(DriverObject
);
1511 ObDereferenceObject(DriverObject
);
1512 ObDereferenceObject(DriverObject
);
1513 LdrUnloadModule(ModuleObject
);
1515 return STATUS_SUCCESS
;
1519 IopMarkLastReinitializeDriver(VOID
)
1523 KeAcquireSpinLock(&DriverReinitListLock
,
1526 if (IsListEmpty(&DriverReinitListHead
))
1528 DriverReinitTailEntry
= NULL
;
1532 DriverReinitTailEntry
= DriverReinitListHead
.Blink
;
1535 KeReleaseSpinLock(&DriverReinitListLock
,
1541 IopReinitializeDrivers(VOID
)
1543 PDRIVER_REINIT_ITEM ReinitItem
;
1547 KeAcquireSpinLock(&DriverReinitListLock
,
1550 if (DriverReinitTailEntry
== NULL
)
1552 KeReleaseSpinLock(&DriverReinitListLock
,
1557 KeReleaseSpinLock(&DriverReinitListLock
,
1562 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1563 &DriverReinitListLock
);
1567 ReinitItem
= (PDRIVER_REINIT_ITEM
)CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1569 /* Increment reinitialization counter */
1570 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1572 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1573 ReinitItem
->Context
,
1574 ReinitItem
->DriverObject
->DriverExtension
->Count
);
1578 if (Entry
== DriverReinitTailEntry
)
1583 /* PUBLIC FUNCTIONS ***********************************************************/
1592 IN PUNICODE_STRING DriverName
, OPTIONAL
1593 IN PDRIVER_INITIALIZE InitializationFunction
1597 return STATUS_NOT_IMPLEMENTED
;
1606 IN PDRIVER_OBJECT DriverObject
1616 * Loads a device driver.
1620 * Name of the service to load (registry key).
1630 NtLoadDriver(IN PUNICODE_STRING DriverServiceName
)
1632 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1633 UNICODE_STRING ImagePath
;
1634 UNICODE_STRING ServiceName
;
1637 PDEVICE_NODE DeviceNode
;
1638 PMODULE_OBJECT ModuleObject
;
1639 PDRIVER_OBJECT DriverObject
;
1642 DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName
);
1645 * Check security privileges
1648 /* FIXME: Uncomment when privileges will be correctly implemented. */
1650 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, KeGetPreviousMode()))
1652 DPRINT("Privilege not held\n");
1653 return STATUS_PRIVILEGE_NOT_HELD
;
1657 RtlInitUnicodeString(&ImagePath
, NULL
);
1660 * Get the service name from the registry key name.
1663 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1665 Start
= DriverServiceName
->Buffer
;
1669 RtlInitUnicodeString(&ServiceName
, Start
);
1675 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
1677 RtlInitUnicodeString(&ImagePath
, NULL
);
1679 QueryTable
[0].Name
= L
"Type";
1680 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1681 QueryTable
[0].EntryContext
= &Type
;
1683 QueryTable
[1].Name
= L
"ImagePath";
1684 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1685 QueryTable
[1].EntryContext
= &ImagePath
;
1687 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1688 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1690 if (!NT_SUCCESS(Status
))
1692 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
1693 RtlFreeUnicodeString(&ImagePath
);
1698 * Normalize the image path for all later processing.
1701 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1703 if (!NT_SUCCESS(Status
))
1705 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1709 DPRINT("FullImagePath: '%S'\n", ImagePath
.Buffer
);
1710 DPRINT("Type: %lx\n", Type
);
1713 * See, if the driver module isn't already loaded
1716 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1717 if (ModuleObject
!= NULL
)
1719 DPRINT("Image already loaded\n");
1720 return STATUS_IMAGE_ALREADY_LOADED
;
1724 * Create device node
1727 /* Use IopRootDeviceNode for now */
1728 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1730 if (!NT_SUCCESS(Status
))
1732 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status
);
1737 * Load the driver module
1740 Status
= LdrLoadModule(&ImagePath
, &ModuleObject
);
1742 if (!NT_SUCCESS(Status
))
1744 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status
);
1745 IopFreeDeviceNode(DeviceNode
);
1750 * Set a service name for the device node
1753 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1755 Start
= DriverServiceName
->Buffer
;
1758 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, Start
);
1761 * Initialize the driver module
1764 Status
= IopInitializeDriverModule(
1767 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1768 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */),
1771 if (!NT_SUCCESS(Status
))
1773 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status
);
1774 LdrUnloadModule(ModuleObject
);
1775 IopFreeDeviceNode(DeviceNode
);
1779 IopInitializeDevice(DeviceNode
, DriverObject
);
1787 * Unloads a legacy device driver.
1791 * Name of the service to unload (registry key).
1801 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName
)
1803 return IopUnloadDriver(DriverServiceName
, FALSE
);
1807 * IoRegisterDriverReinitialization
1814 IoRegisterDriverReinitialization(
1815 PDRIVER_OBJECT DriverObject
,
1816 PDRIVER_REINITIALIZE ReinitRoutine
,
1819 PDRIVER_REINIT_ITEM ReinitItem
;
1821 ReinitItem
= ExAllocatePool(NonPagedPool
, sizeof(DRIVER_REINIT_ITEM
));
1822 if (ReinitItem
== NULL
)
1825 ReinitItem
->DriverObject
= DriverObject
;
1826 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1827 ReinitItem
->Context
= Context
;
1829 ExInterlockedInsertTailList(
1830 &DriverReinitListHead
,
1831 &ReinitItem
->ItemEntry
,
1832 &DriverReinitListLock
);
1836 * IoAllocateDriverObjectExtension
1843 IoAllocateDriverObjectExtension(
1844 PDRIVER_OBJECT DriverObject
,
1845 PVOID ClientIdentificationAddress
,
1846 ULONG DriverObjectExtensionSize
,
1847 PVOID
*DriverObjectExtension
)
1850 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1851 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension
;
1853 NewDriverExtension
= ExAllocatePoolWithTag(
1855 sizeof(PRIVATE_DRIVER_EXTENSIONS
) - sizeof(CHAR
) +
1856 DriverObjectExtensionSize
,
1857 TAG_DRIVER_EXTENSION
);
1859 if (NewDriverExtension
== NULL
)
1861 return STATUS_INSUFFICIENT_RESOURCES
;
1864 OldIrql
= KeRaiseIrqlToDpcLevel();
1866 NewDriverExtension
->Link
= DriverObject
->DriverSection
;
1867 NewDriverExtension
->ClientIdentificationAddress
= ClientIdentificationAddress
;
1869 for (DriverExtensions
= DriverObject
->DriverSection
;
1870 DriverExtensions
!= NULL
;
1871 DriverExtensions
= DriverExtensions
->Link
)
1873 if (DriverExtensions
->ClientIdentificationAddress
==
1874 ClientIdentificationAddress
)
1876 KfLowerIrql(OldIrql
);
1877 return STATUS_OBJECT_NAME_COLLISION
;
1881 DriverObject
->DriverSection
= NewDriverExtension
;
1883 KfLowerIrql(OldIrql
);
1885 *DriverObjectExtension
= &NewDriverExtension
->Extension
;
1887 return STATUS_SUCCESS
;
1891 * IoGetDriverObjectExtension
1898 IoGetDriverObjectExtension(
1899 PDRIVER_OBJECT DriverObject
,
1900 PVOID ClientIdentificationAddress
)
1903 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1905 OldIrql
= KeRaiseIrqlToDpcLevel();
1907 for (DriverExtensions
= DriverObject
->DriverSection
;
1908 DriverExtensions
!= NULL
&&
1909 DriverExtensions
->ClientIdentificationAddress
!=
1910 ClientIdentificationAddress
;
1911 DriverExtensions
= DriverExtensions
->Link
)
1914 KfLowerIrql(OldIrql
);
1916 if (DriverExtensions
== NULL
)
1919 return &DriverExtensions
->Extension
;