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
;
21 extern ULONG KeTickCount
;
24 LdrProcessModule(PVOID ModuleLoadBase
,
25 PUNICODE_STRING ModuleName
,
26 PMODULE_OBJECT
*ModuleObject
);
28 typedef struct _SERVICE_GROUP
30 LIST_ENTRY GroupListEntry
;
31 UNICODE_STRING GroupName
;
32 BOOLEAN ServicesRunning
;
35 } SERVICE_GROUP
, *PSERVICE_GROUP
;
37 typedef struct _SERVICE
39 LIST_ENTRY ServiceListEntry
;
40 UNICODE_STRING ServiceName
;
41 UNICODE_STRING RegistryPath
;
42 UNICODE_STRING ServiceGroup
;
43 UNICODE_STRING ImagePath
;
50 /* BOOLEAN ServiceRunning;*/ // needed ??
53 typedef struct _DRIVER_REINIT_ITEM
56 PDRIVER_OBJECT DriverObject
;
57 PDRIVER_REINITIALIZE ReinitRoutine
;
59 } DRIVER_REINIT_ITEM
, *PDRIVER_REINIT_ITEM
;
61 /* GLOBALS ********************************************************************/
63 static LIST_ENTRY DriverReinitListHead
;
64 static PLIST_ENTRY DriverReinitTailEntry
;
65 static KSPIN_LOCK DriverReinitListLock
;
67 static LIST_ENTRY GroupListHead
= {NULL
, NULL
};
68 static LIST_ENTRY ServiceListHead
= {NULL
, NULL
};
70 static UNICODE_STRING IopHardwareDatabaseKey
=
71 ROS_STRING_INITIALIZER(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
73 POBJECT_TYPE EXPORTED IoDriverObjectType
= NULL
;
75 #define TAG_DRIVER TAG('D', 'R', 'V', 'R')
76 #define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
78 /* DECLARATIONS ***************************************************************/
85 POBJECT_ATTRIBUTES ObjectAttributes
);
88 IopDeleteDriver(PVOID ObjectBody
);
90 /* PRIVATE FUNCTIONS **********************************************************/
93 IopInitDriverImplementation(VOID
)
95 /* Register the process object type */
96 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
97 IoDriverObjectType
->Tag
= TAG('D', 'R', 'V', 'R');
98 IoDriverObjectType
->TotalObjects
= 0;
99 IoDriverObjectType
->TotalHandles
= 0;
100 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
101 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
102 IoDriverObjectType
->PagedPoolCharge
= 0;
103 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(DRIVER_OBJECT
);
104 IoDriverObjectType
->Dump
= NULL
;
105 IoDriverObjectType
->Open
= NULL
;
106 IoDriverObjectType
->Close
= NULL
;
107 IoDriverObjectType
->Delete
= IopDeleteDriver
;
108 IoDriverObjectType
->Parse
= NULL
;
109 IoDriverObjectType
->Security
= NULL
;
110 IoDriverObjectType
->QueryName
= NULL
;
111 IoDriverObjectType
->OkayToClose
= NULL
;
112 IoDriverObjectType
->Create
= IopCreateDriver
;
113 IoDriverObjectType
->DuplicationNotify
= NULL
;
114 RtlRosInitUnicodeStringFromLiteral(&IoDriverObjectType
->TypeName
, L
"Driver");
116 ObpCreateTypeObject(IoDriverObjectType
);
118 InitializeListHead(&DriverReinitListHead
);
119 KeInitializeSpinLock(&DriverReinitListLock
);
120 DriverReinitTailEntry
= NULL
;
124 IopInvalidDeviceRequest(
125 PDEVICE_OBJECT DeviceObject
,
128 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
129 Irp
->IoStatus
.Information
= 0;
130 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
131 return STATUS_INVALID_DEVICE_REQUEST
;
139 POBJECT_ATTRIBUTES ObjectAttributes
)
141 PDRIVER_OBJECT Object
= ObjectBody
;
144 DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
145 ObjectBody
, Parent
, RemainingPath
);
147 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
148 return STATUS_UNSUCCESSFUL
;
150 /* Create driver extension */
151 Object
->DriverExtension
= (PDRIVER_EXTENSION
)
152 ExAllocatePoolWithTag(
154 sizeof(DRIVER_EXTENSION
),
155 TAG_DRIVER_EXTENSION
);
157 if (Object
->DriverExtension
== NULL
)
159 return STATUS_NO_MEMORY
;
162 RtlZeroMemory(Object
->DriverExtension
, sizeof(DRIVER_EXTENSION
));
164 Object
->Type
= InternalDriverType
;
166 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
167 Object
->MajorFunction
[i
] = IopInvalidDeviceRequest
;
169 Object
->HardwareDatabase
= &IopHardwareDatabaseKey
;
171 return STATUS_SUCCESS
;
175 IopDeleteDriver(PVOID ObjectBody
)
177 PDRIVER_OBJECT Object
= ObjectBody
;
179 PPRIVATE_DRIVER_EXTENSIONS DriverExtension
, NextDriverExtension
;
181 DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody
);
183 ExFreePool(Object
->DriverExtension
);
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
;
212 DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n",
213 DriverObject
, ServiceName
, FileSystem
, DriverImageStart
, DriverImageSize
);
215 *DriverObject
= NULL
;
217 /* Create ModuleName string */
218 if (ServiceName
!= NULL
&& ServiceName
->Buffer
!= NULL
)
220 if (FileSystem
== TRUE
)
221 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
223 wcscpy(NameBuffer
, DRIVER_ROOT_NAME
);
224 wcscat(NameBuffer
, ServiceName
->Buffer
);
226 RtlInitUnicodeString(&DriverName
, NameBuffer
);
227 DPRINT("Driver name: '%wZ'\n", &DriverName
);
231 RtlInitUnicodeString(&DriverName
, NULL
);
234 /* Initialize ObjectAttributes for driver object */
235 InitializeObjectAttributes(
242 /* Create driver object */
243 Status
= ObCreateObject(
249 sizeof(DRIVER_OBJECT
),
254 if (!NT_SUCCESS(Status
))
259 Object
->DriverStart
= DriverImageStart
;
260 Object
->DriverSize
= DriverImageSize
;
262 *DriverObject
= Object
;
264 return STATUS_SUCCESS
;
268 * IopDisplayLoadingMessage
270 * Display 'Loading XXX...' message.
274 IopDisplayLoadingMessage(PWCHAR ServiceName
)
276 CHAR TextBuffer
[256];
277 sprintf(TextBuffer
, "Loading %S...\n", ServiceName
);
278 HalDisplayString(TextBuffer
);
282 * IopNormalizeImagePath
284 * Normalize an image path to contain complete path.
288 * The input path and on exit the result path. ImagePath.Buffer
289 * must be allocated by ExAllocatePool on input. Caller is responsible
290 * for freeing the buffer when it's no longer needed.
293 * Name of the service that ImagePath belongs to.
299 * The input image path isn't freed on error.
303 IopNormalizeImagePath(
304 IN OUT PUNICODE_STRING ImagePath
,
305 IN PUNICODE_STRING ServiceName
)
307 UNICODE_STRING InputImagePath
;
312 sizeof(UNICODE_STRING
));
314 if (InputImagePath
.Length
== 0)
316 ImagePath
->Length
= (33 * sizeof(WCHAR
)) + ServiceName
->Length
;
317 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
318 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
319 if (ImagePath
->Buffer
== NULL
)
320 return STATUS_NO_MEMORY
;
322 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\system32\\drivers\\");
323 wcscat(ImagePath
->Buffer
, ServiceName
->Buffer
);
324 wcscat(ImagePath
->Buffer
, L
".sys");
326 if (InputImagePath
.Buffer
[0] != L
'\\')
328 ImagePath
->Length
= (12 * sizeof(WCHAR
)) + InputImagePath
.Length
;
329 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
330 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
331 if (ImagePath
->Buffer
== NULL
)
332 return STATUS_NO_MEMORY
;
334 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\");
335 wcscat(ImagePath
->Buffer
, InputImagePath
.Buffer
);
336 RtlFreeUnicodeString(&InputImagePath
);
339 return STATUS_SUCCESS
;
343 * IopLoadServiceModule
345 * Load a module specified by registry settings for service.
349 * Name of the service to load.
356 IopLoadServiceModule(
357 IN PUNICODE_STRING ServiceName
,
358 OUT PMODULE_OBJECT
*ModuleObject
)
360 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
362 UNICODE_STRING ServiceImagePath
;
365 DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName
, ModuleObject
);
368 * Get information about the service.
371 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
373 RtlInitUnicodeString(&ServiceImagePath
, NULL
);
375 QueryTable
[0].Name
= L
"Start";
376 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
377 QueryTable
[0].EntryContext
= &ServiceStart
;
379 QueryTable
[1].Name
= L
"ImagePath";
380 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
381 QueryTable
[1].EntryContext
= &ServiceImagePath
;
383 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
384 ServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
386 if (!NT_SUCCESS(Status
))
388 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
392 IopDisplayLoadingMessage(ServiceName
->Buffer
);
395 * Normalize the image path for all later processing.
398 Status
= IopNormalizeImagePath(&ServiceImagePath
, ServiceName
);
400 if (!NT_SUCCESS(Status
))
402 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
410 *ModuleObject
= LdrGetModuleObject(&ServiceImagePath
);
412 if (*ModuleObject
== NULL
)
414 Status
= STATUS_UNSUCCESSFUL
;
417 * Special case for boot modules that were loaded by boot loader.
420 if (ServiceStart
== 0)
423 CHAR SearchName
[256];
425 PLOADER_MODULE KeLoaderModules
=
426 (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
430 * Improve this searching algorithm by using the image name
431 * stored in registry entry ImageName and use the whole path
432 * (requires change in FreeLoader).
435 _snprintf(SearchName
, sizeof(SearchName
), "%wZ.sys", ServiceName
);
436 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
438 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
439 if (!_stricmp(ModuleName
, SearchName
))
441 DPRINT("Initializing boot module\n");
443 /* Tell, that the module is already loaded */
444 KeLoaderModules
[i
].Reserved
= 1;
446 Status
= LdrProcessModule(
447 (PVOID
)KeLoaderModules
[i
].ModStart
,
457 * Case for rest of the drivers (except disabled)
460 else if (ServiceStart
< 4)
462 DPRINT("Loading module\n");
463 Status
= LdrLoadModule(&ServiceImagePath
, ModuleObject
);
468 DPRINT("Module already loaded\n");
469 Status
= STATUS_SUCCESS
;
472 RtlFreeUnicodeString(&ServiceImagePath
);
475 * Now check if the module was loaded successfully.
478 if (!NT_SUCCESS(Status
))
480 DPRINT("Module loading failed (Status %x)\n", Status
);
483 DPRINT("Module loading (Status %x)\n", Status
);
489 * IopInitializeDriverModule
491 * Initalize a loaded driver.
495 * Pointer to device node.
498 * Module object representing the driver. It can be retrieve by
499 * IopLoadServiceModule.
502 * Set to TRUE for file system drivers.
505 * On successful return this contains the driver object representing
510 IopInitializeDriverModule(
511 IN PDEVICE_NODE DeviceNode
,
512 IN PMODULE_OBJECT ModuleObject
,
513 IN BOOLEAN FileSystemDriver
,
514 OUT PDRIVER_OBJECT
*DriverObject
)
516 UNICODE_STRING RegistryKey
;
517 PDRIVER_INITIALIZE DriverEntry
= ModuleObject
->EntryPoint
;
519 WCHAR ServicesKeyName
[] = L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
521 Status
= IopCreateDriverObject(
523 &DeviceNode
->ServiceName
,
526 ModuleObject
->Length
);
528 if (!NT_SUCCESS(Status
))
530 DPRINT("IopCreateDriverObject failed (Status %x)\n", Status
);
534 if (DeviceNode
->ServiceName
.Buffer
)
536 RegistryKey
.Length
= DeviceNode
->ServiceName
.Length
+
537 sizeof(ServicesKeyName
) - sizeof(UNICODE_NULL
);
538 RegistryKey
.MaximumLength
= RegistryKey
.Length
+ sizeof(UNICODE_NULL
);
539 RegistryKey
.Buffer
= ExAllocatePool(PagedPool
, RegistryKey
.MaximumLength
);
540 wcscpy(RegistryKey
.Buffer
, ServicesKeyName
);
541 wcscat(RegistryKey
.Buffer
, DeviceNode
->ServiceName
.Buffer
);
545 RtlInitUnicodeString(&RegistryKey
, NULL
);
548 DPRINT("RegistryKey: %wZ\n", &RegistryKey
);
549 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry
);
551 IopMarkLastReinitializeDriver();
553 Status
= DriverEntry(*DriverObject
, &RegistryKey
);
554 if (!NT_SUCCESS(Status
))
556 ObMakeTemporaryObject(*DriverObject
);
557 ObDereferenceObject(*DriverObject
);
561 IopReinitializeDrivers();
563 return STATUS_SUCCESS
;
567 * IopAttachFilterDriversCallback
569 * Internal routine used by IopAttachFilterDrivers.
573 IopAttachFilterDriversCallback(
581 PDEVICE_NODE DeviceNode
= Context
;
582 UNICODE_STRING ServiceName
;
584 PMODULE_OBJECT ModuleObject
;
585 PDRIVER_OBJECT DriverObject
;
588 for (Filters
= ValueData
;
589 ((ULONG_PTR
)Filters
- (ULONG_PTR
)ValueData
) < ValueLength
&&
591 Filters
+= (ServiceName
.Length
/ sizeof(WCHAR
)) + 1)
593 DPRINT("Filter Driver: %S (%wZ)\n", Filters
, &DeviceNode
->InstancePath
);
594 ServiceName
.Buffer
= Filters
;
595 ServiceName
.MaximumLength
=
596 ServiceName
.Length
= wcslen(Filters
) * sizeof(WCHAR
);
598 /* Load and initialize the filter driver */
599 Status
= IopLoadServiceModule(&ServiceName
, &ModuleObject
);
600 if (!NT_SUCCESS(Status
))
603 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
604 if (!NT_SUCCESS(Status
))
607 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
608 if (!NT_SUCCESS(Status
))
612 return STATUS_SUCCESS
;
616 * IopAttachFilterDrivers
618 * Load filter drivers for specified device node.
622 * Set to TRUE for loading lower level filters or FALSE for upper
627 IopAttachFilterDrivers(
628 PDEVICE_NODE DeviceNode
,
631 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
633 UNICODE_STRING Class
;
634 WCHAR ClassBuffer
[40];
638 * First load the device filters
641 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
643 QueryTable
[0].Name
= L
"LowerFilters";
645 QueryTable
[0].Name
= L
"UpperFilters";
646 QueryTable
[0].EntryContext
= NULL
;
647 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
648 QueryTable
[1].QueryRoutine
= NULL
;
649 QueryTable
[1].Name
= NULL
;
651 KeyBuffer
= ExAllocatePool(
653 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
654 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
655 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
657 RtlQueryRegistryValues(
658 RTL_REGISTRY_ABSOLUTE
,
665 * Now get the class GUID
669 Class
.MaximumLength
= 40 * sizeof(WCHAR
);
670 Class
.Buffer
= ClassBuffer
;
671 QueryTable
[0].QueryRoutine
= NULL
;
672 QueryTable
[0].Name
= L
"ClassGUID";
673 QueryTable
[0].EntryContext
= &Class
;
674 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
676 Status
= RtlQueryRegistryValues(
677 RTL_REGISTRY_ABSOLUTE
,
683 ExFreePool(KeyBuffer
);
686 * Load the class filter driver
689 if (NT_SUCCESS(Status
))
691 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
693 QueryTable
[0].Name
= L
"LowerFilters";
695 QueryTable
[0].Name
= L
"UpperFilters";
696 QueryTable
[0].EntryContext
= NULL
;
697 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
699 KeyBuffer
= ExAllocatePool(PagedPool
, (58 * sizeof(WCHAR
)) + Class
.Length
);
700 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
701 wcscat(KeyBuffer
, ClassBuffer
);
703 RtlQueryRegistryValues(
704 RTL_REGISTRY_ABSOLUTE
,
710 ExFreePool(KeyBuffer
);
713 return STATUS_SUCCESS
;
716 static NTSTATUS STDCALL
717 IopGetGroupOrderList(PWSTR ValueName
,
724 PSERVICE_GROUP Group
;
726 DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
727 ValueName
, ValueType
, ValueData
, ValueLength
, Context
, EntryContext
);
729 if (ValueType
== REG_BINARY
&&
731 ValueLength
>= sizeof(DWORD
) &&
732 ValueLength
>= (*(PULONG
)ValueData
+ 1) * sizeof(DWORD
))
734 Group
= (PSERVICE_GROUP
)Context
;
735 Group
->TagCount
= ((PULONG
)ValueData
)[0];
736 if (Group
->TagCount
> 0)
738 if (ValueLength
>= (Group
->TagCount
+ 1) * sizeof(DWORD
))
740 Group
->TagArray
= ExAllocatePool(NonPagedPool
, Group
->TagCount
* sizeof(DWORD
));
741 if (Group
->TagArray
== NULL
)
744 return STATUS_INSUFFICIENT_RESOURCES
;
746 memcpy(Group
->TagArray
, (PULONG
)ValueData
+ 1, Group
->TagCount
* sizeof(DWORD
));
751 return STATUS_UNSUCCESSFUL
;
755 return STATUS_SUCCESS
;
758 static NTSTATUS STDCALL
759 IopCreateGroupListEntry(PWSTR ValueName
,
766 PSERVICE_GROUP Group
;
767 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
771 if (ValueType
== REG_SZ
)
773 DPRINT("GroupName: '%S'\n", (PWCHAR
)ValueData
);
775 Group
= ExAllocatePool(NonPagedPool
,
776 sizeof(SERVICE_GROUP
));
779 return(STATUS_INSUFFICIENT_RESOURCES
);
782 RtlZeroMemory(Group
, sizeof(SERVICE_GROUP
));
784 if (!RtlCreateUnicodeString(&Group
->GroupName
,
788 return(STATUS_INSUFFICIENT_RESOURCES
);
791 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
792 QueryTable
[0].Name
= (PWSTR
)ValueData
;
793 QueryTable
[0].QueryRoutine
= IopGetGroupOrderList
;
795 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
800 DPRINT("%x %d %S\n", Status
, Group
->TagCount
, (PWSTR
)ValueData
);
802 InsertTailList(&GroupListHead
,
803 &Group
->GroupListEntry
);
806 return(STATUS_SUCCESS
);
810 static NTSTATUS STDCALL
811 IopCreateServiceListEntry(PUNICODE_STRING ServiceName
)
813 RTL_QUERY_REGISTRY_TABLE QueryTable
[7];
817 DPRINT("ServiceName: '%wZ'\n", ServiceName
);
819 /* Allocate service entry */
820 Service
= (PSERVICE
)ExAllocatePool(NonPagedPool
, sizeof(SERVICE
));
823 DPRINT1("ExAllocatePool() failed\n");
824 return(STATUS_INSUFFICIENT_RESOURCES
);
826 RtlZeroMemory(Service
, sizeof(SERVICE
));
828 /* Get service data */
829 RtlZeroMemory(&QueryTable
,
832 QueryTable
[0].Name
= L
"Start";
833 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
834 QueryTable
[0].EntryContext
= &Service
->Start
;
836 QueryTable
[1].Name
= L
"Type";
837 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
838 QueryTable
[1].EntryContext
= &Service
->Type
;
840 QueryTable
[2].Name
= L
"ErrorControl";
841 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
842 QueryTable
[2].EntryContext
= &Service
->ErrorControl
;
844 QueryTable
[3].Name
= L
"Group";
845 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
846 QueryTable
[3].EntryContext
= &Service
->ServiceGroup
;
848 QueryTable
[4].Name
= L
"ImagePath";
849 QueryTable
[4].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
850 QueryTable
[4].EntryContext
= &Service
->ImagePath
;
852 QueryTable
[5].Name
= L
"Tag";
853 QueryTable
[5].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
854 QueryTable
[5].EntryContext
= &Service
->Tag
;
856 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
861 if (!NT_SUCCESS(Status
) || Service
->Start
> 1)
863 RtlFreeUnicodeString(&Service
->ServiceGroup
);
864 RtlFreeUnicodeString(&Service
->ImagePath
);
869 /* Copy service name */
870 Service
->ServiceName
.Length
= ServiceName
->Length
;
871 Service
->ServiceName
.MaximumLength
= ServiceName
->Length
+ sizeof(WCHAR
);
872 Service
->ServiceName
.Buffer
= ExAllocatePool(NonPagedPool
,
873 Service
->ServiceName
.MaximumLength
);
874 RtlCopyMemory(Service
->ServiceName
.Buffer
,
876 ServiceName
->Length
);
877 Service
->ServiceName
.Buffer
[ServiceName
->Length
/ sizeof(WCHAR
)] = 0;
879 /* Build registry path */
880 Service
->RegistryPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
881 Service
->RegistryPath
.Buffer
= ExAllocatePool(NonPagedPool
,
882 MAX_PATH
* sizeof(WCHAR
));
883 wcscpy(Service
->RegistryPath
.Buffer
,
884 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
885 wcscat(Service
->RegistryPath
.Buffer
,
886 Service
->ServiceName
.Buffer
);
887 Service
->RegistryPath
.Length
= wcslen(Service
->RegistryPath
.Buffer
) * sizeof(WCHAR
);
889 DPRINT("ServiceName: '%wZ'\n", &Service
->ServiceName
);
890 DPRINT("RegistryPath: '%wZ'\n", &Service
->RegistryPath
);
891 DPRINT("ServiceGroup: '%wZ'\n", &Service
->ServiceGroup
);
892 DPRINT("ImagePath: '%wZ'\n", &Service
->ImagePath
);
893 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
894 Service
->Start
, Service
->Type
, Service
->Tag
, Service
->ErrorControl
);
896 /* Append service entry */
897 InsertTailList(&ServiceListHead
,
898 &Service
->ServiceListEntry
);
900 return(STATUS_SUCCESS
);
904 NTSTATUS INIT_FUNCTION
905 IoCreateDriverList(VOID
)
907 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
908 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
909 OBJECT_ATTRIBUTES ObjectAttributes
;
910 UNICODE_STRING ServicesKeyName
;
911 UNICODE_STRING SubKeyName
;
916 ULONG KeyInfoLength
= 0;
917 ULONG ReturnedLength
;
919 DPRINT("IoCreateDriverList() called\n");
921 /* Initialize basic variables */
922 InitializeListHead(&GroupListHead
);
923 InitializeListHead(&ServiceListHead
);
925 /* Build group order list */
926 RtlZeroMemory(&QueryTable
,
929 QueryTable
[0].Name
= L
"List";
930 QueryTable
[0].QueryRoutine
= IopCreateGroupListEntry
;
932 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
933 L
"ServiceGroupOrder",
937 if (!NT_SUCCESS(Status
))
940 /* Enumerate services and create the service list */
941 RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName
,
942 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
944 InitializeObjectAttributes(&ObjectAttributes
,
946 OBJ_CASE_INSENSITIVE
,
950 Status
= NtOpenKey(&KeyHandle
,
953 if (!NT_SUCCESS(Status
))
958 KeyInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
959 KeyInfo
= ExAllocatePool(NonPagedPool
, KeyInfoLength
);
963 return(STATUS_INSUFFICIENT_RESOURCES
);
969 Status
= NtEnumerateKey(KeyHandle
,
975 if (NT_SUCCESS(Status
))
977 if (KeyInfo
->NameLength
< MAX_PATH
* sizeof(WCHAR
))
980 SubKeyName
.Length
= KeyInfo
->NameLength
;
981 SubKeyName
.MaximumLength
= KeyInfo
->NameLength
+ sizeof(WCHAR
);
982 SubKeyName
.Buffer
= KeyInfo
->Name
;
983 SubKeyName
.Buffer
[SubKeyName
.Length
/ sizeof(WCHAR
)] = 0;
985 DPRINT("KeyName: '%wZ'\n", &SubKeyName
);
986 IopCreateServiceListEntry(&SubKeyName
);
990 if (!NT_SUCCESS(Status
))
999 DPRINT("IoCreateDriverList() done\n");
1001 return(STATUS_SUCCESS
);
1004 NTSTATUS INIT_FUNCTION
1005 IoDestroyDriverList(VOID
)
1007 PLIST_ENTRY GroupEntry
;
1008 PLIST_ENTRY ServiceEntry
;
1009 PSERVICE_GROUP CurrentGroup
;
1010 PSERVICE CurrentService
;
1012 DPRINT("IoDestroyDriverList() called\n");
1014 /* Destroy group list */
1015 GroupEntry
= GroupListHead
.Flink
;
1016 while (GroupEntry
!= &GroupListHead
)
1018 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1020 RtlFreeUnicodeString(&CurrentGroup
->GroupName
);
1021 RemoveEntryList(GroupEntry
);
1022 if (CurrentGroup
->TagArray
)
1024 ExFreePool(CurrentGroup
->TagArray
);
1026 ExFreePool(CurrentGroup
);
1028 GroupEntry
= GroupListHead
.Flink
;
1031 /* Destroy service list */
1032 ServiceEntry
= ServiceListHead
.Flink
;
1033 while (ServiceEntry
!= &ServiceListHead
)
1035 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1037 RtlFreeUnicodeString(&CurrentService
->ServiceName
);
1038 RtlFreeUnicodeString(&CurrentService
->RegistryPath
);
1039 RtlFreeUnicodeString(&CurrentService
->ServiceGroup
);
1040 RtlFreeUnicodeString(&CurrentService
->ImagePath
);
1041 RemoveEntryList(ServiceEntry
);
1042 ExFreePool(CurrentService
);
1044 ServiceEntry
= ServiceListHead
.Flink
;
1047 DPRINT("IoDestroyDriverList() done\n");
1049 return(STATUS_SUCCESS
);
1052 VOID STATIC INIT_FUNCTION
1053 MiFreeBootDriverMemory(PVOID StartAddress
, ULONG Length
)
1057 for (i
= 0; i
< PAGE_ROUND_UP(Length
) / PAGE_SIZE
; i
++)
1059 MmDeleteVirtualMapping(NULL
, (char*)StartAddress
+ i
* PAGE_SIZE
, TRUE
, NULL
, NULL
);
1064 * IopInitializeBuiltinDriver
1066 * Initialize a driver that is already loaded in memory.
1069 NTSTATUS FASTCALL INIT_FUNCTION
1070 IopInitializeBuiltinDriver(
1071 PDEVICE_NODE ModuleDeviceNode
,
1072 PVOID ModuleLoadBase
,
1076 PMODULE_OBJECT ModuleObject
;
1077 PDEVICE_NODE DeviceNode
;
1078 PDRIVER_OBJECT DriverObject
;
1080 CHAR TextBuffer
[256];
1081 PCHAR FileNameWithoutPath
;
1082 LPWSTR FileExtension
;
1084 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1085 FileName
, ModuleLoadBase
, ModuleLength
);
1088 * Display 'Initializing XXX...' message
1091 sprintf(TextBuffer
, "Initializing %s...\n", FileName
);
1092 HalDisplayString(TextBuffer
);
1095 * Determine the right device object
1098 if (ModuleDeviceNode
== NULL
)
1100 /* Use IopRootDeviceNode for now */
1101 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1102 if (!NT_SUCCESS(Status
))
1104 CPRINT("Driver load failed, status (%x)\n", Status
);
1109 DeviceNode
= ModuleDeviceNode
;
1113 * Generate filename without path (not needed by freeldr)
1116 FileNameWithoutPath
= strrchr(FileName
, '\\');
1117 if (FileNameWithoutPath
== NULL
)
1119 FileNameWithoutPath
= FileName
;
1126 RtlCreateUnicodeStringFromAsciiz(&DeviceNode
->ServiceName
,
1127 FileNameWithoutPath
);
1128 Status
= LdrProcessModule(ModuleLoadBase
, &DeviceNode
->ServiceName
,
1130 if (!NT_SUCCESS(Status
))
1132 if (ModuleDeviceNode
== NULL
)
1133 IopFreeDeviceNode(DeviceNode
);
1134 CPRINT("Driver load failed, status (%x)\n", Status
);
1139 * Strip the file extension from ServiceName
1142 FileExtension
= wcsrchr(DeviceNode
->ServiceName
.Buffer
, '.');
1143 if (FileExtension
!= NULL
)
1145 DeviceNode
->ServiceName
.Length
-= wcslen(FileExtension
) * sizeof(WCHAR
);
1146 FileExtension
[0] = 0;
1150 * Initialize the driver
1153 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
,
1156 if (!NT_SUCCESS(Status
))
1158 if (ModuleDeviceNode
== NULL
)
1159 IopFreeDeviceNode(DeviceNode
);
1160 CPRINT("Driver load failed, status (%x)\n", Status
);
1164 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1170 * IopInitializeBootDrivers
1172 * Initialize boot drivers and free memory for boot files.
1182 IopInitializeBootDrivers(VOID
)
1184 ULONG BootDriverCount
;
1190 PLOADER_MODULE KeLoaderModules
= (PLOADER_MODULE
)KeLoaderBlock
.ModsAddr
;
1192 UNICODE_STRING DriverName
;
1195 DPRINT("IopInitializeBootDrivers()\n");
1197 BootDriverCount
= 0;
1198 for (i
= 0; i
< KeLoaderBlock
.ModsCount
; i
++)
1200 ModuleStart
= KeLoaderModules
[i
].ModStart
;
1201 ModuleSize
= KeLoaderModules
[i
].ModEnd
- ModuleStart
;
1202 ModuleName
= (PCHAR
)KeLoaderModules
[i
].String
;
1203 ModuleLoaded
= KeLoaderModules
[i
].Reserved
;
1204 Extension
= strrchr(ModuleName
, '.');
1205 if (Extension
== NULL
)
1208 if (!_stricmp(Extension
, ".sym"))
1210 /* Pass symbol files to kernel debugger */
1211 KDB_SYMBOLFILE_HOOK((PVOID
)ModuleStart
, ModuleName
, ModuleSize
);
1213 else if (!_stricmp(Extension
, ".exe") || !_stricmp(Extension
, ".dll"))
1215 /* Log *.exe and *.dll files */
1216 RtlCreateUnicodeStringFromAsciiz(&DriverName
, ModuleName
);
1217 IopBootLog(&DriverName
, TRUE
);
1218 RtlFreeUnicodeString(&DriverName
);
1220 else if (!_stricmp(Extension
, ".sys"))
1222 /* Initialize and log boot start driver */
1225 Status
= IopInitializeBuiltinDriver(NULL
,
1229 RtlCreateUnicodeStringFromAsciiz(&DriverName
, ModuleName
);
1230 IopBootLog(&DriverName
, NT_SUCCESS(Status
) ? TRUE
: FALSE
);
1231 RtlFreeUnicodeString(&DriverName
);
1237 * Free memory for all boot files, except ntoskrnl.exe
1238 * and symbol files, if the kernel debugger is active
1240 if (i
!= 0 /* ntoskrnl.exe is always the first module */
1241 #if defined(DBG) || defined(KDBG)
1242 && _stricmp(Extension
, ".sym")
1246 MiFreeBootDriverMemory((PVOID
)KeLoaderModules
[i
].ModStart
,
1247 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
1251 if (BootDriverCount
== 0)
1253 DbgPrint("No boot drivers available.\n");
1258 static INIT_FUNCTION NTSTATUS
1259 IopLoadDriver(PSERVICE Service
)
1261 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1263 IopDisplayLoadingMessage(Service
->ServiceName
.Buffer
);
1264 Status
= NtLoadDriver(&Service
->RegistryPath
);
1265 IopBootLog(&Service
->ImagePath
, NT_SUCCESS(Status
) ? TRUE
: FALSE
);
1266 if (!NT_SUCCESS(Status
))
1268 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status
);
1270 if (Service
->ErrorControl
== 1)
1274 else if (Service
->ErrorControl
== 2)
1276 if (IsLastKnownGood
== FALSE
)
1278 /* Boot last known good configuration */
1281 else if (Service
->ErrorControl
== 3)
1283 if (IsLastKnownGood
== FALSE
)
1285 /* Boot last known good configuration */
1299 * IopInitializeSystemDrivers
1301 * Load drivers marked as system start.
1311 IopInitializeSystemDrivers(VOID
)
1313 PLIST_ENTRY GroupEntry
;
1314 PLIST_ENTRY ServiceEntry
;
1315 PSERVICE_GROUP CurrentGroup
;
1316 PSERVICE CurrentService
;
1320 DPRINT("IopInitializeSystemDrivers()\n");
1322 GroupEntry
= GroupListHead
.Flink
;
1323 while (GroupEntry
!= &GroupListHead
)
1325 CurrentGroup
= CONTAINING_RECORD(GroupEntry
, SERVICE_GROUP
, GroupListEntry
);
1327 DPRINT("Group: %wZ\n", &CurrentGroup
->GroupName
);
1329 /* Load all drivers with a valid tag */
1330 for (i
= 0; i
< CurrentGroup
->TagCount
; i
++)
1332 ServiceEntry
= ServiceListHead
.Flink
;
1333 while (ServiceEntry
!= &ServiceListHead
)
1335 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1337 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1338 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1339 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/) &&
1340 (CurrentService
->Tag
== CurrentGroup
->TagArray
[i
]))
1342 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1343 Status
= IopLoadDriver(CurrentService
);
1345 ServiceEntry
= ServiceEntry
->Flink
;
1349 /* Load all drivers without a tag or with an invalid tag */
1350 ServiceEntry
= ServiceListHead
.Flink
;
1351 while (ServiceEntry
!= &ServiceListHead
)
1353 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
1354 if ((RtlCompareUnicodeString(&CurrentGroup
->GroupName
,
1355 &CurrentService
->ServiceGroup
, TRUE
) == 0) &&
1356 (CurrentService
->Start
== 1 /*SERVICE_SYSTEM_START*/))
1358 for (i
= 0; i
< CurrentGroup
->TagCount
; i
++)
1360 if (CurrentGroup
->TagArray
[i
] == CurrentService
->Tag
)
1365 if (i
>= CurrentGroup
->TagCount
)
1367 DPRINT(" Path: %wZ\n", &CurrentService
->RegistryPath
);
1368 Status
= IopLoadDriver(CurrentService
);
1371 ServiceEntry
= ServiceEntry
->Flink
;
1374 GroupEntry
= GroupEntry
->Flink
;
1377 DPRINT("IopInitializeSystemDrivers() done\n");
1383 * Unloads a device driver.
1387 * Name of the service to unload (registry key).
1390 * Whether to unload Plug & Plug or only legacy drivers. If this
1391 * parameter is set to FALSE, the routine will unload only legacy
1398 * Guard the whole function by SEH.
1402 IopUnloadDriver(PUNICODE_STRING DriverServiceName
, BOOLEAN UnloadPnpDrivers
)
1404 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1405 UNICODE_STRING ImagePath
;
1406 UNICODE_STRING ServiceName
;
1407 UNICODE_STRING ObjectName
;
1408 PDRIVER_OBJECT DriverObject
;
1409 PMODULE_OBJECT ModuleObject
;
1413 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName
, UnloadPnpDrivers
);
1416 * Get the service name from the registry key name
1419 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1421 Start
= DriverServiceName
->Buffer
;
1425 RtlInitUnicodeString(&ServiceName
, Start
);
1428 * Construct the driver object name
1431 ObjectName
.Length
= (wcslen(Start
) + 8) * sizeof(WCHAR
);
1432 ObjectName
.MaximumLength
= ObjectName
.Length
+ sizeof(WCHAR
);
1433 ObjectName
.Buffer
= ExAllocatePool(NonPagedPool
, ObjectName
.MaximumLength
);
1434 wcscpy(ObjectName
.Buffer
, L
"\\Driver\\");
1435 memcpy(ObjectName
.Buffer
+ 8, Start
, (ObjectName
.Length
- 8) * sizeof(WCHAR
));
1436 ObjectName
.Buffer
[ObjectName
.Length
/sizeof(WCHAR
)] = 0;
1439 * Find the driver object
1442 Status
= ObReferenceObjectByName(&ObjectName
, 0, 0, 0, IoDriverObjectType
,
1443 KernelMode
, 0, (PVOID
*)&DriverObject
);
1445 if (!NT_SUCCESS(Status
))
1447 DPRINT("Can't locate driver object for %wZ\n", ObjectName
);
1452 * Free the buffer for driver object name
1455 ExFreePool(ObjectName
.Buffer
);
1458 * Get path of service...
1461 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1463 RtlInitUnicodeString(&ImagePath
, NULL
);
1465 QueryTable
[0].Name
= L
"ImagePath";
1466 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1467 QueryTable
[0].EntryContext
= &ImagePath
;
1469 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1470 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1472 if (!NT_SUCCESS(Status
))
1474 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1479 * Normalize the image path for all later processing.
1482 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1484 if (!NT_SUCCESS(Status
))
1486 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1491 * ... and check if it's loaded
1494 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1495 if (ModuleObject
== NULL
)
1497 return STATUS_UNSUCCESSFUL
;
1501 * Free the service path
1504 RtlFreeUnicodeString(&ImagePath
);
1507 * Unload the module and release the references to the device object
1510 if (DriverObject
->DriverUnload
)
1511 (*DriverObject
->DriverUnload
)(DriverObject
);
1512 ObDereferenceObject(DriverObject
);
1513 ObDereferenceObject(DriverObject
);
1514 LdrUnloadModule(ModuleObject
);
1516 return STATUS_SUCCESS
;
1520 IopMarkLastReinitializeDriver(VOID
)
1524 KeAcquireSpinLock(&DriverReinitListLock
,
1527 if (IsListEmpty(&DriverReinitListHead
))
1529 DriverReinitTailEntry
= NULL
;
1533 DriverReinitTailEntry
= DriverReinitListHead
.Blink
;
1536 KeReleaseSpinLock(&DriverReinitListLock
,
1542 IopReinitializeDrivers(VOID
)
1544 PDRIVER_REINIT_ITEM ReinitItem
;
1548 KeAcquireSpinLock(&DriverReinitListLock
,
1551 if (DriverReinitTailEntry
== NULL
)
1553 KeReleaseSpinLock(&DriverReinitListLock
,
1558 KeReleaseSpinLock(&DriverReinitListLock
,
1563 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1564 &DriverReinitListLock
);
1568 ReinitItem
= (PDRIVER_REINIT_ITEM
)CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1570 /* Increment reinitialization counter */
1571 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1573 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1574 ReinitItem
->Context
,
1575 ReinitItem
->DriverObject
->DriverExtension
->Count
);
1579 if (Entry
== DriverReinitTailEntry
)
1584 /* PUBLIC FUNCTIONS ***********************************************************/
1593 IN PUNICODE_STRING DriverName
, OPTIONAL
1594 IN PDRIVER_INITIALIZE InitializationFunction
1597 WCHAR NameBuffer
[100];
1599 UNICODE_STRING LocalDriverName
; /* To reduce code if no name given */
1601 OBJECT_ATTRIBUTES ObjectAttributes
;
1603 PDRIVER_OBJECT DriverObject
;
1604 UNICODE_STRING ServiceKeyName
;
1607 /* First, create a unique name for the driver if we don't have one */
1610 /* Create a random name and set up the string*/
1611 NameLength
= swprintf(NameBuffer
, L
"\\Driver\\%08u", KeTickCount
);
1612 LocalDriverName
.Length
= NameLength
* sizeof(WCHAR
);
1613 LocalDriverName
.MaximumLength
= LocalDriverName
.Length
+ sizeof(UNICODE_NULL
);
1614 LocalDriverName
.Buffer
= NameBuffer
;
1618 /* So we can avoid another code path, use a local var */
1619 LocalDriverName
= *DriverName
;
1622 /* Initialize the Attributes */
1623 ObjectSize
= sizeof(DRIVER_OBJECT
) + sizeof(DRIVER_EXTENSION
);
1624 InitializeObjectAttributes(&ObjectAttributes
,
1626 OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
1630 /* Create the Object */
1631 Status
= ObCreateObject(KernelMode
,
1639 (PVOID
*)&DriverObject
);
1641 /* Return on failure */
1642 if (!NT_SUCCESS(Status
)) return Status
;
1644 /* Set up the Object */
1645 RtlZeroMemory(DriverObject
, ObjectSize
);
1646 DriverObject
->Type
= IO_TYPE_DRIVER
;
1647 DriverObject
->Size
= sizeof(DRIVER_OBJECT
);
1648 DriverObject
->Flags
= DRVO_BUILTIN_DRIVER
;
1649 DriverObject
->DriverExtension
= (PDRIVER_EXTENSION
)(DriverObject
+ 1);
1650 DriverObject
->DriverExtension
->DriverObject
= DriverObject
;
1651 DriverObject
->DriverInit
= InitializationFunction
;
1652 /* FIXME: Invalidate all Major Functions b/c now they are NULL and might crash */
1654 /* Set up the Service Key Name */
1655 ServiceKeyName
.Buffer
= ExAllocatePool(PagedPool
, LocalDriverName
.Length
+ sizeof(WCHAR
));
1656 ServiceKeyName
.Length
= LocalDriverName
.Length
;
1657 ServiceKeyName
.MaximumLength
= LocalDriverName
.MaximumLength
;
1658 RtlMoveMemory(ServiceKeyName
.Buffer
, LocalDriverName
.Buffer
, LocalDriverName
.Length
);
1659 ServiceKeyName
.Buffer
[ServiceKeyName
.Length
/ sizeof(WCHAR
)] = L
'\0';
1660 DriverObject
->DriverExtension
->ServiceKeyName
= ServiceKeyName
;
1662 /* Also store it in the Driver Object. This is a bit of a hack. */
1663 RtlMoveMemory(&DriverObject
->DriverName
, &ServiceKeyName
, sizeof(UNICODE_STRING
));
1665 /* Add the Object and get its handle */
1666 Status
= ObInsertObject(DriverObject
,
1673 /* Return on Failure */
1674 if (!NT_SUCCESS(Status
)) return Status
;
1676 /* Now reference it */
1677 Status
= ObReferenceObjectByHandle(hDriver
,
1681 (PVOID
*)&DriverObject
,
1685 /* Finally, call its init function */
1686 Status
= (*InitializationFunction
)(DriverObject
, NULL
);
1688 if (!NT_SUCCESS(Status
)) {
1689 /* If it didn't work, then kill the object */
1690 ObMakeTemporaryObject(DriverObject
);
1691 ObDereferenceObject(DriverObject
);
1694 /* Return the Status */
1704 IN PDRIVER_OBJECT DriverObject
1707 /* Simply derefence the Object */
1708 ObDereferenceObject(DriverObject
);
1715 * Loads a device driver.
1719 * Name of the service to load (registry key).
1729 NtLoadDriver(IN PUNICODE_STRING DriverServiceName
)
1731 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1732 UNICODE_STRING ImagePath
;
1733 UNICODE_STRING ServiceName
;
1736 PDEVICE_NODE DeviceNode
;
1737 PMODULE_OBJECT ModuleObject
;
1738 PDRIVER_OBJECT DriverObject
;
1741 DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName
);
1744 * Check security privileges
1747 /* FIXME: Uncomment when privileges will be correctly implemented. */
1749 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, KeGetPreviousMode()))
1751 DPRINT("Privilege not held\n");
1752 return STATUS_PRIVILEGE_NOT_HELD
;
1756 RtlInitUnicodeString(&ImagePath
, NULL
);
1759 * Get the service name from the registry key name.
1762 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1764 Start
= DriverServiceName
->Buffer
;
1768 RtlInitUnicodeString(&ServiceName
, Start
);
1774 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
1776 RtlInitUnicodeString(&ImagePath
, NULL
);
1778 QueryTable
[0].Name
= L
"Type";
1779 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1780 QueryTable
[0].EntryContext
= &Type
;
1782 QueryTable
[1].Name
= L
"ImagePath";
1783 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1784 QueryTable
[1].EntryContext
= &ImagePath
;
1786 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1787 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1789 if (!NT_SUCCESS(Status
))
1791 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
1792 RtlFreeUnicodeString(&ImagePath
);
1797 * Normalize the image path for all later processing.
1800 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1802 if (!NT_SUCCESS(Status
))
1804 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1808 DPRINT("FullImagePath: '%S'\n", ImagePath
.Buffer
);
1809 DPRINT("Type: %lx\n", Type
);
1812 * See, if the driver module isn't already loaded
1815 ModuleObject
= LdrGetModuleObject(&ImagePath
);
1816 if (ModuleObject
!= NULL
)
1818 DPRINT("Image already loaded\n");
1819 return STATUS_IMAGE_ALREADY_LOADED
;
1823 * Create device node
1826 /* Use IopRootDeviceNode for now */
1827 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1829 if (!NT_SUCCESS(Status
))
1831 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status
);
1836 * Load the driver module
1839 Status
= LdrLoadModule(&ImagePath
, &ModuleObject
);
1841 if (!NT_SUCCESS(Status
))
1843 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status
);
1844 IopFreeDeviceNode(DeviceNode
);
1849 * Set a service name for the device node
1852 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
1854 Start
= DriverServiceName
->Buffer
;
1857 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, Start
);
1860 * Initialize the driver module
1863 Status
= IopInitializeDriverModule(
1866 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1867 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */),
1870 if (!NT_SUCCESS(Status
))
1872 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status
);
1873 LdrUnloadModule(ModuleObject
);
1874 IopFreeDeviceNode(DeviceNode
);
1878 IopInitializeDevice(DeviceNode
, DriverObject
);
1886 * Unloads a legacy device driver.
1890 * Name of the service to unload (registry key).
1900 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName
)
1902 return IopUnloadDriver(DriverServiceName
, FALSE
);
1906 * IoRegisterDriverReinitialization
1913 IoRegisterDriverReinitialization(
1914 PDRIVER_OBJECT DriverObject
,
1915 PDRIVER_REINITIALIZE ReinitRoutine
,
1918 PDRIVER_REINIT_ITEM ReinitItem
;
1920 ReinitItem
= ExAllocatePool(NonPagedPool
, sizeof(DRIVER_REINIT_ITEM
));
1921 if (ReinitItem
== NULL
)
1924 ReinitItem
->DriverObject
= DriverObject
;
1925 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1926 ReinitItem
->Context
= Context
;
1928 ExInterlockedInsertTailList(
1929 &DriverReinitListHead
,
1930 &ReinitItem
->ItemEntry
,
1931 &DriverReinitListLock
);
1935 * IoAllocateDriverObjectExtension
1942 IoAllocateDriverObjectExtension(
1943 PDRIVER_OBJECT DriverObject
,
1944 PVOID ClientIdentificationAddress
,
1945 ULONG DriverObjectExtensionSize
,
1946 PVOID
*DriverObjectExtension
)
1949 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
1950 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension
;
1952 NewDriverExtension
= ExAllocatePoolWithTag(
1954 sizeof(PRIVATE_DRIVER_EXTENSIONS
) - sizeof(CHAR
) +
1955 DriverObjectExtensionSize
,
1956 TAG_DRIVER_EXTENSION
);
1958 if (NewDriverExtension
== NULL
)
1960 return STATUS_INSUFFICIENT_RESOURCES
;
1963 OldIrql
= KeRaiseIrqlToDpcLevel();
1965 NewDriverExtension
->Link
= DriverObject
->DriverSection
;
1966 NewDriverExtension
->ClientIdentificationAddress
= ClientIdentificationAddress
;
1968 for (DriverExtensions
= DriverObject
->DriverSection
;
1969 DriverExtensions
!= NULL
;
1970 DriverExtensions
= DriverExtensions
->Link
)
1972 if (DriverExtensions
->ClientIdentificationAddress
==
1973 ClientIdentificationAddress
)
1975 KfLowerIrql(OldIrql
);
1976 return STATUS_OBJECT_NAME_COLLISION
;
1980 DriverObject
->DriverSection
= NewDriverExtension
;
1982 KfLowerIrql(OldIrql
);
1984 *DriverObjectExtension
= &NewDriverExtension
->Extension
;
1986 return STATUS_SUCCESS
;
1990 * IoGetDriverObjectExtension
1997 IoGetDriverObjectExtension(
1998 PDRIVER_OBJECT DriverObject
,
1999 PVOID ClientIdentificationAddress
)
2002 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions
;
2004 OldIrql
= KeRaiseIrqlToDpcLevel();
2006 for (DriverExtensions
= DriverObject
->DriverSection
;
2007 DriverExtensions
!= NULL
&&
2008 DriverExtensions
->ClientIdentificationAddress
!=
2009 ClientIdentificationAddress
;
2010 DriverExtensions
= DriverExtensions
->Link
)
2013 KfLowerIrql(OldIrql
);
2015 if (DriverExtensions
== NULL
)
2018 return &DriverExtensions
->Extension
;