2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/driver.c
5 * PURPOSE: Driver Object Management
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Filip Navara (navaraf@reactos.org)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES *******************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ********************************************************************/
19 LIST_ENTRY DriverReinitListHead
;
20 KSPIN_LOCK DriverReinitListLock
;
21 PLIST_ENTRY DriverReinitTailEntry
;
23 PLIST_ENTRY DriverBootReinitTailEntry
;
24 LIST_ENTRY DriverBootReinitListHead
;
25 KSPIN_LOCK DriverBootReinitListLock
;
27 UNICODE_STRING IopHardwareDatabaseKey
=
28 RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
30 POBJECT_TYPE IoDriverObjectType
= NULL
;
32 extern BOOLEAN ExpInTextModeSetup
;
34 /* PRIVATE FUNCTIONS **********************************************************/
37 IopInvalidDeviceRequest(
38 PDEVICE_OBJECT DeviceObject
,
41 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
42 Irp
->IoStatus
.Information
= 0;
43 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
44 return STATUS_INVALID_DEVICE_REQUEST
;
49 IopDeleteDriver(IN PVOID ObjectBody
)
51 PDRIVER_OBJECT DriverObject
= ObjectBody
;
52 PIO_CLIENT_EXTENSION DriverExtension
, NextDriverExtension
;
55 /* Get the extension and loop them */
56 DriverExtension
= IoGetDrvObjExtension(DriverObject
)->
57 ClientDriverExtension
;
58 while (DriverExtension
)
60 /* Get the next one */
61 NextDriverExtension
= DriverExtension
->NextExtension
;
62 ExFreePoolWithTag(DriverExtension
, TAG_DRIVER_EXTENSION
);
65 DriverExtension
= NextDriverExtension
;
68 /* Check if the driver image is still loaded */
69 if (DriverObject
->DriverSection
)
72 //LdrpUnloadImage(DriverObject->DriverSection);
75 /* Check if it has a name */
76 if (DriverObject
->DriverName
.Buffer
)
79 ExFreePool(DriverObject
->DriverName
.Buffer
);
82 #if 0 /* See a bit of hack in IopCreateDriver */
83 /* Check if it has a service key name */
84 if (DriverObject
->DriverExtension
->ServiceKeyName
.Buffer
)
87 ExFreePool(DriverObject
->DriverExtension
->ServiceKeyName
.Buffer
);
94 PDRIVER_OBJECT
*DriverObject
,
95 PUNICODE_STRING ServiceName
,
98 PDRIVER_OBJECT Object
;
99 WCHAR NameBuffer
[MAX_PATH
];
100 UNICODE_STRING DriverName
;
103 DPRINT("IopGetDriverObject(%p '%wZ' %x)\n",
104 DriverObject
, ServiceName
, FileSystem
);
106 *DriverObject
= NULL
;
108 /* Create ModuleName string */
109 if (ServiceName
== NULL
|| ServiceName
->Buffer
== NULL
)
110 /* We don't know which DriverObject we have to open */
111 return STATUS_INVALID_PARAMETER_2
;
113 DriverName
.Buffer
= NameBuffer
;
114 DriverName
.Length
= 0;
115 DriverName
.MaximumLength
= sizeof(NameBuffer
);
117 if (FileSystem
== TRUE
)
118 RtlAppendUnicodeToString(&DriverName
, FILESYSTEM_ROOT_NAME
);
120 RtlAppendUnicodeToString(&DriverName
, DRIVER_ROOT_NAME
);
121 RtlAppendUnicodeStringToString(&DriverName
, ServiceName
);
123 DPRINT("Driver name: '%wZ'\n", &DriverName
);
125 /* Open driver object */
126 Status
= ObReferenceObjectByName(
128 OBJ_OPENIF
| OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, /* Attributes */
129 NULL
, /* PassedAccessState */
130 0, /* DesiredAccess */
133 NULL
, /* ParseContext */
136 if (!NT_SUCCESS(Status
))
138 DPRINT("Failed to reference driver object, status=0x%08x\n", Status
);
142 *DriverObject
= Object
;
144 DPRINT("Driver Object: %p\n", Object
);
146 return STATUS_SUCCESS
;
150 * IopDisplayLoadingMessage
152 * Display 'Loading XXX...' message.
158 IopDisplayLoadingMessage(PVOID ServiceName
,
161 CHAR TextBuffer
[256];
162 PCHAR Extra
= ".sys";
164 if (ExpInTextModeSetup
) return;
167 if (wcsstr(_wcsupr(ServiceName
), L
".SYS")) Extra
= "";
170 KeLoaderBlock
->ArcBootDeviceName
,
171 KeLoaderBlock
->NtBootPathName
,
178 if (strstr(_strupr(ServiceName
), ".SYS")) Extra
= "";
181 KeLoaderBlock
->ArcBootDeviceName
,
182 KeLoaderBlock
->NtBootPathName
,
187 HalDisplayString(TextBuffer
);
191 * IopNormalizeImagePath
193 * Normalize an image path to contain complete path.
197 * The input path and on exit the result path. ImagePath.Buffer
198 * must be allocated by ExAllocatePool on input. Caller is responsible
199 * for freeing the buffer when it's no longer needed.
202 * Name of the service that ImagePath belongs to.
208 * The input image path isn't freed on error.
212 IopNormalizeImagePath(
213 IN OUT PUNICODE_STRING ImagePath
,
214 IN PUNICODE_STRING ServiceName
)
216 UNICODE_STRING InputImagePath
;
221 sizeof(UNICODE_STRING
));
223 if (InputImagePath
.Length
== 0)
225 ImagePath
->Length
= (33 * sizeof(WCHAR
)) + ServiceName
->Length
;
226 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
227 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
228 if (ImagePath
->Buffer
== NULL
)
229 return STATUS_NO_MEMORY
;
231 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\system32\\drivers\\");
232 wcscat(ImagePath
->Buffer
, ServiceName
->Buffer
);
233 wcscat(ImagePath
->Buffer
, L
".sys");
235 if (InputImagePath
.Buffer
[0] != L
'\\')
237 ImagePath
->Length
= (12 * sizeof(WCHAR
)) + InputImagePath
.Length
;
238 ImagePath
->MaximumLength
= ImagePath
->Length
+ sizeof(UNICODE_NULL
);
239 ImagePath
->Buffer
= ExAllocatePool(NonPagedPool
, ImagePath
->MaximumLength
);
240 if (ImagePath
->Buffer
== NULL
)
241 return STATUS_NO_MEMORY
;
243 wcscpy(ImagePath
->Buffer
, L
"\\SystemRoot\\");
244 wcscat(ImagePath
->Buffer
, InputImagePath
.Buffer
);
245 ExFreePool(InputImagePath
.Buffer
);
248 return STATUS_SUCCESS
;
252 * IopLoadServiceModule
254 * Load a module specified by registry settings for service.
258 * Name of the service to load.
265 IopLoadServiceModule(
266 IN PUNICODE_STRING ServiceName
,
267 OUT PLDR_DATA_TABLE_ENTRY
*ModuleObject
)
269 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
271 UNICODE_STRING ServiceImagePath
, CCSName
;
273 OBJECT_ATTRIBUTES ObjectAttributes
;
274 HANDLE CCSKey
, ServiceKey
;
276 DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName
, ModuleObject
);
278 /* FIXME: This check may be removed once the bug is fixed */
279 if (ServiceName
->Buffer
== NULL
)
280 return STATUS_UNSUCCESSFUL
;
282 /* Open CurrentControlSet */
283 RtlInitUnicodeString(&CCSName
,
284 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
285 InitializeObjectAttributes(&ObjectAttributes
,
287 OBJ_CASE_INSENSITIVE
,
290 Status
= ZwOpenKey(&CCSKey
, KEY_READ
, &ObjectAttributes
);
292 if (!NT_SUCCESS(Status
))
294 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status
);
298 /* Open service key */
299 InitializeObjectAttributes(&ObjectAttributes
,
301 OBJ_CASE_INSENSITIVE
,
304 Status
= ZwOpenKey(&ServiceKey
, KEY_READ
, &ObjectAttributes
);
305 if (!NT_SUCCESS(Status
))
307 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status
);
313 * Get information about the service.
316 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
318 RtlInitUnicodeString(&ServiceImagePath
, NULL
);
320 QueryTable
[0].Name
= L
"Start";
321 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
322 QueryTable
[0].EntryContext
= &ServiceStart
;
324 QueryTable
[1].Name
= L
"ImagePath";
325 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
326 QueryTable
[1].EntryContext
= &ServiceImagePath
;
328 Status
= RtlQueryRegistryValues(RTL_REGISTRY_HANDLE
,
329 (PWSTR
)ServiceKey
, QueryTable
, NULL
, NULL
);
334 if (!NT_SUCCESS(Status
))
336 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
341 * Normalize the image path for all later processing.
344 Status
= IopNormalizeImagePath(&ServiceImagePath
, ServiceName
);
346 if (!NT_SUCCESS(Status
))
348 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
353 * Case for disabled drivers
356 if (ServiceStart
>= 4)
358 /* FIXME: Check if it is the right status code */
359 Status
= STATUS_PLUGPLAY_NO_DEVICE
;
363 DPRINT("Loading module\n");
364 Status
= MmLoadSystemImage(&ServiceImagePath
, NULL
, NULL
, 0, (PVOID
)ModuleObject
, NULL
);
367 ExFreePool(ServiceImagePath
.Buffer
);
370 * Now check if the module was loaded successfully.
373 if (!NT_SUCCESS(Status
))
375 DPRINT("Module loading failed (Status %x)\n", Status
);
378 DPRINT("Module loading (Status %x)\n", Status
);
384 * IopInitializeDriverModule
386 * Initalize a loaded driver.
390 * Pointer to device node.
393 * Module object representing the driver. It can be retrieve by
394 * IopLoadServiceModule.
397 * Name of the service (as in registry).
400 * Set to TRUE for file system drivers.
403 * On successful return this contains the driver object representing
408 IopInitializeDriverModule(
409 IN PDEVICE_NODE DeviceNode
,
410 IN PLDR_DATA_TABLE_ENTRY ModuleObject
,
411 IN PUNICODE_STRING ServiceName
,
412 IN BOOLEAN FileSystemDriver
,
413 OUT PDRIVER_OBJECT
*DriverObject
)
415 const WCHAR ServicesKeyName
[] = L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
416 WCHAR NameBuffer
[MAX_PATH
];
417 UNICODE_STRING DriverName
;
418 UNICODE_STRING RegistryKey
;
419 PDRIVER_INITIALIZE DriverEntry
;
420 PDRIVER_OBJECT Driver
;
421 PDEVICE_OBJECT DeviceObject
;
424 DriverEntry
= ModuleObject
->EntryPoint
;
426 if (ServiceName
!= NULL
&& ServiceName
->Length
!= 0)
428 RegistryKey
.Length
= 0;
429 RegistryKey
.MaximumLength
= sizeof(ServicesKeyName
) + ServiceName
->Length
;
430 RegistryKey
.Buffer
= ExAllocatePool(PagedPool
, RegistryKey
.MaximumLength
);
431 if (RegistryKey
.Buffer
== NULL
)
433 return STATUS_INSUFFICIENT_RESOURCES
;
435 RtlAppendUnicodeToString(&RegistryKey
, ServicesKeyName
);
436 RtlAppendUnicodeStringToString(&RegistryKey
, ServiceName
);
440 RtlInitUnicodeString(&RegistryKey
, NULL
);
443 /* Create ModuleName string */
444 if (ServiceName
&& ServiceName
->Length
> 0)
446 if (FileSystemDriver
== TRUE
)
447 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
449 wcscpy(NameBuffer
, DRIVER_ROOT_NAME
);
451 RtlInitUnicodeString(&DriverName
, NameBuffer
);
452 DriverName
.MaximumLength
= sizeof(NameBuffer
);
454 RtlAppendUnicodeStringToString(&DriverName
, ServiceName
);
456 DPRINT("Driver name: '%wZ'\n", &DriverName
);
459 DriverName
.Length
= 0;
461 Status
= IopCreateDriver(
462 DriverName
.Length
> 0 ? &DriverName
: NULL
,
465 ModuleObject
->DllBase
,
466 ModuleObject
->SizeOfImage
,
468 RtlFreeUnicodeString(&RegistryKey
);
470 *DriverObject
= Driver
;
471 if (!NT_SUCCESS(Status
))
473 DPRINT("IopCreateDriver() failed (Status 0x%08lx)\n", Status
);
477 /* Set the driver as initialized */
478 Driver
->Flags
|= DRVO_INITIALIZED
;
479 DeviceObject
= Driver
->DeviceObject
;
482 /* Set every device as initialized too */
483 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
484 DeviceObject
= DeviceObject
->NextDevice
;
487 IopReinitializeDrivers();
489 return STATUS_SUCCESS
;
493 * IopAttachFilterDriversCallback
495 * Internal routine used by IopAttachFilterDrivers.
499 IopAttachFilterDriversCallback(
507 PDEVICE_NODE DeviceNode
= Context
;
508 UNICODE_STRING ServiceName
;
510 PLDR_DATA_TABLE_ENTRY ModuleObject
;
511 PDRIVER_OBJECT DriverObject
;
514 for (Filters
= ValueData
;
515 ((ULONG_PTR
)Filters
- (ULONG_PTR
)ValueData
) < ValueLength
&&
517 Filters
+= (ServiceName
.Length
/ sizeof(WCHAR
)) + 1)
519 DPRINT("Filter Driver: %S (%wZ)\n", Filters
, &DeviceNode
->InstancePath
);
520 ServiceName
.Buffer
= Filters
;
521 ServiceName
.MaximumLength
=
522 ServiceName
.Length
= wcslen(Filters
) * sizeof(WCHAR
);
524 /* Load and initialize the filter driver */
525 Status
= IopLoadServiceModule(&ServiceName
, &ModuleObject
);
526 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
528 if (!NT_SUCCESS(Status
))
531 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, &ServiceName
,
532 FALSE
, &DriverObject
);
533 if (!NT_SUCCESS(Status
))
538 /* get existing DriverObject pointer */
539 Status
= IopGetDriverObject(
543 if (!NT_SUCCESS(Status
))
545 DPRINT1("IopGetDriverObject() returned status 0x%08x!\n", Status
);
550 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
551 if (!NT_SUCCESS(Status
))
555 return STATUS_SUCCESS
;
559 * IopAttachFilterDrivers
561 * Load filter drivers for specified device node.
565 * Set to TRUE for loading lower level filters or FALSE for upper
570 IopAttachFilterDrivers(
571 PDEVICE_NODE DeviceNode
,
574 RTL_QUERY_REGISTRY_TABLE QueryTable
[2] = {{0}};
576 UNICODE_STRING Class
;
577 WCHAR ClassBuffer
[40];
581 * First load the device filters
584 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
586 QueryTable
[0].Name
= L
"LowerFilters";
588 QueryTable
[0].Name
= L
"UpperFilters";
589 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
591 KeyBuffer
= ExAllocatePool(
593 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
594 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
595 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
597 RtlQueryRegistryValues(
598 RTL_REGISTRY_ABSOLUTE
,
605 * Now get the class GUID
609 Class
.MaximumLength
= 40 * sizeof(WCHAR
);
610 Class
.Buffer
= ClassBuffer
;
611 QueryTable
[0].QueryRoutine
= NULL
;
612 QueryTable
[0].Name
= L
"ClassGUID";
613 QueryTable
[0].EntryContext
= &Class
;
614 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
616 Status
= RtlQueryRegistryValues(
617 RTL_REGISTRY_ABSOLUTE
,
623 ExFreePool(KeyBuffer
);
626 * Load the class filter driver
629 if (NT_SUCCESS(Status
))
631 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
633 QueryTable
[0].Name
= L
"LowerFilters";
635 QueryTable
[0].Name
= L
"UpperFilters";
636 QueryTable
[0].EntryContext
= NULL
;
637 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
639 KeyBuffer
= ExAllocatePool(PagedPool
, (58 * sizeof(WCHAR
)) + Class
.Length
);
640 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
641 wcscat(KeyBuffer
, ClassBuffer
);
643 RtlQueryRegistryValues(
644 RTL_REGISTRY_ABSOLUTE
,
650 ExFreePool(KeyBuffer
);
653 return STATUS_SUCCESS
;
658 MiResolveImageReferences(IN PVOID ImageBase
,
659 IN PUNICODE_STRING ImageFileDirectory
,
660 IN PUNICODE_STRING NamePrefix OPTIONAL
,
661 OUT PCHAR
*MissingApi
,
662 OUT PWCHAR
*MissingDriver
,
663 OUT PLOAD_IMPORTS
*LoadImports
);
665 extern KSPIN_LOCK PsLoadedModuleSpinLock
;
668 // Used for images already loaded (boot drivers)
672 LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry
,
673 PUNICODE_STRING FileName
,
674 PLDR_DATA_TABLE_ENTRY
*ModuleObject
)
677 PLDR_DATA_TABLE_ENTRY NewEntry
;
678 UNICODE_STRING BaseName
, BaseDirectory
;
679 PLOAD_IMPORTS LoadedImports
= (PVOID
)-2;
680 PCHAR MissingApiName
, Buffer
;
681 PWCHAR MissingDriverName
;
682 PVOID DriverBase
= LdrEntry
->DllBase
;
684 /* Allocate a buffer we'll use for names */
685 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, MAX_PATH
, TAG_LDR_WSTR
);
689 return STATUS_INSUFFICIENT_RESOURCES
;
692 /* Check for a separator */
693 if (FileName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
698 /* Loop the path until we get to the base name */
699 p
= &FileName
->Buffer
[FileName
->Length
/ sizeof(WCHAR
)];
700 while (*(p
- 1) != OBJ_NAME_PATH_SEPARATOR
) p
--;
703 BaseLength
= (ULONG
)(&FileName
->Buffer
[FileName
->Length
/ sizeof(WCHAR
)] - p
);
704 BaseLength
*= sizeof(WCHAR
);
706 /* Setup the string */
707 BaseName
.Length
= (USHORT
)BaseLength
;
712 /* Otherwise, we already have a base name */
713 BaseName
.Length
= FileName
->Length
;
714 BaseName
.Buffer
= FileName
->Buffer
;
717 /* Setup the maximum length */
718 BaseName
.MaximumLength
= BaseName
.Length
;
720 /* Now compute the base directory */
721 BaseDirectory
= *FileName
;
722 BaseDirectory
.Length
-= BaseName
.Length
;
723 BaseDirectory
.MaximumLength
= BaseDirectory
.Length
;
727 /* Resolve imports */
728 MissingApiName
= Buffer
;
729 Status
= MiResolveImageReferences(DriverBase
,
735 if (!NT_SUCCESS(Status
)) return Status
;
738 *ModuleObject
= LdrEntry
;
739 return STATUS_SUCCESS
;
743 * IopInitializeBuiltinDriver
745 * Initialize a driver that is already loaded in memory.
750 IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
752 PDEVICE_NODE DeviceNode
;
753 PDRIVER_OBJECT DriverObject
;
755 PWCHAR FileNameWithoutPath
;
756 LPWSTR FileExtension
;
757 PUNICODE_STRING ModuleName
= &LdrEntry
->BaseDllName
;
758 UNICODE_STRING ServiceName
;
759 #if 1 // Disable for FreeLDR 2.5
760 UNICODE_STRING ServiceNameWithExtension
;
761 PLDR_DATA_TABLE_ENTRY ModuleObject
;
765 * Display 'Loading XXX...' message
767 IopDisplayLoadingMessage(ModuleName
->Buffer
, TRUE
);
770 * Generate filename without path (not needed by freeldr)
772 FileNameWithoutPath
= wcsrchr(ModuleName
->Buffer
, L
'\\');
773 if (FileNameWithoutPath
== NULL
)
775 FileNameWithoutPath
= ModuleName
->Buffer
;
779 FileNameWithoutPath
++;
785 #if 1 // Remove for FreeLDR 2.5.
786 RtlCreateUnicodeString(&ServiceNameWithExtension
, FileNameWithoutPath
);
787 Status
= LdrProcessDriverModule(LdrEntry
, &ServiceNameWithExtension
, &ModuleObject
);
788 if (!NT_SUCCESS(Status
))
790 CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName
, Status
);
796 * Strip the file extension from ServiceName
798 RtlCreateUnicodeString(&ServiceName
, FileNameWithoutPath
);
799 FileExtension
= wcsrchr(ServiceName
.Buffer
, '.');
800 if (FileExtension
!= NULL
)
802 ServiceName
.Length
-= wcslen(FileExtension
) * sizeof(WCHAR
);
803 FileExtension
[0] = 0;
807 * Determine the right device object
809 /* Use IopRootDeviceNode for now */
810 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &ServiceName
, &DeviceNode
);
811 if (!NT_SUCCESS(Status
))
813 CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName
, Status
);
816 DeviceNode
->ServiceName
= ServiceName
;
819 * Initialize the driver
821 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
822 Status
= IopInitializeDriverModule(DeviceNode
, LdrEntry
,
823 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
825 if (!NT_SUCCESS(Status
))
827 IopFreeDeviceNode(DeviceNode
);
831 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
832 if (NT_SUCCESS(Status
))
834 Status
= IopStartDevice(DeviceNode
);
841 * IopInitializeBootDrivers
843 * Initialize boot drivers and free memory for boot files.
853 IopInitializeBootDrivers(VOID
)
855 PLIST_ENTRY ListHead
, NextEntry
;
856 PLDR_DATA_TABLE_ENTRY LdrEntry
;
857 PDEVICE_NODE DeviceNode
;
858 PDRIVER_OBJECT DriverObject
;
859 LDR_DATA_TABLE_ENTRY ModuleObject
;
861 UNICODE_STRING DriverName
;
863 DPRINT("IopInitializeBootDrivers()");
865 /* Use IopRootDeviceNode for now */
866 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, NULL
, &DeviceNode
);
867 if (!NT_SUCCESS(Status
)) return;
869 /* Setup the module object for the RAW FS Driver */
870 ModuleObject
.DllBase
= NULL
;
871 ModuleObject
.SizeOfImage
= 0;
872 ModuleObject
.EntryPoint
= RawFsDriverEntry
;
873 RtlInitUnicodeString(&DriverName
, L
"RAW");
876 Status
= IopInitializeDriverModule(DeviceNode
,
881 if (!NT_SUCCESS(Status
))
884 IopFreeDeviceNode(DeviceNode
);
888 /* Now initialize the associated device */
889 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
890 if (!NT_SUCCESS(Status
))
893 IopFreeDeviceNode(DeviceNode
);
898 Status
= IopStartDevice(DeviceNode
);
899 if (!NT_SUCCESS(Status
))
902 IopFreeDeviceNode(DeviceNode
);
906 /* Loop the boot modules */
907 ListHead
= &KeLoaderBlock
->LoadOrderListHead
;
908 NextEntry
= ListHead
->Flink
;
909 while (ListHead
!= NextEntry
)
912 LdrEntry
= CONTAINING_RECORD(NextEntry
,
913 LDR_DATA_TABLE_ENTRY
,
917 * HACK: Make sure we're loading a driver
918 * (we should be using BootDriverListHead!)
920 if (wcsstr(_wcsupr(LdrEntry
->BaseDllName
.Buffer
), L
".SYS"))
922 /* Make sure we didn't load this driver already */
923 if (!(LdrEntry
->Flags
& LDRP_ENTRY_INSERTED
))
925 DPRINT("Initializing bootdriver %wZ\n", &LdrEntry
->BaseDllName
);
927 IopInitializeBuiltinDriver(LdrEntry
);
931 /* Go to the next driver */
932 NextEntry
= NextEntry
->Flink
;
935 /* In old ROS, the loader list became empty after this point. Simulate. */
936 InitializeListHead(&KeLoaderBlock
->LoadOrderListHead
);
942 * Unloads a device driver.
946 * Name of the service to unload (registry key).
949 * Whether to unload Plug & Plug or only legacy drivers. If this
950 * parameter is set to FALSE, the routine will unload only legacy
957 * Guard the whole function by SEH.
961 IopUnloadDriver(PUNICODE_STRING DriverServiceName
, BOOLEAN UnloadPnpDrivers
)
963 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
964 UNICODE_STRING ImagePath
;
965 UNICODE_STRING ServiceName
;
966 UNICODE_STRING ObjectName
;
967 PDRIVER_OBJECT DriverObject
;
968 LOAD_UNLOAD_PARAMS LoadParams
;
972 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName
, UnloadPnpDrivers
);
977 * Get the service name from the registry key name
980 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
982 Start
= DriverServiceName
->Buffer
;
986 RtlInitUnicodeString(&ServiceName
, Start
);
989 * Construct the driver object name
992 ObjectName
.Length
= (wcslen(Start
) + 8) * sizeof(WCHAR
);
993 ObjectName
.MaximumLength
= ObjectName
.Length
+ sizeof(WCHAR
);
994 ObjectName
.Buffer
= ExAllocatePool(PagedPool
, ObjectName
.MaximumLength
);
995 wcscpy(ObjectName
.Buffer
, L
"\\Driver\\");
996 memcpy(ObjectName
.Buffer
+ 8, Start
, ObjectName
.Length
- 8 * sizeof(WCHAR
));
997 ObjectName
.Buffer
[ObjectName
.Length
/sizeof(WCHAR
)] = 0;
1000 * Find the driver object
1003 Status
= ObReferenceObjectByName(&ObjectName
, 0, 0, 0, IoDriverObjectType
,
1004 KernelMode
, 0, (PVOID
*)&DriverObject
);
1006 if (!NT_SUCCESS(Status
))
1008 DPRINT1("Can't locate driver object for %wZ\n", &ObjectName
);
1013 * Free the buffer for driver object name
1016 ExFreePool(ObjectName
.Buffer
);
1019 * Get path of service...
1022 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1024 RtlInitUnicodeString(&ImagePath
, NULL
);
1026 QueryTable
[0].Name
= L
"ImagePath";
1027 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1028 QueryTable
[0].EntryContext
= &ImagePath
;
1030 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1031 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1033 if (!NT_SUCCESS(Status
))
1035 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1040 * Normalize the image path for all later processing.
1043 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1045 if (!NT_SUCCESS(Status
))
1047 DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1052 * Free the service path
1055 ExFreePool(ImagePath
.Buffer
);
1058 * Unload the module and release the references to the device object
1061 /* Call the load/unload routine, depending on current process */
1062 if (DriverObject
->DriverUnload
)
1064 if (PsGetCurrentProcess() == PsInitialSystemProcess
)
1066 /* Just call right away */
1067 (*DriverObject
->DriverUnload
)(DriverObject
);
1071 /* Load/Unload must be called from system process */
1073 /* Prepare parameters block */
1074 LoadParams
.DriverObject
= DriverObject
;
1075 KeInitializeEvent(&LoadParams
.Event
, NotificationEvent
, FALSE
);
1077 ExInitializeWorkItem(&LoadParams
.WorkItem
,
1078 (PWORKER_THREAD_ROUTINE
)IopLoadUnloadDriver
,
1079 (PVOID
)&LoadParams
);
1082 ExQueueWorkItem(&LoadParams
.WorkItem
, DelayedWorkQueue
);
1084 /* And wait when it completes */
1085 KeWaitForSingleObject(&LoadParams
.Event
, UserRequest
, KernelMode
,
1090 ObDereferenceObject(DriverObject
);
1091 ObDereferenceObject(DriverObject
);
1092 MmUnloadSystemImage(DriverObject
->DriverSection
);
1094 return STATUS_SUCCESS
;
1099 IopReinitializeDrivers(VOID
)
1101 PDRIVER_REINIT_ITEM ReinitItem
;
1104 /* Get the first entry and start looping */
1105 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1106 &DriverReinitListLock
);
1110 ReinitItem
= CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1112 /* Increment reinitialization counter */
1113 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1115 /* Remove the device object flag */
1116 ReinitItem
->DriverObject
->Flags
&= ~DRVO_REINIT_REGISTERED
;
1118 /* Call the routine */
1119 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1120 ReinitItem
->Context
,
1121 ReinitItem
->DriverObject
->
1122 DriverExtension
->Count
);
1124 /* Free the entry */
1127 /* Move to the next one */
1128 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1129 &DriverReinitListLock
);
1135 IopReinitializeBootDrivers(VOID
)
1137 PDRIVER_REINIT_ITEM ReinitItem
;
1140 /* Get the first entry and start looping */
1141 Entry
= ExInterlockedRemoveHeadList(&DriverBootReinitListHead
,
1142 &DriverBootReinitListLock
);
1146 ReinitItem
= CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1148 /* Increment reinitialization counter */
1149 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1151 /* Remove the device object flag */
1152 ReinitItem
->DriverObject
->Flags
&= ~DRVO_BOOTREINIT_REGISTERED
;
1154 /* Call the routine */
1155 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1156 ReinitItem
->Context
,
1157 ReinitItem
->DriverObject
->
1158 DriverExtension
->Count
);
1160 /* Free the entry */
1163 /* Move to the next one */
1164 Entry
= ExInterlockedRemoveHeadList(&DriverBootReinitListHead
,
1165 &DriverBootReinitListLock
);
1171 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL
,
1172 IN PDRIVER_INITIALIZE InitializationFunction
,
1173 IN PUNICODE_STRING RegistryPath
,
1175 IN ULONG SizeOfImage
,
1176 OUT PDRIVER_OBJECT
*pDriverObject
)
1178 WCHAR NameBuffer
[100];
1180 UNICODE_STRING LocalDriverName
;
1182 OBJECT_ATTRIBUTES ObjectAttributes
;
1184 PDRIVER_OBJECT DriverObject
;
1185 UNICODE_STRING ServiceKeyName
;
1187 ULONG i
, RetryCount
= 0;
1190 /* First, create a unique name for the driver if we don't have one */
1193 /* Create a random name and set up the string*/
1194 NameLength
= (USHORT
)swprintf(NameBuffer
,
1197 LocalDriverName
.Length
= NameLength
* sizeof(WCHAR
);
1198 LocalDriverName
.MaximumLength
= LocalDriverName
.Length
+ sizeof(UNICODE_NULL
);
1199 LocalDriverName
.Buffer
= NameBuffer
;
1203 /* So we can avoid another code path, use a local var */
1204 LocalDriverName
= *DriverName
;
1207 /* Initialize the Attributes */
1208 ObjectSize
= sizeof(DRIVER_OBJECT
) + sizeof(EXTENDED_DRIVER_EXTENSION
);
1209 InitializeObjectAttributes(&ObjectAttributes
,
1211 OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
1215 /* Create the Object */
1216 Status
= ObCreateObject(KernelMode
,
1224 (PVOID
*)&DriverObject
);
1225 if (!NT_SUCCESS(Status
)) return Status
;
1227 DPRINT("IopCreateDriver(): created DO %p\n", DriverObject
);
1229 /* Set up the Object */
1230 RtlZeroMemory(DriverObject
, ObjectSize
);
1231 DriverObject
->Type
= IO_TYPE_DRIVER
;
1232 DriverObject
->Size
= sizeof(DRIVER_OBJECT
);
1233 DriverObject
->Flags
= DRVO_BUILTIN_DRIVER
;
1234 DriverObject
->DriverExtension
= (PDRIVER_EXTENSION
)(DriverObject
+ 1);
1235 DriverObject
->DriverExtension
->DriverObject
= DriverObject
;
1236 DriverObject
->DriverInit
= InitializationFunction
;
1238 /* Loop all Major Functions */
1239 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
1241 /* Invalidate each function */
1242 DriverObject
->MajorFunction
[i
] = IopInvalidDeviceRequest
;
1245 /* Set up the service key name buffer */
1246 ServiceKeyName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
1247 LocalDriverName
.Length
+
1250 if (!ServiceKeyName
.Buffer
)
1253 ObMakeTemporaryObject(DriverObject
);
1254 ObDereferenceObject(DriverObject
);
1255 return STATUS_INSUFFICIENT_RESOURCES
;
1258 /* Fill out the key data and copy the buffer */
1259 ServiceKeyName
.Length
= LocalDriverName
.Length
;
1260 ServiceKeyName
.MaximumLength
= LocalDriverName
.MaximumLength
;
1261 RtlCopyMemory(ServiceKeyName
.Buffer
,
1262 LocalDriverName
.Buffer
,
1263 LocalDriverName
.Length
);
1265 /* Null-terminate it and set it */
1266 ServiceKeyName
.Buffer
[ServiceKeyName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1267 DriverObject
->DriverExtension
->ServiceKeyName
= ServiceKeyName
;
1269 /* Also store it in the Driver Object. This is a bit of a hack. */
1270 RtlCopyMemory(&DriverObject
->DriverName
,
1272 sizeof(UNICODE_STRING
));
1274 /* Add the Object and get its handle */
1275 Status
= ObInsertObject(DriverObject
,
1282 /* Eliminate small possibility when this function is called more than
1283 once in a row, and KeTickCount doesn't get enough time to change */
1284 if (!DriverName
&& (Status
== STATUS_OBJECT_NAME_COLLISION
) && (RetryCount
< 100))
1290 if (!NT_SUCCESS(Status
)) return Status
;
1292 /* Now reference it */
1293 Status
= ObReferenceObjectByHandle(hDriver
,
1297 (PVOID
*)&DriverObject
,
1299 if (!NT_SUCCESS(Status
))
1302 ObMakeTemporaryObject(DriverObject
);
1303 ObDereferenceObject(DriverObject
);
1307 /* Close the extra handle */
1310 DriverObject
->HardwareDatabase
= &IopHardwareDatabaseKey
;
1311 DriverObject
->DriverStart
= DllBase
;
1312 DriverObject
->DriverSize
= SizeOfImage
;
1314 /* Finally, call its init function */
1315 DPRINT("RegistryKey: %wZ\n", RegistryPath
);
1316 DPRINT("Calling driver entrypoint at %p\n", InitializationFunction
);
1317 Status
= (*InitializationFunction
)(DriverObject
, RegistryPath
);
1318 if (!NT_SUCCESS(Status
))
1320 /* If it didn't work, then kill the object */
1321 DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName
, Status
);
1322 ObMakeTemporaryObject(DriverObject
);
1323 ObDereferenceObject(DriverObject
);
1327 /* Returns to caller the object */
1328 *pDriverObject
= DriverObject
;
1331 /* Return the Status */
1335 /* PUBLIC FUNCTIONS ***********************************************************/
1342 IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL
,
1343 IN PDRIVER_INITIALIZE InitializationFunction
)
1345 PDRIVER_OBJECT DriverObject
;
1346 return IopCreateDriver(DriverName
, InitializationFunction
, NULL
, 0, 0, &DriverObject
);
1354 IoDeleteDriver(IN PDRIVER_OBJECT DriverObject
)
1356 /* Simply derefence the Object */
1357 ObDereferenceObject(DriverObject
);
1365 IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject
,
1366 IN PDRIVER_REINITIALIZE ReinitRoutine
,
1369 PDRIVER_REINIT_ITEM ReinitItem
;
1371 /* Allocate the entry */
1372 ReinitItem
= ExAllocatePoolWithTag(NonPagedPool
,
1373 sizeof(DRIVER_REINIT_ITEM
),
1375 if (!ReinitItem
) return;
1378 ReinitItem
->DriverObject
= DriverObject
;
1379 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1380 ReinitItem
->Context
= Context
;
1382 /* Set the Driver Object flag and insert the entry into the list */
1383 DriverObject
->Flags
|= DRVO_BOOTREINIT_REGISTERED
;
1384 ExInterlockedInsertTailList(&DriverBootReinitListHead
,
1385 &ReinitItem
->ItemEntry
,
1386 &DriverBootReinitListLock
);
1394 IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject
,
1395 IN PDRIVER_REINITIALIZE ReinitRoutine
,
1398 PDRIVER_REINIT_ITEM ReinitItem
;
1400 /* Allocate the entry */
1401 ReinitItem
= ExAllocatePoolWithTag(NonPagedPool
,
1402 sizeof(DRIVER_REINIT_ITEM
),
1404 if (!ReinitItem
) return;
1407 ReinitItem
->DriverObject
= DriverObject
;
1408 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1409 ReinitItem
->Context
= Context
;
1411 /* Set the Driver Object flag and insert the entry into the list */
1412 DriverObject
->Flags
|= DRVO_REINIT_REGISTERED
;
1413 ExInterlockedInsertTailList(&DriverReinitListHead
,
1414 &ReinitItem
->ItemEntry
,
1415 &DriverReinitListLock
);
1423 IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject
,
1424 IN PVOID ClientIdentificationAddress
,
1425 IN ULONG DriverObjectExtensionSize
,
1426 OUT PVOID
*DriverObjectExtension
)
1429 PIO_CLIENT_EXTENSION DriverExtensions
, NewDriverExtension
;
1430 BOOLEAN Inserted
= FALSE
;
1432 /* Assume failure */
1433 *DriverObjectExtension
= NULL
;
1435 /* Allocate the extension */
1436 NewDriverExtension
= ExAllocatePoolWithTag(NonPagedPool
,
1437 sizeof(IO_CLIENT_EXTENSION
) +
1438 DriverObjectExtensionSize
,
1439 TAG_DRIVER_EXTENSION
);
1440 if (!NewDriverExtension
) return STATUS_INSUFFICIENT_RESOURCES
;
1442 /* Clear the extension for teh caller */
1443 RtlZeroMemory(NewDriverExtension
,
1444 sizeof(IO_CLIENT_EXTENSION
) + DriverObjectExtensionSize
);
1447 OldIrql
= KeRaiseIrqlToDpcLevel();
1449 /* Fill out the extension */
1450 NewDriverExtension
->ClientIdentificationAddress
= ClientIdentificationAddress
;
1452 /* Loop the current extensions */
1453 DriverExtensions
= IoGetDrvObjExtension(DriverObject
)->
1454 ClientDriverExtension
;
1455 while (DriverExtensions
)
1457 /* Check if the identifier matches */
1458 if (DriverExtensions
->ClientIdentificationAddress
==
1459 ClientIdentificationAddress
)
1461 /* We have a collision, break out */
1465 /* Go to the next one */
1466 DriverExtensions
= DriverExtensions
->NextExtension
;
1469 /* Check if we didn't collide */
1470 if (!DriverExtensions
)
1472 /* Link this one in */
1473 NewDriverExtension
->NextExtension
=
1474 IoGetDrvObjExtension(DriverObject
)->ClientDriverExtension
;
1475 IoGetDrvObjExtension(DriverObject
)->ClientDriverExtension
=
1480 /* Release the lock */
1481 KeLowerIrql(OldIrql
);
1483 /* Check if insertion failed */
1486 /* Free the entry and fail */
1487 ExFreePool(NewDriverExtension
);
1488 return STATUS_OBJECT_NAME_COLLISION
;
1491 /* Otherwise, return the pointer */
1492 *DriverObjectExtension
= NewDriverExtension
+ 1;
1493 return STATUS_SUCCESS
;
1501 IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject
,
1502 IN PVOID ClientIdentificationAddress
)
1505 PIO_CLIENT_EXTENSION DriverExtensions
;
1508 OldIrql
= KeRaiseIrqlToDpcLevel();
1510 /* Loop the list until we find the right one */
1511 DriverExtensions
= IoGetDrvObjExtension(DriverObject
)->ClientDriverExtension
;
1512 while (DriverExtensions
)
1514 /* Check for a match */
1515 if (DriverExtensions
->ClientIdentificationAddress
==
1516 ClientIdentificationAddress
)
1523 DriverExtensions
= DriverExtensions
->NextExtension
;
1527 KeLowerIrql(OldIrql
);
1529 /* Return nothing or the extension */
1530 if (!DriverExtensions
) return NULL
;
1531 return DriverExtensions
+ 1;
1535 IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams
)
1537 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1538 UNICODE_STRING ImagePath
;
1539 UNICODE_STRING ServiceName
;
1542 PDEVICE_NODE DeviceNode
;
1543 PDRIVER_OBJECT DriverObject
;
1544 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1547 /* Check if it's an unload request */
1548 if (LoadParams
->DriverObject
)
1550 (*LoadParams
->DriverObject
->DriverUnload
)(LoadParams
->DriverObject
);
1552 /* Return success and signal the event */
1553 LoadParams
->Status
= STATUS_SUCCESS
;
1554 (VOID
)KeSetEvent(&LoadParams
->Event
, 0, FALSE
);
1558 RtlInitUnicodeString(&ImagePath
, NULL
);
1561 * Get the service name from the registry key name.
1563 ASSERT(LoadParams
->ServiceName
->Length
>= sizeof(WCHAR
));
1565 ServiceName
= *LoadParams
->ServiceName
;
1566 cur
= LoadParams
->ServiceName
->Buffer
+
1567 (LoadParams
->ServiceName
->Length
/ sizeof(WCHAR
)) - 1;
1568 while (LoadParams
->ServiceName
->Buffer
!= cur
)
1572 ServiceName
.Buffer
= cur
+ 1;
1573 ServiceName
.Length
= LoadParams
->ServiceName
->Length
-
1574 (USHORT
)((ULONG_PTR
)ServiceName
.Buffer
-
1575 (ULONG_PTR
)LoadParams
->ServiceName
->Buffer
);
1585 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
1587 RtlInitUnicodeString(&ImagePath
, NULL
);
1589 QueryTable
[0].Name
= L
"Type";
1590 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1591 QueryTable
[0].EntryContext
= &Type
;
1593 QueryTable
[1].Name
= L
"ImagePath";
1594 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1595 QueryTable
[1].EntryContext
= &ImagePath
;
1597 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1598 LoadParams
->ServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
1600 if (!NT_SUCCESS(Status
))
1602 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
1603 ExFreePool(ImagePath
.Buffer
);
1604 LoadParams
->Status
= Status
;
1605 (VOID
)KeSetEvent(&LoadParams
->Event
, 0, FALSE
);
1610 * Normalize the image path for all later processing.
1613 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1615 if (!NT_SUCCESS(Status
))
1617 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1618 LoadParams
->Status
= Status
;
1619 (VOID
)KeSetEvent(&LoadParams
->Event
, 0, FALSE
);
1623 DPRINT("FullImagePath: '%wZ'\n", &ImagePath
);
1624 DPRINT("Type: %lx\n", Type
);
1627 * Create device node
1630 /* Use IopRootDeviceNode for now */
1631 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &ServiceName
, &DeviceNode
);
1633 if (!NT_SUCCESS(Status
))
1635 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status
);
1636 LoadParams
->Status
= Status
;
1637 (VOID
)KeSetEvent(&LoadParams
->Event
, 0, FALSE
);
1641 /* Get existing DriverObject pointer (in case the driver has
1642 already been loaded and initialized) */
1643 Status
= IopGetDriverObject(
1646 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1647 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */));
1649 if (!NT_SUCCESS(Status
))
1652 * Load the driver module
1655 Status
= MmLoadSystemImage(&ImagePath
, NULL
, NULL
, 0, (PVOID
)&ModuleObject
, NULL
);
1656 if (!NT_SUCCESS(Status
) && Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1658 DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status
);
1659 IopFreeDeviceNode(DeviceNode
);
1660 LoadParams
->Status
= Status
;
1661 (VOID
)KeSetEvent(&LoadParams
->Event
, 0, FALSE
);
1666 * Set a service name for the device node
1669 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, ServiceName
.Buffer
);
1672 * Initialize the driver module if it's loaded for the first time
1674 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1676 Status
= IopInitializeDriverModule(
1679 &DeviceNode
->ServiceName
,
1680 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1681 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */),
1684 if (!NT_SUCCESS(Status
))
1686 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status
);
1687 MmUnloadSystemImage(ModuleObject
);
1688 IopFreeDeviceNode(DeviceNode
);
1689 LoadParams
->Status
= Status
;
1690 (VOID
)KeSetEvent(&LoadParams
->Event
, 0, FALSE
);
1695 /* We have a driver for this DeviceNode */
1696 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
1699 IopInitializeDevice(DeviceNode
, DriverObject
);
1700 LoadParams
->Status
= IopStartDevice(DeviceNode
);
1701 (VOID
)KeSetEvent(&LoadParams
->Event
, 0, FALSE
);
1707 * Loads a device driver.
1711 * Name of the service to load (registry key).
1720 NtLoadDriver(IN PUNICODE_STRING DriverServiceName
)
1722 UNICODE_STRING CapturedDriverServiceName
= {0};
1723 KPROCESSOR_MODE PreviousMode
;
1724 LOAD_UNLOAD_PARAMS LoadParams
;
1729 PreviousMode
= KeGetPreviousMode();
1732 * Check security privileges
1735 /* FIXME: Uncomment when privileges will be correctly implemented. */
1737 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1739 DPRINT("Privilege not held\n");
1740 return STATUS_PRIVILEGE_NOT_HELD
;
1744 Status
= ProbeAndCaptureUnicodeString(&CapturedDriverServiceName
,
1747 if (!NT_SUCCESS(Status
))
1752 DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName
);
1754 LoadParams
.ServiceName
= &CapturedDriverServiceName
;
1755 LoadParams
.DriverObject
= NULL
;
1756 KeInitializeEvent(&LoadParams
.Event
, NotificationEvent
, FALSE
);
1758 /* Call the load/unload routine, depending on current process */
1759 if (PsGetCurrentProcess() == PsInitialSystemProcess
)
1761 /* Just call right away */
1762 IopLoadUnloadDriver(&LoadParams
);
1766 /* Load/Unload must be called from system process */
1767 ExInitializeWorkItem(&LoadParams
.WorkItem
,
1768 (PWORKER_THREAD_ROUTINE
)IopLoadUnloadDriver
,
1769 (PVOID
)&LoadParams
);
1772 ExQueueWorkItem(&LoadParams
.WorkItem
, DelayedWorkQueue
);
1774 /* And wait when it completes */
1775 KeWaitForSingleObject(&LoadParams
.Event
, UserRequest
, KernelMode
,
1779 ReleaseCapturedUnicodeString(&CapturedDriverServiceName
,
1782 return LoadParams
.Status
;
1788 * Unloads a legacy device driver.
1792 * Name of the service to unload (registry key).
1802 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName
)
1804 return IopUnloadDriver(DriverServiceName
, FALSE
);