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
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 * Filip Navara (xnavara@volny.cz)
12 /* INCLUDES *******************************************************************/
16 #include <internal/debug.h>
19 extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
20 extern ULONG KeTickCount
;
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
->PeakObjects
= 0;
100 IoDriverObjectType
->PeakHandles
= 0;
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 RtlInitUnicodeString(&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
= IO_TYPE_DRIVER
;
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
);
183 RtlFreeUnicodeString(&Object
->DriverName
);
185 OldIrql
= KeRaiseIrqlToDpcLevel();
187 for (DriverExtension
= Object
->DriverSection
;
188 DriverExtension
!= NULL
;
189 DriverExtension
= NextDriverExtension
)
191 NextDriverExtension
= DriverExtension
->Link
;
192 ExFreePool(DriverExtension
);
195 KfLowerIrql(OldIrql
);
199 IopCreateDriverObject(
200 PDRIVER_OBJECT
*DriverObject
,
201 PUNICODE_STRING ServiceName
,
203 PVOID DriverImageStart
,
204 ULONG DriverImageSize
)
206 PDRIVER_OBJECT Object
;
207 WCHAR NameBuffer
[MAX_PATH
];
208 UNICODE_STRING DriverName
;
209 OBJECT_ATTRIBUTES ObjectAttributes
;
213 DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n",
214 DriverObject
, ServiceName
, FileSystem
, DriverImageStart
, DriverImageSize
);
216 *DriverObject
= NULL
;
218 /* Create ModuleName string */
219 if (ServiceName
!= NULL
&& ServiceName
->Buffer
!= NULL
)
221 if (FileSystem
== TRUE
)
222 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
224 wcscpy(NameBuffer
, DRIVER_ROOT_NAME
);
225 wcscat(NameBuffer
, ServiceName
->Buffer
);
227 RtlInitUnicodeString(&DriverName
, NameBuffer
);
228 DPRINT("Driver name: '%wZ'\n", &DriverName
);
230 Buffer
= (PWSTR
)ExAllocatePool(NonPagedPool
, DriverName
.Length
);
231 /* If we don't success, it is not a problem. Our driver
232 * object will not have associated driver name... */
236 RtlInitUnicodeString(&DriverName
, NULL
);
239 /* Initialize ObjectAttributes for driver object */
240 InitializeObjectAttributes(
247 /* Create driver object */
248 Status
= ObCreateObject(
254 sizeof(DRIVER_OBJECT
),
259 if (!NT_SUCCESS(Status
))
264 Object
->DriverStart
= DriverImageStart
;
265 Object
->DriverSize
= DriverImageSize
;
268 Object
->DriverName
.Buffer
= Buffer
;
269 Object
->DriverName
.Length
= Object
->DriverName
.MaximumLength
= DriverName
.Length
;
270 RtlCopyMemory(Object
->DriverName
.Buffer
, DriverName
.Buffer
, DriverName
.Length
);
273 *DriverObject
= Object
;
275 return STATUS_SUCCESS
;
279 * IopDisplayLoadingMessage
281 * Display 'Loading XXX...' message.
285 IopDisplayLoadingMessage(PWCHAR ServiceName
)
287 CHAR TextBuffer
[256];
288 sprintf(TextBuffer
, "Loading %S...\n", ServiceName
);
289 HalDisplayString(TextBuffer
);
293 * IopNormalizeImagePath
295 * Normalize an image path to contain complete path.
299 * The input path and on exit the result path. ImagePath.Buffer
300 * must be allocated by ExAllocatePool on input. Caller is responsible
301 * for freeing the buffer when it's no longer needed.
304 * Name of the service that ImagePath belongs to.
310 * The input image path isn't freed on error.
314 IopNormalizeImagePath(
315 IN OUT PUNICODE_STRING ImagePath
,
316 IN PUNICODE_STRING ServiceName
)
318 UNICODE_STRING InputImagePath
;
323 sizeof(UNICODE_STRING
));
325 if (InputImagePath
.Length
== 0)
327 ImagePath
->Length
= (33 * sizeof(WCHAR
)) + ServiceName
->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\\system32\\drivers\\");
334 wcscat(ImagePath
->Buffer
, ServiceName
->Buffer
);
335 wcscat(ImagePath
->Buffer
, L
".sys");
337 if (InputImagePath
.Buffer
[0] != L
'\\')
339 ImagePath
->Length
= (12 * sizeof(WCHAR
)) + InputImagePath
.Length
;
340 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
341 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
342 if (ImagePath
->Buffer
== NULL
)
343 return STATUS_NO_MEMORY
;
345 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\");
346 wcscat(ImagePath
->Buffer
, InputImagePath
.Buffer
);
347 RtlFreeUnicodeString(&InputImagePath
);
350 return STATUS_SUCCESS
;
354 * IopLoadServiceModule
356 * Load a module specified by registry settings for service.
360 * Name of the service to load.
367 IopLoadServiceModule(
368 IN PUNICODE_STRING ServiceName
,
369 OUT PMODULE_OBJECT
*ModuleObject
)
371 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
373 UNICODE_STRING ServiceImagePath
;
376 DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName
, ModuleObject
);
379 * Get information about the service.
382 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
384 RtlInitUnicodeString(&ServiceImagePath
, NULL
);
386 QueryTable
[0].Name
= L
"Start";
387 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
388 QueryTable
[0].EntryContext
= &ServiceStart
;
390 QueryTable
[1].Name
= L
"ImagePath";
391 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
392 QueryTable
[1].EntryContext
= &ServiceImagePath
;
394 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
395 ServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
397 if (!NT_SUCCESS(Status
))
399 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
403 IopDisplayLoadingMessage(ServiceName
->Buffer
);
406 * Normalize the image path for all later processing.
409 Status
= IopNormalizeImagePath(&ServiceImagePath
, ServiceName
);
411 if (!NT_SUCCESS(Status
))
413 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
421 *ModuleObject
= LdrGetModuleObject(&ServiceImagePath
);
423 if (*ModuleObject
== NULL
)
425 Status
= STATUS_UNSUCCESSFUL
;
428 * Special case for boot modules that were loaded by boot loader.
431 if (ServiceStart
== 0)
434 CHAR SearchName
[256];
436 PLOADER_MODULE KeLoaderModules
=
437 (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
441 * Improve this searching algorithm by using the image name
442 * stored in registry entry ImageName and use the whole path
443 * (requires change in FreeLoader).
446 _snprintf(SearchName
, sizeof(SearchName
), "%wZ.sys", ServiceName
);
447 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
449 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
450 if (!_stricmp(ModuleName
, SearchName
))
452 DPRINT("Initializing boot module\n");
454 /* Tell, that the module is already loaded */
455 KeLoaderModules
[i
].Reserved
= 1;
457 Status
= LdrProcessModule(
458 (PVOID
)KeLoaderModules
[i
].ModStart
,
462 KDB_SYMBOLFILE_HOOK(SearchName
);
470 * Case for rest of the drivers (except disabled)
473 else if (ServiceStart
< 4)
475 DPRINT("Loading module\n");
476 Status
= LdrLoadModule(&ServiceImagePath
, ModuleObject
);
481 DPRINT("Module already loaded\n");
482 Status
= STATUS_SUCCESS
;
485 RtlFreeUnicodeString(&ServiceImagePath
);
488 * Now check if the module was loaded successfully.
491 if (!NT_SUCCESS(Status
))
493 DPRINT("Module loading failed (Status %x)\n", Status
);
496 DPRINT("Module loading (Status %x)\n", Status
);
502 * IopInitializeDriverModule
504 * Initalize a loaded driver.
508 * Pointer to device node.
511 * Module object representing the driver. It can be retrieve by
512 * IopLoadServiceModule.
515 * Set to TRUE for file system drivers.
518 * On successful return this contains the driver object representing
523 IopInitializeDriverModule(
524 IN PDEVICE_NODE DeviceNode
,
525 IN PMODULE_OBJECT ModuleObject
,
526 IN BOOLEAN FileSystemDriver
,
527 OUT PDRIVER_OBJECT
*DriverObject
)
529 UNICODE_STRING RegistryKey
;
530 PDRIVER_INITIALIZE DriverEntry
= ModuleObject
->EntryPoint
;
532 WCHAR ServicesKeyName
[] = L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
534 Status
= IopCreateDriverObject(
536 &DeviceNode
->ServiceName
,
539 ModuleObject
->Length
);
541 if (!NT_SUCCESS(Status
))
543 DPRINT("IopCreateDriverObject failed (Status %x)\n", Status
);
547 if (DeviceNode
->ServiceName
.Buffer
)
549 RegistryKey
.Length
= DeviceNode
->ServiceName
.Length
+
550 sizeof(ServicesKeyName
) - sizeof(UNICODE_NULL
);
551 RegistryKey
.MaximumLength
= RegistryKey
.Length
+ sizeof(UNICODE_NULL
);
552 RegistryKey
.Buffer
= ExAllocatePool(PagedPool
, RegistryKey
.MaximumLength
);
553 wcscpy(RegistryKey
.Buffer
, ServicesKeyName
);
554 wcscat(RegistryKey
.Buffer
, DeviceNode
->ServiceName
.Buffer
);
558 RtlInitUnicodeString(&RegistryKey
, NULL
);
561 DPRINT("RegistryKey: %wZ\n", &RegistryKey
);
562 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry
);
564 IopMarkLastReinitializeDriver();
566 Status
= DriverEntry(*DriverObject
, &RegistryKey
);
567 if (!NT_SUCCESS(Status
))
569 ObMakeTemporaryObject(*DriverObject
);
570 ObDereferenceObject(*DriverObject
);
574 IopReinitializeDrivers();
576 return STATUS_SUCCESS
;
580 * IopAttachFilterDriversCallback
582 * Internal routine used by IopAttachFilterDrivers.
586 IopAttachFilterDriversCallback(
594 PDEVICE_NODE DeviceNode
= Context
;
595 UNICODE_STRING ServiceName
;
597 PMODULE_OBJECT ModuleObject
;
598 PDRIVER_OBJECT DriverObject
;
601 for (Filters
= ValueData
;
602 ((ULONG_PTR
)Filters
- (ULONG_PTR
)ValueData
) < ValueLength
&&
604 Filters
+= (ServiceName
.Length
/ sizeof(WCHAR
)) + 1)
606 DPRINT("Filter Driver: %S (%wZ)\n", Filters
, &DeviceNode
->InstancePath
);
607 ServiceName
.Buffer
= Filters
;
608 ServiceName
.MaximumLength
=
609 ServiceName
.Length
= wcslen(Filters
) * sizeof(WCHAR
);
611 /* Load and initialize the filter driver */
612 Status
= IopLoadServiceModule(&ServiceName
, &ModuleObject
);
613 if (!NT_SUCCESS(Status
))
616 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
617 if (!NT_SUCCESS(Status
))
620 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
621 if (!NT_SUCCESS(Status
))
625 return STATUS_SUCCESS
;
629 * IopAttachFilterDrivers
631 * Load filter drivers for specified device node.
635 * Set to TRUE for loading lower level filters or FALSE for upper
640 IopAttachFilterDrivers(
641 PDEVICE_NODE DeviceNode
,
644 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
646 UNICODE_STRING Class
;
647 WCHAR ClassBuffer
[40];
651 * First load the device filters
654 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
656 QueryTable
[0].Name
= L
"LowerFilters";
658 QueryTable
[0].Name
= L
"UpperFilters";
659 QueryTable
[0].EntryContext
= NULL
;
660 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
661 QueryTable
[1].QueryRoutine
= NULL
;
662 QueryTable
[1].Name
= NULL
;
664 KeyBuffer
= ExAllocatePool(
666 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
667 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
668 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
670 RtlQueryRegistryValues(
671 RTL_REGISTRY_ABSOLUTE
,
678 * Now get the class GUID
682 Class
.MaximumLength
= 40 * sizeof(WCHAR
);
683 Class
.Buffer
= ClassBuffer
;
684 QueryTable
[0].QueryRoutine
= NULL
;
685 QueryTable
[0].Name
= L
"ClassGUID";
686 QueryTable
[0].EntryContext
= &Class
;
687 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
689 Status
= RtlQueryRegistryValues(
690 RTL_REGISTRY_ABSOLUTE
,
696 ExFreePool(KeyBuffer
);
699 * Load the class filter driver
702 if (NT_SUCCESS(Status
))
704 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
706 QueryTable
[0].Name
= L
"LowerFilters";
708 QueryTable
[0].Name
= L
"UpperFilters";
709 QueryTable
[0].EntryContext
= NULL
;
710 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
712 KeyBuffer
= ExAllocatePool(PagedPool
, (58 * sizeof(WCHAR
)) + Class
.Length
);
713 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
714 wcscat(KeyBuffer
, ClassBuffer
);
716 RtlQueryRegistryValues(
717 RTL_REGISTRY_ABSOLUTE
,
723 ExFreePool(KeyBuffer
);
726 return STATUS_SUCCESS
;
729 static NTSTATUS STDCALL
730 IopGetGroupOrderList(PWSTR ValueName
,
737 PSERVICE_GROUP Group
;
739 DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
740 ValueName
, ValueType
, ValueData
, ValueLength
, Context
, EntryContext
);
742 if (ValueType
== REG_BINARY
&&
744 ValueLength
>= sizeof(DWORD
) &&
745 ValueLength
>= (*(PULONG
)ValueData
+ 1) * sizeof(DWORD
))
747 Group
= (PSERVICE_GROUP
)Context
;
748 Group
->TagCount
= ((PULONG
)ValueData
)[0];
749 if (Group
->TagCount
> 0)
751 if (ValueLength
>= (Group
->TagCount
+ 1) * sizeof(DWORD
))
753 Group
->TagArray
= ExAllocatePool(NonPagedPool
, Group
->TagCount
* sizeof(DWORD
));
754 if (Group
->TagArray
== NULL
)
757 return STATUS_INSUFFICIENT_RESOURCES
;
759 memcpy(Group
->TagArray
, (PULONG
)ValueData
+ 1, Group
->TagCount
* sizeof(DWORD
));
764 return STATUS_UNSUCCESSFUL
;
768 return STATUS_SUCCESS
;
771 static NTSTATUS STDCALL
772 IopCreateGroupListEntry(PWSTR ValueName
,
779 PSERVICE_GROUP Group
;
780 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
784 if (ValueType
== REG_SZ
)
786 DPRINT("GroupName: '%S'\n", (PWCHAR
)ValueData
);
788 Group
= ExAllocatePool(NonPagedPool
,
789 sizeof(SERVICE_GROUP
));
792 return(STATUS_INSUFFICIENT_RESOURCES
);
795 RtlZeroMemory(Group
, sizeof(SERVICE_GROUP
));
797 if (!RtlpCreateUnicodeString(&Group
->GroupName
, (PWSTR
)ValueData
, NonPagedPool
))
800 return(STATUS_INSUFFICIENT_RESOURCES
);
803 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
804 QueryTable
[0].Name
= (PWSTR
)ValueData
;
805 QueryTable
[0].QueryRoutine
= IopGetGroupOrderList
;
807 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
812 DPRINT("%x %d %S\n", Status
, Group
->TagCount
, (PWSTR
)ValueData
);
814 InsertTailList(&GroupListHead
,
815 &Group
->GroupListEntry
);
818 return(STATUS_SUCCESS
);
822 static NTSTATUS STDCALL
823 IopCreateServiceListEntry(PUNICODE_STRING ServiceName
)
825 RTL_QUERY_REGISTRY_TABLE QueryTable
[7];
829 DPRINT("ServiceName: '%wZ'\n", ServiceName
);
831 /* Allocate service entry */
832 Service
= (PSERVICE
)ExAllocatePool(NonPagedPool
, sizeof(SERVICE
));
835 DPRINT1("ExAllocatePool() failed\n");
836 return(STATUS_INSUFFICIENT_RESOURCES
);
838 RtlZeroMemory(Service
, sizeof(SERVICE
));
840 /* Get service data */
841 RtlZeroMemory(&QueryTable
,
844 QueryTable
[0].Name
= L
"Start";
845 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
846 QueryTable
[0].EntryContext
= &Service
->Start
;
848 QueryTable
[1].Name
= L
"Type";
849 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
850 QueryTable
[1].EntryContext
= &Service
->Type
;
852 QueryTable
[2].Name
= L
"ErrorControl";
853 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
854 QueryTable
[2].EntryContext
= &Service
->ErrorControl
;
856 QueryTable
[3].Name
= L
"Group";
857 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
858 QueryTable
[3].EntryContext
= &Service
->ServiceGroup
;
860 QueryTable
[4].Name
= L
"ImagePath";
861 QueryTable
[4].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
862 QueryTable
[4].EntryContext
= &Service
->ImagePath
;
864 QueryTable
[5].Name
= L
"Tag";
865 QueryTable
[5].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
866 QueryTable
[5].EntryContext
= &Service
->Tag
;
868 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
873 if (!NT_SUCCESS(Status
) || Service
->Start
> 1)
875 RtlFreeUnicodeString(&Service
->ServiceGroup
);
876 RtlFreeUnicodeString(&Service
->ImagePath
);
881 /* Copy service name */
882 Service
->ServiceName
.Length
= ServiceName
->Length
;
883 Service
->ServiceName
.MaximumLength
= ServiceName
->Length
+ sizeof(WCHAR
);
884 Service
->ServiceName
.Buffer
= ExAllocatePool(NonPagedPool
,
885 Service
->ServiceName
.MaximumLength
);
886 RtlCopyMemory(Service
->ServiceName
.Buffer
,
888 ServiceName
->Length
);
889 Service
->ServiceName
.Buffer
[ServiceName
->Length
/ sizeof(WCHAR
)] = 0;
891 /* Build registry path */
892 Service
->RegistryPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
893 Service
->RegistryPath
.Buffer
= ExAllocatePool(NonPagedPool
,
894 MAX_PATH
* sizeof(WCHAR
));
895 wcscpy(Service
->RegistryPath
.Buffer
,
896 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
897 wcscat(Service
->RegistryPath
.Buffer
,
898 Service
->ServiceName
.Buffer
);
899 Service
->RegistryPath
.Length
= wcslen(Service
->RegistryPath
.Buffer
) * sizeof(WCHAR
);
901 DPRINT("ServiceName: '%wZ'\n", &Service
->ServiceName
);
902 DPRINT("RegistryPath: '%wZ'\n", &Service
->RegistryPath
);
903 DPRINT("ServiceGroup: '%wZ'\n", &Service
->ServiceGroup
);
904 DPRINT("ImagePath: '%wZ'\n", &Service
->ImagePath
);
905 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
906 Service
->Start
, Service
->Type
, Service
->Tag
, Service
->ErrorControl
);
908 /* Append service entry */
909 InsertTailList(&ServiceListHead
,
910 &Service
->ServiceListEntry
);
912 return(STATUS_SUCCESS
);
916 NTSTATUS INIT_FUNCTION
917 IoCreateDriverList(VOID
)
919 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
920 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
921 OBJECT_ATTRIBUTES ObjectAttributes
;
922 UNICODE_STRING ServicesKeyName
;
923 UNICODE_STRING SubKeyName
;
928 ULONG KeyInfoLength
= 0;
929 ULONG ReturnedLength
;
931 DPRINT("IoCreateDriverList() called\n");
933 /* Initialize basic variables */
934 InitializeListHead(&GroupListHead
);
935 InitializeListHead(&ServiceListHead
);
937 /* Build group order list */
938 RtlZeroMemory(&QueryTable
,
941 QueryTable
[0].Name
= L
"List";
942 QueryTable
[0].QueryRoutine
= IopCreateGroupListEntry
;
944 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
945 L
"ServiceGroupOrder",
949 if (!NT_SUCCESS(Status
))
952 /* Enumerate services and create the service list */
953 RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName
,
954 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
956 InitializeObjectAttributes(&ObjectAttributes
,
958 OBJ_CASE_INSENSITIVE
,
962 Status
= ZwOpenKey(&KeyHandle
,
963 KEY_ENUMERATE_SUB_KEYS
,
965 if (!NT_SUCCESS(Status
))
970 KeyInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
971 KeyInfo
= ExAllocatePool(NonPagedPool
, KeyInfoLength
);
975 return(STATUS_INSUFFICIENT_RESOURCES
);
981 Status
= ZwEnumerateKey(KeyHandle
,
987 if (NT_SUCCESS(Status
))
989 if (KeyInfo
->NameLength
< MAX_PATH
* sizeof(WCHAR
))
992 SubKeyName
.Length
= KeyInfo
->NameLength
;
993 SubKeyName
.MaximumLength
= KeyInfo
->NameLength
+ sizeof(WCHAR
);
994 SubKeyName
.Buffer
= KeyInfo
->Name
;
995 SubKeyName
.Buffer
[SubKeyName
.Length
/ sizeof(WCHAR
)] = 0;
997 DPRINT("KeyName: '%wZ'\n", &SubKeyName
);
998 IopCreateServiceListEntry(&SubKeyName
);
1002 if (!NT_SUCCESS(Status
))
1008 ExFreePool(KeyInfo
);
1011 DPRINT("IoCreateDriverList() done\n");
1013 return(STATUS_SUCCESS
);
1016 NTSTATUS INIT_FUNCTION
1017 IoDestroyDriverList(VOID
)
1019 PLIST_ENTRY GroupEntry
;
1020 PLIST_ENTRY ServiceEntry
;
1021 PSERVICE_GROUP CurrentGroup
;
1022 PSERVICE CurrentService
;
1024 DPRINT("IoDestroyDriverList() called\n");
1026 /* Destroy group list */
1027 GroupEntry
= GroupListHead
.Flink
;
1028 while (GroupEntry
!= &GroupListHead
)
1030 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1032 RtlFreeUnicodeString(&CurrentGroup
->GroupName
);
1033 RemoveEntryList(GroupEntry
);
1034 if (CurrentGroup
->TagArray
)
1036 ExFreePool(CurrentGroup
->TagArray
);
1038 ExFreePool(CurrentGroup
);
1040 GroupEntry
= GroupListHead
.Flink
;
1043 /* Destroy service list */
1044 ServiceEntry
= ServiceListHead
.Flink
;
1045 while (ServiceEntry
!= &ServiceListHead
)
1047 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1049 RtlFreeUnicodeString(&CurrentService
->ServiceName
);
1050 RtlFreeUnicodeString(&CurrentService
->RegistryPath
);
1051 RtlFreeUnicodeString(&CurrentService
->ServiceGroup
);
1052 RtlFreeUnicodeString(&CurrentService
->ImagePath
);
1053 RemoveEntryList(ServiceEntry
);
1054 ExFreePool(CurrentService
);
1056 ServiceEntry
= ServiceListHead
.Flink
;
1059 DPRINT("IoDestroyDriverList() done\n");
1061 return(STATUS_SUCCESS
);
1064 VOID STATIC INIT_FUNCTION
1065 MiFreeBootDriverMemory(PVOID StartAddress
, ULONG Length
)
1069 for (i
= 0; i
< PAGE_ROUND_UP(Length
) / PAGE_SIZE
; i
++)
1071 MmDeleteVirtualMapping(NULL
, (char*)StartAddress
+ i
* PAGE_SIZE
, TRUE
, NULL
, NULL
);
1076 * IopInitializeBuiltinDriver
1078 * Initialize a driver that is already loaded in memory.
1081 NTSTATUS FASTCALL INIT_FUNCTION
1082 IopInitializeBuiltinDriver(
1083 PDEVICE_NODE ModuleDeviceNode
,
1084 PVOID ModuleLoadBase
,
1088 PMODULE_OBJECT ModuleObject
;
1089 PDEVICE_NODE DeviceNode
;
1090 PDRIVER_OBJECT DriverObject
;
1092 CHAR TextBuffer
[256];
1093 PCHAR FileNameWithoutPath
;
1094 LPWSTR FileExtension
;
1096 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1097 FileName
, ModuleLoadBase
, ModuleLength
);
1100 * Display 'Initializing XXX...' message
1103 sprintf(TextBuffer
, "Initializing %s...\n", FileName
);
1104 HalDisplayString(TextBuffer
);
1107 * Determine the right device object
1110 if (ModuleDeviceNode
== NULL
)
1112 /* Use IopRootDeviceNode for now */
1113 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1114 if (!NT_SUCCESS(Status
))
1116 CPRINT("Driver load failed, status (%x)\n", Status
);
1121 DeviceNode
= ModuleDeviceNode
;
1125 * Generate filename without path (not needed by freeldr)
1128 FileNameWithoutPath
= strrchr(FileName
, '\\');
1129 if (FileNameWithoutPath
== NULL
)
1131 FileNameWithoutPath
= FileName
;
1138 RtlCreateUnicodeStringFromAsciiz(&DeviceNode
->ServiceName
,
1139 FileNameWithoutPath
);
1140 Status
= LdrProcessModule(ModuleLoadBase
, &DeviceNode
->ServiceName
,
1142 if (!NT_SUCCESS(Status
))
1144 if (ModuleDeviceNode
== NULL
)
1145 IopFreeDeviceNode(DeviceNode
);
1146 CPRINT("Driver load failed, status (%x)\n", Status
);
1151 KDB_SYMBOLFILE_HOOK(FileName
);
1154 * Strip the file extension from ServiceName
1157 FileExtension
= wcsrchr(DeviceNode
->ServiceName
.Buffer
, '.');
1158 if (FileExtension
!= NULL
)
1160 DeviceNode
->ServiceName
.Length
-= wcslen(FileExtension
) * sizeof(WCHAR
);
1161 FileExtension
[0] = 0;
1165 * Initialize the driver
1168 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
,
1171 if (!NT_SUCCESS(Status
))
1173 if (ModuleDeviceNode
== NULL
)
1174 IopFreeDeviceNode(DeviceNode
);
1175 CPRINT("Driver load failed, status (%x)\n", Status
);
1179 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1185 * IopInitializeBootDrivers
1187 * Initialize boot drivers and free memory for boot files.
1197 IopInitializeBootDrivers(VOID
)
1199 ULONG BootDriverCount
;
1205 PLOADER_MODULE KeLoaderModules
= (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
1207 UNICODE_STRING DriverName
;
1210 DPRINT("IopInitializeBootDrivers()\n");
1212 BootDriverCount
= 0;
1213 for (i
= 0; i
< KeLoaderBlock
.ModsCount
; i
++)
1215 ModuleStart
= KeLoaderModules
[i
].ModStart
;
1216 ModuleSize
= KeLoaderModules
[i
].ModEnd
- ModuleStart
;
1217 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
1218 ModuleLoaded
= KeLoaderModules
[i
].Reserved
;
1219 Extension
= strrchr(ModuleName
, '.');
1220 if (Extension
== NULL
)
1223 if (!_stricmp(Extension
, ".sym") || !_stricmp(Extension
, ".dll"))
1225 /* Process symbols for *.exe and *.dll */
1226 KDB_SYMBOLFILE_HOOK(ModuleName
);
1228 /* Log *.exe and *.dll files */
1229 RtlCreateUnicodeStringFromAsciiz(&DriverName
, ModuleName
);
1230 IopBootLog(&DriverName
, TRUE
);
1231 RtlFreeUnicodeString(&DriverName
);
1233 else if (!_stricmp(Extension
, ".sys"))
1235 /* Initialize and log boot start driver */
1238 Status
= IopInitializeBuiltinDriver(NULL
,
1242 RtlCreateUnicodeStringFromAsciiz(&DriverName
, ModuleName
);
1243 IopBootLog(&DriverName
, NT_SUCCESS(Status
) ? TRUE
: FALSE
);
1244 RtlFreeUnicodeString(&DriverName
);
1251 * Free memory for all boot files, except ntoskrnl.exe.
1253 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
1255 MiFreeBootDriverMemory((PVOID
)KeLoaderModules
[i
].ModStart
,
1256 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
1259 KeLoaderBlock
.ModsCount
= 0;
1261 if (BootDriverCount
== 0)
1263 DbgPrint("No boot drivers available.\n");
1268 static INIT_FUNCTION NTSTATUS
1269 IopLoadDriver(PSERVICE Service
)
1271 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1273 IopDisplayLoadingMessage(Service
->ServiceName
.Buffer
);
1274 Status
= ZwLoadDriver(&Service
->RegistryPath
);
1275 IopBootLog(&Service
->ImagePath
, NT_SUCCESS(Status
) ? TRUE
: FALSE
);
1276 if (!NT_SUCCESS(Status
))
1278 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status
);
1280 if (Service
->ErrorControl
== 1)
1284 else if (Service
->ErrorControl
== 2)
1286 if (IsLastKnownGood
== FALSE
)
1288 /* Boot last known good configuration */
1291 else if (Service
->ErrorControl
== 3)
1293 if (IsLastKnownGood
== FALSE
)
1295 /* Boot last known good configuration */
1309 * IopInitializeSystemDrivers
1311 * Load drivers marked as system start.
1321 IopInitializeSystemDrivers(VOID
)
1323 PLIST_ENTRY GroupEntry
;
1324 PLIST_ENTRY ServiceEntry
;
1325 PSERVICE_GROUP CurrentGroup
;
1326 PSERVICE CurrentService
;
1330 DPRINT("IopInitializeSystemDrivers()\n");
1332 GroupEntry
= GroupListHead
.Flink
;
1333 while (GroupEntry
!= &GroupListHead
)
1335 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1337 DPRINT("Group: %wZ\n", &CurrentGroup
->GroupName
);
1339 /* Load all drivers with a valid tag */
1340 for (i
= 0; i
< CurrentGroup
->TagCount
; i
++)
1342 ServiceEntry
= ServiceListHead
.Flink
;
1343 while (ServiceEntry
!= &ServiceListHead
)
1345 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1347 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1348 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1349 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/) &&
1350 (CurrentService
->Tag
== CurrentGroup
->TagArray
[i
]))
1352 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1353 Status
= IopLoadDriver(CurrentService
);
1355 ServiceEntry
= ServiceEntry
->Flink
;
1359 /* Load all drivers without a tag or with an invalid tag */
1360 ServiceEntry
= ServiceListHead
.Flink
;
1361 while (ServiceEntry
!= &ServiceListHead
)
1363 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1364 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1365 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1366 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/))
1368 for (i
= 0; i
< CurrentGroup
->TagCount
; i
++)
1370 if (CurrentGroup
->TagArray
[i
] == CurrentService
->Tag
)
1375 if (i
>= CurrentGroup
->TagCount
)
1377 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1378 Status
= IopLoadDriver(CurrentService
);
1381 ServiceEntry
= ServiceEntry
->Flink
;
1384 GroupEntry
= GroupEntry
->Flink
;
1387 DPRINT("IopInitializeSystemDrivers() done\n");
1393 * Unloads a device driver.
1397 * Name of the service to unload (registry key).
1400 * Whether to unload Plug & Plug or only legacy drivers. If this
1401 * parameter is set to FALSE, the routine will unload only legacy
1408 * Guard the whole function by SEH.
1412 IopUnloadDriver(PUNICODE_STRING DriverServiceName
, BOOLEAN UnloadPnpDrivers
)
1414 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1415 UNICODE_STRING ImagePath
;
1416 UNICODE_STRING ServiceName
;
1417 UNICODE_STRING ObjectName
;
1418 PDRIVER_OBJECT DriverObject
;
1419 PMODULE_OBJECT ModuleObject
;
1423 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName
, UnloadPnpDrivers
);
1426 * Get the service name from the registry key name
1429 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1431 Start
= DriverServiceName
->Buffer
;
1435 RtlInitUnicodeString(&ServiceName
, Start
);
1438 * Construct the driver object name
1441 ObjectName
.Length
= (wcslen(Start
) + 8) * sizeof(WCHAR
);
1442 ObjectName
.MaximumLength
= ObjectName
.Length
+ sizeof(WCHAR
);
1443 ObjectName
.Buffer
= ExAllocatePool(NonPagedPool
, ObjectName
.MaximumLength
);
1444 wcscpy(ObjectName
.Buffer
, L
"\\Driver\\");
1445 memcpy(ObjectName
.Buffer
+ 8, Start
, (ObjectName
.Length
- 8) * sizeof(WCHAR
));
1446 ObjectName
.Buffer
[ObjectName
.Length
/sizeof(WCHAR
)] = 0;
1449 * Find the driver object
1452 Status
= ObReferenceObjectByName(&ObjectName
, 0, 0, 0, IoDriverObjectType
,
1453 KernelMode
, 0, (PVOID
*)&DriverObject
);
1455 if (!NT_SUCCESS(Status
))
1457 DPRINT("Can't locate driver object for %wZ\n", ObjectName
);
1462 * Free the buffer for driver object name
1465 ExFreePool(ObjectName
.Buffer
);
1468 * Get path of service...
1471 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1473 RtlInitUnicodeString(&ImagePath
, NULL
);
1475 QueryTable
[0].Name
= L
"ImagePath";
1476 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1477 QueryTable
[0].EntryContext
= &ImagePath
;
1479 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1480 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1482 if (!NT_SUCCESS(Status
))
1484 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1489 * Normalize the image path for all later processing.
1492 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1494 if (!NT_SUCCESS(Status
))
1496 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1501 * ... and check if it's loaded
1504 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1505 if (ModuleObject
== NULL
)
1507 return STATUS_UNSUCCESSFUL
;
1511 * Free the service path
1514 RtlFreeUnicodeString(&ImagePath
);
1517 * Unload the module and release the references to the device object
1520 if (DriverObject
->DriverUnload
)
1521 (*DriverObject
->DriverUnload
)(DriverObject
);
1522 ObDereferenceObject(DriverObject
);
1523 ObDereferenceObject(DriverObject
);
1524 LdrUnloadModule(ModuleObject
);
1526 return STATUS_SUCCESS
;
1530 IopMarkLastReinitializeDriver(VOID
)
1534 KeAcquireSpinLock(&DriverReinitListLock
,
1537 if (IsListEmpty(&DriverReinitListHead
))
1539 DriverReinitTailEntry
= NULL
;
1543 DriverReinitTailEntry
= DriverReinitListHead
.Blink
;
1546 KeReleaseSpinLock(&DriverReinitListLock
,
1552 IopReinitializeDrivers(VOID
)
1554 PDRIVER_REINIT_ITEM ReinitItem
;
1558 KeAcquireSpinLock(&DriverReinitListLock
,
1561 if (DriverReinitTailEntry
== NULL
)
1563 KeReleaseSpinLock(&DriverReinitListLock
,
1568 KeReleaseSpinLock(&DriverReinitListLock
,
1573 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1574 &DriverReinitListLock
);
1578 ReinitItem
= (PDRIVER_REINIT_ITEM
)CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1580 /* Increment reinitialization counter */
1581 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1583 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1584 ReinitItem
->Context
,
1585 ReinitItem
->DriverObject
->DriverExtension
->Count
);
1589 if (Entry
== DriverReinitTailEntry
)
1594 /* PUBLIC FUNCTIONS ***********************************************************/
1603 IN PUNICODE_STRING DriverName
, OPTIONAL
1604 IN PDRIVER_INITIALIZE InitializationFunction
1607 WCHAR NameBuffer
[100];
1609 UNICODE_STRING LocalDriverName
; /* To reduce code if no name given */
1611 OBJECT_ATTRIBUTES ObjectAttributes
;
1613 PDRIVER_OBJECT DriverObject
;
1614 UNICODE_STRING ServiceKeyName
;
1617 /* First, create a unique name for the driver if we don't have one */
1620 /* Create a random name and set up the string*/
1621 NameLength
= swprintf(NameBuffer
, L
"\\Driver\\%08u", KeTickCount
);
1622 LocalDriverName
.Length
= NameLength
* sizeof(WCHAR
);
1623 LocalDriverName
.MaximumLength
= LocalDriverName
.Length
+ sizeof(UNICODE_NULL
);
1624 LocalDriverName
.Buffer
= NameBuffer
;
1628 /* So we can avoid another code path, use a local var */
1629 LocalDriverName
= *DriverName
;
1632 /* Initialize the Attributes */
1633 ObjectSize
= sizeof(DRIVER_OBJECT
) + sizeof(DRIVER_EXTENSION
);
1634 InitializeObjectAttributes(&ObjectAttributes
,
1636 OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
1640 /* Create the Object */
1641 Status
= ObCreateObject(KernelMode
,
1649 (PVOID
*)&DriverObject
);
1651 /* Return on failure */
1652 if (!NT_SUCCESS(Status
)) return Status
;
1654 /* Set up the Object */
1655 RtlZeroMemory(DriverObject
, ObjectSize
);
1656 DriverObject
->Type
= IO_TYPE_DRIVER
;
1657 DriverObject
->Size
= sizeof(DRIVER_OBJECT
);
1658 DriverObject
->Flags
= DRVO_BUILTIN_DRIVER
;
1659 DriverObject
->DriverExtension
= (PDRIVER_EXTENSION
)(DriverObject
+ 1);
1660 DriverObject
->DriverExtension
->DriverObject
= DriverObject
;
1661 DriverObject
->DriverInit
= InitializationFunction
;
1662 /* FIXME: Invalidate all Major Functions b/c now they are NULL and might crash */
1664 /* Set up the Service Key Name */
1665 ServiceKeyName
.Buffer
= ExAllocatePool(PagedPool
, LocalDriverName
.Length
+ sizeof(WCHAR
));
1666 ServiceKeyName
.Length
= LocalDriverName
.Length
;
1667 ServiceKeyName
.MaximumLength
= LocalDriverName
.MaximumLength
;
1668 RtlMoveMemory(ServiceKeyName
.Buffer
, LocalDriverName
.Buffer
, LocalDriverName
.Length
);
1669 ServiceKeyName
.Buffer
[ServiceKeyName
.Length
/ sizeof(WCHAR
)] = L
'\0';
1670 DriverObject
->DriverExtension
->ServiceKeyName
= ServiceKeyName
;
1672 /* Also store it in the Driver Object. This is a bit of a hack. */
1673 RtlMoveMemory(&DriverObject
->DriverName
, &ServiceKeyName
, sizeof(UNICODE_STRING
));
1675 /* Add the Object and get its handle */
1676 Status
= ObInsertObject(DriverObject
,
1683 /* Return on Failure */
1684 if (!NT_SUCCESS(Status
)) return Status
;
1686 /* Now reference it */
1687 Status
= ObReferenceObjectByHandle(hDriver
,
1691 (PVOID
*)&DriverObject
,
1695 /* Finally, call its init function */
1696 Status
= (*InitializationFunction
)(DriverObject
, NULL
);
1698 if (!NT_SUCCESS(Status
)) {
1699 /* If it didn't work, then kill the object */
1700 ObMakeTemporaryObject(DriverObject
);
1701 ObDereferenceObject(DriverObject
);
1704 /* Return the Status */
1714 IN PDRIVER_OBJECT DriverObject
1717 /* Simply derefence the Object */
1718 ObDereferenceObject(DriverObject
);
1725 * Loads a device driver.
1729 * Name of the service to load (registry key).
1739 NtLoadDriver(IN PUNICODE_STRING DriverServiceName
)
1741 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1742 UNICODE_STRING ImagePath
;
1743 UNICODE_STRING ServiceName
;
1746 PDEVICE_NODE DeviceNode
;
1747 PMODULE_OBJECT ModuleObject
;
1748 PDRIVER_OBJECT DriverObject
;
1751 DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName
);
1754 * Check security privileges
1757 /* FIXME: Uncomment when privileges will be correctly implemented. */
1759 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, KeGetPreviousMode()))
1761 DPRINT("Privilege not held\n");
1762 return STATUS_PRIVILEGE_NOT_HELD
;
1766 RtlInitUnicodeString(&ImagePath
, NULL
);
1769 * Get the service name from the registry key name.
1772 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1774 Start
= DriverServiceName
->Buffer
;
1778 RtlInitUnicodeString(&ServiceName
, Start
);
1784 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
1786 RtlInitUnicodeString(&ImagePath
, NULL
);
1788 QueryTable
[0].Name
= L
"Type";
1789 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1790 QueryTable
[0].EntryContext
= &Type
;
1792 QueryTable
[1].Name
= L
"ImagePath";
1793 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1794 QueryTable
[1].EntryContext
= &ImagePath
;
1796 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1797 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1799 if (!NT_SUCCESS(Status
))
1801 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
1802 RtlFreeUnicodeString(&ImagePath
);
1807 * Normalize the image path for all later processing.
1810 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1812 if (!NT_SUCCESS(Status
))
1814 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1818 DPRINT("FullImagePath: '%S'\n", ImagePath
.Buffer
);
1819 DPRINT("Type: %lx\n", Type
);
1822 * See, if the driver module isn't already loaded
1825 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1826 if (ModuleObject
!= NULL
)
1828 DPRINT("Image already loaded\n");
1829 return STATUS_IMAGE_ALREADY_LOADED
;
1833 * Create device node
1836 /* Use IopRootDeviceNode for now */
1837 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1839 if (!NT_SUCCESS(Status
))
1841 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status
);
1846 * Load the driver module
1849 Status
= LdrLoadModule(&ImagePath
, &ModuleObject
);
1851 if (!NT_SUCCESS(Status
))
1853 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status
);
1854 IopFreeDeviceNode(DeviceNode
);
1859 * Set a service name for the device node
1862 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1864 Start
= DriverServiceName
->Buffer
;
1867 RtlpCreateUnicodeString(&DeviceNode
->ServiceName
, Start
, NonPagedPool
);
1870 * Initialize the driver module
1873 Status
= IopInitializeDriverModule(
1876 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1877 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */),
1880 if (!NT_SUCCESS(Status
))
1882 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status
);
1883 LdrUnloadModule(ModuleObject
);
1884 IopFreeDeviceNode(DeviceNode
);
1888 IopInitializeDevice(DeviceNode
, DriverObject
);
1896 * Unloads a legacy device driver.
1900 * Name of the service to unload (registry key).
1910 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName
)
1912 return IopUnloadDriver(DriverServiceName
, FALSE
);
1916 * IoRegisterDriverReinitialization
1923 IoRegisterDriverReinitialization(
1924 PDRIVER_OBJECT DriverObject
,
1925 PDRIVER_REINITIALIZE ReinitRoutine
,
1928 PDRIVER_REINIT_ITEM ReinitItem
;
1930 ReinitItem
= ExAllocatePool(NonPagedPool
, sizeof(DRIVER_REINIT_ITEM
));
1931 if (ReinitItem
== NULL
)
1934 ReinitItem
->DriverObject
= DriverObject
;
1935 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1936 ReinitItem
->Context
= Context
;
1938 ExInterlockedInsertTailList(
1939 &DriverReinitListHead
,
1940 &ReinitItem
->ItemEntry
,
1941 &DriverReinitListLock
);
1945 * IoAllocateDriverObjectExtension
1952 IoAllocateDriverObjectExtension(
1953 PDRIVER_OBJECT DriverObject
,
1954 PVOID ClientIdentificationAddress
,
1955 ULONG DriverObjectExtensionSize
,
1956 PVOID
*DriverObjectExtension
)
1959 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1960 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension
;
1962 NewDriverExtension
= ExAllocatePoolWithTag(
1964 sizeof(PRIVATE_DRIVER_EXTENSIONS
) - sizeof(CHAR
) +
1965 DriverObjectExtensionSize
,
1966 TAG_DRIVER_EXTENSION
);
1968 if (NewDriverExtension
== NULL
)
1970 return STATUS_INSUFFICIENT_RESOURCES
;
1973 OldIrql
= KeRaiseIrqlToDpcLevel();
1975 NewDriverExtension
->Link
= DriverObject
->DriverSection
;
1976 NewDriverExtension
->ClientIdentificationAddress
= ClientIdentificationAddress
;
1978 for (DriverExtensions
= DriverObject
->DriverSection
;
1979 DriverExtensions
!= NULL
;
1980 DriverExtensions
= DriverExtensions
->Link
)
1982 if (DriverExtensions
->ClientIdentificationAddress
==
1983 ClientIdentificationAddress
)
1985 KfLowerIrql(OldIrql
);
1986 return STATUS_OBJECT_NAME_COLLISION
;
1990 DriverObject
->DriverSection
= NewDriverExtension
;
1992 KfLowerIrql(OldIrql
);
1994 *DriverObjectExtension
= &NewDriverExtension
->Extension
;
1996 return STATUS_SUCCESS
;
2000 * IoGetDriverObjectExtension
2007 IoGetDriverObjectExtension(
2008 PDRIVER_OBJECT DriverObject
,
2009 PVOID ClientIdentificationAddress
)
2012 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
2014 OldIrql
= KeRaiseIrqlToDpcLevel();
2016 for (DriverExtensions
= DriverObject
->DriverSection
;
2017 DriverExtensions
!= NULL
&&
2018 DriverExtensions
->ClientIdentificationAddress
!=
2019 ClientIdentificationAddress
;
2020 DriverExtensions
= DriverExtensions
->Link
)
2023 KfLowerIrql(OldIrql
);
2025 if (DriverExtensions
== NULL
)
2028 return &DriverExtensions
->Extension
;