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
;
274 DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName
, ModuleObject
);
276 /* FIXME: This check may be removed once the bug is fixed */
277 if (ServiceName
->Buffer
== NULL
)
278 return STATUS_UNSUCCESSFUL
;
281 * Get information about the service.
284 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
286 RtlInitUnicodeString(&ServiceImagePath
, NULL
);
288 QueryTable
[0].Name
= L
"Start";
289 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
290 QueryTable
[0].EntryContext
= &ServiceStart
;
292 QueryTable
[1].Name
= L
"ImagePath";
293 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
294 QueryTable
[1].EntryContext
= &ServiceImagePath
;
296 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
297 ServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
299 if (!NT_SUCCESS(Status
))
301 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
306 * Normalize the image path for all later processing.
309 Status
= IopNormalizeImagePath(&ServiceImagePath
, ServiceName
);
311 if (!NT_SUCCESS(Status
))
313 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
318 * Case for disabled drivers
321 if (ServiceStart
>= 4)
323 /* FIXME: Check if it is the right status code */
324 Status
= STATUS_PLUGPLAY_NO_DEVICE
;
328 DPRINT("Loading module\n");
329 Status
= MmLoadSystemImage(&ServiceImagePath
, NULL
, NULL
, 0, (PVOID
)ModuleObject
, NULL
);
332 ExFreePool(ServiceImagePath
.Buffer
);
335 * Now check if the module was loaded successfully.
338 if (!NT_SUCCESS(Status
))
340 DPRINT("Module loading failed (Status %x)\n", Status
);
343 DPRINT("Module loading (Status %x)\n", Status
);
349 * IopInitializeDriverModule
351 * Initalize a loaded driver.
355 * Pointer to device node.
358 * Module object representing the driver. It can be retrieve by
359 * IopLoadServiceModule.
362 * Name of the service (as in registry).
365 * Set to TRUE for file system drivers.
368 * On successful return this contains the driver object representing
373 IopInitializeDriverModule(
374 IN PDEVICE_NODE DeviceNode
,
375 IN PLDR_DATA_TABLE_ENTRY ModuleObject
,
376 IN PUNICODE_STRING ServiceName
,
377 IN BOOLEAN FileSystemDriver
,
378 OUT PDRIVER_OBJECT
*DriverObject
)
380 const WCHAR ServicesKeyName
[] = L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
381 WCHAR NameBuffer
[MAX_PATH
];
382 UNICODE_STRING DriverName
;
383 UNICODE_STRING RegistryKey
;
384 PDRIVER_INITIALIZE DriverEntry
;
385 PDRIVER_OBJECT Driver
;
386 PDEVICE_OBJECT DeviceObject
;
389 DriverEntry
= ModuleObject
->EntryPoint
;
391 if (ServiceName
!= NULL
&& ServiceName
->Length
!= 0)
393 RegistryKey
.Length
= 0;
394 RegistryKey
.MaximumLength
= sizeof(ServicesKeyName
) + ServiceName
->Length
;
395 RegistryKey
.Buffer
= ExAllocatePool(PagedPool
, RegistryKey
.MaximumLength
);
396 if (RegistryKey
.Buffer
== NULL
)
398 return STATUS_INSUFFICIENT_RESOURCES
;
400 RtlAppendUnicodeToString(&RegistryKey
, ServicesKeyName
);
401 RtlAppendUnicodeStringToString(&RegistryKey
, ServiceName
);
405 RtlInitUnicodeString(&RegistryKey
, NULL
);
408 /* Create ModuleName string */
409 if (ServiceName
&& ServiceName
->Length
> 0)
411 if (FileSystemDriver
== TRUE
)
412 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
414 wcscpy(NameBuffer
, DRIVER_ROOT_NAME
);
415 wcscat(NameBuffer
, ServiceName
->Buffer
);
417 RtlInitUnicodeString(&DriverName
, NameBuffer
);
418 DPRINT("Driver name: '%wZ'\n", &DriverName
);
421 DriverName
.Length
= 0;
423 Status
= IopCreateDriver(
424 DriverName
.Length
> 0 ? &DriverName
: NULL
,
427 ModuleObject
->DllBase
,
428 ModuleObject
->SizeOfImage
,
430 RtlFreeUnicodeString(&RegistryKey
);
432 *DriverObject
= Driver
;
433 if (!NT_SUCCESS(Status
))
435 DPRINT("IopCreateDriver() failed (Status 0x%08lx)\n", Status
);
439 /* Set the driver as initialized */
440 Driver
->Flags
|= DRVO_INITIALIZED
;
441 DeviceObject
= Driver
->DeviceObject
;
444 /* Set every device as initialized too */
445 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
446 DeviceObject
= DeviceObject
->NextDevice
;
449 IopReinitializeDrivers();
451 return STATUS_SUCCESS
;
455 * IopAttachFilterDriversCallback
457 * Internal routine used by IopAttachFilterDrivers.
461 IopAttachFilterDriversCallback(
469 PDEVICE_NODE DeviceNode
= Context
;
470 UNICODE_STRING ServiceName
;
472 PLDR_DATA_TABLE_ENTRY ModuleObject
;
473 PDRIVER_OBJECT DriverObject
;
476 for (Filters
= ValueData
;
477 ((ULONG_PTR
)Filters
- (ULONG_PTR
)ValueData
) < ValueLength
&&
479 Filters
+= (ServiceName
.Length
/ sizeof(WCHAR
)) + 1)
481 DPRINT("Filter Driver: %S (%wZ)\n", Filters
, &DeviceNode
->InstancePath
);
482 ServiceName
.Buffer
= Filters
;
483 ServiceName
.MaximumLength
=
484 ServiceName
.Length
= wcslen(Filters
) * sizeof(WCHAR
);
486 /* Load and initialize the filter driver */
487 Status
= IopLoadServiceModule(&ServiceName
, &ModuleObject
);
488 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
490 if (!NT_SUCCESS(Status
))
493 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, &ServiceName
,
494 FALSE
, &DriverObject
);
495 if (!NT_SUCCESS(Status
))
500 /* get existing DriverObject pointer */
501 Status
= IopGetDriverObject(
505 if (!NT_SUCCESS(Status
))
507 DPRINT1("IopGetDriverObject() returned status 0x%08x!\n", Status
);
512 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
513 if (!NT_SUCCESS(Status
))
517 return STATUS_SUCCESS
;
521 * IopAttachFilterDrivers
523 * Load filter drivers for specified device node.
527 * Set to TRUE for loading lower level filters or FALSE for upper
532 IopAttachFilterDrivers(
533 PDEVICE_NODE DeviceNode
,
536 RTL_QUERY_REGISTRY_TABLE QueryTable
[2] = {{0}};
538 UNICODE_STRING Class
;
539 WCHAR ClassBuffer
[40];
543 * First load the device filters
546 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
548 QueryTable
[0].Name
= L
"LowerFilters";
550 QueryTable
[0].Name
= L
"UpperFilters";
551 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
553 KeyBuffer
= ExAllocatePool(
555 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
556 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
557 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
559 RtlQueryRegistryValues(
560 RTL_REGISTRY_ABSOLUTE
,
567 * Now get the class GUID
571 Class
.MaximumLength
= 40 * sizeof(WCHAR
);
572 Class
.Buffer
= ClassBuffer
;
573 QueryTable
[0].QueryRoutine
= NULL
;
574 QueryTable
[0].Name
= L
"ClassGUID";
575 QueryTable
[0].EntryContext
= &Class
;
576 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
578 Status
= RtlQueryRegistryValues(
579 RTL_REGISTRY_ABSOLUTE
,
585 ExFreePool(KeyBuffer
);
588 * Load the class filter driver
591 if (NT_SUCCESS(Status
))
593 QueryTable
[0].QueryRoutine
= IopAttachFilterDriversCallback
;
595 QueryTable
[0].Name
= L
"LowerFilters";
597 QueryTable
[0].Name
= L
"UpperFilters";
598 QueryTable
[0].EntryContext
= NULL
;
599 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
601 KeyBuffer
= ExAllocatePool(PagedPool
, (58 * sizeof(WCHAR
)) + Class
.Length
);
602 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
603 wcscat(KeyBuffer
, ClassBuffer
);
605 RtlQueryRegistryValues(
606 RTL_REGISTRY_ABSOLUTE
,
612 ExFreePool(KeyBuffer
);
615 return STATUS_SUCCESS
;
620 MiResolveImageReferences(IN PVOID ImageBase
,
621 IN PUNICODE_STRING ImageFileDirectory
,
622 IN PUNICODE_STRING NamePrefix OPTIONAL
,
623 OUT PCHAR
*MissingApi
,
624 OUT PWCHAR
*MissingDriver
,
625 OUT PLOAD_IMPORTS
*LoadImports
);
627 extern KSPIN_LOCK PsLoadedModuleSpinLock
;
630 // Used for images already loaded (boot drivers)
634 LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry
,
635 PUNICODE_STRING FileName
,
636 PLDR_DATA_TABLE_ENTRY
*ModuleObject
)
639 PLDR_DATA_TABLE_ENTRY NewEntry
;
640 UNICODE_STRING BaseName
, BaseDirectory
;
641 PLOAD_IMPORTS LoadedImports
= (PVOID
)-2;
642 PCHAR MissingApiName
, Buffer
;
643 PWCHAR MissingDriverName
;
644 PVOID DriverBase
= LdrEntry
->DllBase
;
646 /* Allocate a buffer we'll use for names */
647 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, MAX_PATH
, TAG_LDR_WSTR
);
651 return STATUS_INSUFFICIENT_RESOURCES
;
654 /* Check for a separator */
655 if (FileName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
660 /* Loop the path until we get to the base name */
661 p
= &FileName
->Buffer
[FileName
->Length
/ sizeof(WCHAR
)];
662 while (*(p
- 1) != OBJ_NAME_PATH_SEPARATOR
) p
--;
665 BaseLength
= (ULONG
)(&FileName
->Buffer
[FileName
->Length
/ sizeof(WCHAR
)] - p
);
666 BaseLength
*= sizeof(WCHAR
);
668 /* Setup the string */
669 BaseName
.Length
= (USHORT
)BaseLength
;
674 /* Otherwise, we already have a base name */
675 BaseName
.Length
= FileName
->Length
;
676 BaseName
.Buffer
= FileName
->Buffer
;
679 /* Setup the maximum length */
680 BaseName
.MaximumLength
= BaseName
.Length
;
682 /* Now compute the base directory */
683 BaseDirectory
= *FileName
;
684 BaseDirectory
.Length
-= BaseName
.Length
;
685 BaseDirectory
.MaximumLength
= BaseDirectory
.Length
;
689 /* Resolve imports */
690 MissingApiName
= Buffer
;
691 Status
= MiResolveImageReferences(DriverBase
,
697 if (!NT_SUCCESS(Status
)) return Status
;
700 *ModuleObject
= LdrEntry
;
701 return STATUS_SUCCESS
;
705 * IopInitializeBuiltinDriver
707 * Initialize a driver that is already loaded in memory.
712 IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
714 PDEVICE_NODE DeviceNode
;
715 PDRIVER_OBJECT DriverObject
;
717 PWCHAR FileNameWithoutPath
;
718 LPWSTR FileExtension
;
719 PUNICODE_STRING ModuleName
= &LdrEntry
->BaseDllName
;
720 UNICODE_STRING ServiceName
;
721 #if 1 // Disable for FreeLDR 2.5
722 UNICODE_STRING ServiceNameWithExtension
;
723 PLDR_DATA_TABLE_ENTRY ModuleObject
;
727 * Display 'Loading XXX...' message
729 IopDisplayLoadingMessage(ModuleName
->Buffer
, TRUE
);
732 * Generate filename without path (not needed by freeldr)
734 FileNameWithoutPath
= wcsrchr(ModuleName
->Buffer
, L
'\\');
735 if (FileNameWithoutPath
== NULL
)
737 FileNameWithoutPath
= ModuleName
->Buffer
;
741 FileNameWithoutPath
++;
747 #if 1 // Remove for FreeLDR 2.5.
748 RtlCreateUnicodeString(&ServiceNameWithExtension
, FileNameWithoutPath
);
749 Status
= LdrProcessDriverModule(LdrEntry
, &ServiceNameWithExtension
, &ModuleObject
);
750 if (!NT_SUCCESS(Status
))
752 CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName
, Status
);
758 * Strip the file extension from ServiceName
760 RtlCreateUnicodeString(&ServiceName
, FileNameWithoutPath
);
761 FileExtension
= wcsrchr(ServiceName
.Buffer
, '.');
762 if (FileExtension
!= NULL
)
764 ServiceName
.Length
-= wcslen(FileExtension
) * sizeof(WCHAR
);
765 FileExtension
[0] = 0;
769 * Determine the right device object
771 /* Use IopRootDeviceNode for now */
772 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &ServiceName
, &DeviceNode
);
773 if (!NT_SUCCESS(Status
))
775 CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName
, Status
);
778 DeviceNode
->ServiceName
= ServiceName
;
781 * Initialize the driver
783 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
784 Status
= IopInitializeDriverModule(DeviceNode
, LdrEntry
,
785 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
787 if (!NT_SUCCESS(Status
))
789 IopFreeDeviceNode(DeviceNode
);
793 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
794 if (NT_SUCCESS(Status
))
796 Status
= IopStartDevice(DeviceNode
);
803 * IopInitializeBootDrivers
805 * Initialize boot drivers and free memory for boot files.
815 IopInitializeBootDrivers(VOID
)
817 PLIST_ENTRY ListHead
, NextEntry
;
818 PLDR_DATA_TABLE_ENTRY LdrEntry
;
819 PDEVICE_NODE DeviceNode
;
820 PDRIVER_OBJECT DriverObject
;
821 LDR_DATA_TABLE_ENTRY ModuleObject
;
823 UNICODE_STRING DriverName
;
825 DPRINT("IopInitializeBootDrivers()");
827 /* Use IopRootDeviceNode for now */
828 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, NULL
, &DeviceNode
);
829 if (!NT_SUCCESS(Status
)) return;
831 /* Setup the module object for the RAW FS Driver */
832 ModuleObject
.DllBase
= NULL
;
833 ModuleObject
.SizeOfImage
= 0;
834 ModuleObject
.EntryPoint
= RawFsDriverEntry
;
835 RtlInitUnicodeString(&DriverName
, L
"RAW");
838 Status
= IopInitializeDriverModule(DeviceNode
,
843 if (!NT_SUCCESS(Status
))
846 IopFreeDeviceNode(DeviceNode
);
850 /* Now initialize the associated device */
851 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
852 if (!NT_SUCCESS(Status
))
855 IopFreeDeviceNode(DeviceNode
);
860 Status
= IopStartDevice(DeviceNode
);
861 if (!NT_SUCCESS(Status
))
864 IopFreeDeviceNode(DeviceNode
);
868 /* Loop the boot modules */
869 ListHead
= &KeLoaderBlock
->LoadOrderListHead
;
870 NextEntry
= ListHead
->Flink
;
871 while (ListHead
!= NextEntry
)
874 LdrEntry
= CONTAINING_RECORD(NextEntry
,
875 LDR_DATA_TABLE_ENTRY
,
879 * HACK: Make sure we're loading a driver
880 * (we should be using BootDriverListHead!)
882 if (wcsstr(_wcsupr(LdrEntry
->BaseDllName
.Buffer
), L
".SYS"))
884 /* Make sure we didn't load this driver already */
885 if (!(LdrEntry
->Flags
& LDRP_ENTRY_INSERTED
))
887 DPRINT("Initializing bootdriver %wZ\n", &LdrEntry
->BaseDllName
);
889 IopInitializeBuiltinDriver(LdrEntry
);
893 /* Go to the next driver */
894 NextEntry
= NextEntry
->Flink
;
897 /* In old ROS, the loader list became empty after this point. Simulate. */
898 InitializeListHead(&KeLoaderBlock
->LoadOrderListHead
);
904 * Unloads a device driver.
908 * Name of the service to unload (registry key).
911 * Whether to unload Plug & Plug or only legacy drivers. If this
912 * parameter is set to FALSE, the routine will unload only legacy
919 * Guard the whole function by SEH.
923 IopUnloadDriver(PUNICODE_STRING DriverServiceName
, BOOLEAN UnloadPnpDrivers
)
925 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
926 UNICODE_STRING ImagePath
;
927 UNICODE_STRING ServiceName
;
928 UNICODE_STRING ObjectName
;
929 PDRIVER_OBJECT DriverObject
;
933 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName
, UnloadPnpDrivers
);
938 * Get the service name from the registry key name
941 Start
= wcsrchr(DriverServiceName
->Buffer
, L
'\\');
943 Start
= DriverServiceName
->Buffer
;
947 RtlInitUnicodeString(&ServiceName
, Start
);
950 * Construct the driver object name
953 ObjectName
.Length
= (wcslen(Start
) + 8) * sizeof(WCHAR
);
954 ObjectName
.MaximumLength
= ObjectName
.Length
+ sizeof(WCHAR
);
955 ObjectName
.Buffer
= ExAllocatePool(PagedPool
, ObjectName
.MaximumLength
);
956 wcscpy(ObjectName
.Buffer
, L
"\\Driver\\");
957 memcpy(ObjectName
.Buffer
+ 8, Start
, (ObjectName
.Length
- 8) * sizeof(WCHAR
));
958 ObjectName
.Buffer
[ObjectName
.Length
/sizeof(WCHAR
)] = 0;
961 * Find the driver object
964 Status
= ObReferenceObjectByName(&ObjectName
, 0, 0, 0, IoDriverObjectType
,
965 KernelMode
, 0, (PVOID
*)&DriverObject
);
967 if (!NT_SUCCESS(Status
))
969 DPRINT("Can't locate driver object for %wZ\n", ObjectName
);
974 * Free the buffer for driver object name
977 ExFreePool(ObjectName
.Buffer
);
980 * Get path of service...
983 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
985 RtlInitUnicodeString(&ImagePath
, NULL
);
987 QueryTable
[0].Name
= L
"ImagePath";
988 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
989 QueryTable
[0].EntryContext
= &ImagePath
;
991 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
992 DriverServiceName
->Buffer
, QueryTable
, NULL
, NULL
);
994 if (!NT_SUCCESS(Status
))
996 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1001 * Normalize the image path for all later processing.
1004 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1006 if (!NT_SUCCESS(Status
))
1008 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1013 * Free the service path
1016 ExFreePool(ImagePath
.Buffer
);
1019 * Unload the module and release the references to the device object
1022 if (DriverObject
->DriverUnload
)
1023 (*DriverObject
->DriverUnload
)(DriverObject
);
1024 ObDereferenceObject(DriverObject
);
1025 ObDereferenceObject(DriverObject
);
1026 MmUnloadSystemImage(DriverObject
->DriverSection
);
1028 return STATUS_SUCCESS
;
1033 IopReinitializeDrivers(VOID
)
1035 PDRIVER_REINIT_ITEM ReinitItem
;
1038 /* Get the first entry and start looping */
1039 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1040 &DriverReinitListLock
);
1044 ReinitItem
= CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1046 /* Increment reinitialization counter */
1047 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1049 /* Remove the device object flag */
1050 ReinitItem
->DriverObject
->Flags
&= ~DRVO_REINIT_REGISTERED
;
1052 /* Call the routine */
1053 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1054 ReinitItem
->Context
,
1055 ReinitItem
->DriverObject
->
1056 DriverExtension
->Count
);
1058 /* Free the entry */
1061 /* Move to the next one */
1062 Entry
= ExInterlockedRemoveHeadList(&DriverReinitListHead
,
1063 &DriverReinitListLock
);
1069 IopReinitializeBootDrivers(VOID
)
1071 PDRIVER_REINIT_ITEM ReinitItem
;
1074 /* Get the first entry and start looping */
1075 Entry
= ExInterlockedRemoveHeadList(&DriverBootReinitListHead
,
1076 &DriverBootReinitListLock
);
1080 ReinitItem
= CONTAINING_RECORD(Entry
, DRIVER_REINIT_ITEM
, ItemEntry
);
1082 /* Increment reinitialization counter */
1083 ReinitItem
->DriverObject
->DriverExtension
->Count
++;
1085 /* Remove the device object flag */
1086 ReinitItem
->DriverObject
->Flags
&= ~DRVO_BOOTREINIT_REGISTERED
;
1088 /* Call the routine */
1089 ReinitItem
->ReinitRoutine(ReinitItem
->DriverObject
,
1090 ReinitItem
->Context
,
1091 ReinitItem
->DriverObject
->
1092 DriverExtension
->Count
);
1094 /* Free the entry */
1097 /* Move to the next one */
1098 Entry
= ExInterlockedRemoveHeadList(&DriverBootReinitListHead
,
1099 &DriverBootReinitListLock
);
1105 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL
,
1106 IN PDRIVER_INITIALIZE InitializationFunction
,
1107 IN PUNICODE_STRING RegistryPath
,
1109 IN ULONG SizeOfImage
,
1110 OUT PDRIVER_OBJECT
*pDriverObject
)
1112 WCHAR NameBuffer
[100];
1114 UNICODE_STRING LocalDriverName
;
1116 OBJECT_ATTRIBUTES ObjectAttributes
;
1118 PDRIVER_OBJECT DriverObject
;
1119 UNICODE_STRING ServiceKeyName
;
1121 ULONG i
, RetryCount
= 0;
1124 /* First, create a unique name for the driver if we don't have one */
1127 /* Create a random name and set up the string*/
1128 NameLength
= (USHORT
)swprintf(NameBuffer
,
1131 LocalDriverName
.Length
= NameLength
* sizeof(WCHAR
);
1132 LocalDriverName
.MaximumLength
= LocalDriverName
.Length
+ sizeof(UNICODE_NULL
);
1133 LocalDriverName
.Buffer
= NameBuffer
;
1137 /* So we can avoid another code path, use a local var */
1138 LocalDriverName
= *DriverName
;
1141 /* Initialize the Attributes */
1142 ObjectSize
= sizeof(DRIVER_OBJECT
) + sizeof(EXTENDED_DRIVER_EXTENSION
);
1143 InitializeObjectAttributes(&ObjectAttributes
,
1145 OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
1149 /* Create the Object */
1150 Status
= ObCreateObject(KernelMode
,
1158 (PVOID
*)&DriverObject
);
1159 if (!NT_SUCCESS(Status
)) return Status
;
1161 DPRINT("IopCreateDriver(): created DO %p\n", DriverObject
);
1163 /* Set up the Object */
1164 RtlZeroMemory(DriverObject
, ObjectSize
);
1165 DriverObject
->Type
= IO_TYPE_DRIVER
;
1166 DriverObject
->Size
= sizeof(DRIVER_OBJECT
);
1167 DriverObject
->Flags
= DRVO_BUILTIN_DRIVER
;
1168 DriverObject
->DriverExtension
= (PDRIVER_EXTENSION
)(DriverObject
+ 1);
1169 DriverObject
->DriverExtension
->DriverObject
= DriverObject
;
1170 DriverObject
->DriverInit
= InitializationFunction
;
1172 /* Loop all Major Functions */
1173 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
1175 /* Invalidate each function */
1176 DriverObject
->MajorFunction
[i
] = IopInvalidDeviceRequest
;
1179 /* Set up the service key name buffer */
1180 ServiceKeyName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
1181 LocalDriverName
.Length
+
1184 if (!ServiceKeyName
.Buffer
)
1187 ObMakeTemporaryObject(DriverObject
);
1188 ObDereferenceObject(DriverObject
);
1189 return STATUS_INSUFFICIENT_RESOURCES
;
1192 /* Fill out the key data and copy the buffer */
1193 ServiceKeyName
.Length
= LocalDriverName
.Length
;
1194 ServiceKeyName
.MaximumLength
= LocalDriverName
.MaximumLength
;
1195 RtlCopyMemory(ServiceKeyName
.Buffer
,
1196 LocalDriverName
.Buffer
,
1197 LocalDriverName
.Length
);
1199 /* Null-terminate it and set it */
1200 ServiceKeyName
.Buffer
[ServiceKeyName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1201 DriverObject
->DriverExtension
->ServiceKeyName
= ServiceKeyName
;
1203 /* Also store it in the Driver Object. This is a bit of a hack. */
1204 RtlCopyMemory(&DriverObject
->DriverName
,
1206 sizeof(UNICODE_STRING
));
1208 /* Add the Object and get its handle */
1209 Status
= ObInsertObject(DriverObject
,
1216 /* Eliminate small possibility when this function is called more than
1217 once in a row, and KeTickCount doesn't get enough time to change */
1218 if (!DriverName
&& (Status
== STATUS_OBJECT_NAME_COLLISION
) && (RetryCount
< 100))
1224 if (!NT_SUCCESS(Status
)) return Status
;
1226 /* Now reference it */
1227 Status
= ObReferenceObjectByHandle(hDriver
,
1231 (PVOID
*)&DriverObject
,
1233 if (!NT_SUCCESS(Status
))
1236 ObMakeTemporaryObject(DriverObject
);
1237 ObDereferenceObject(DriverObject
);
1241 /* Close the extra handle */
1244 DriverObject
->HardwareDatabase
= &IopHardwareDatabaseKey
;
1245 DriverObject
->DriverStart
= DllBase
;
1246 DriverObject
->DriverSize
= SizeOfImage
;
1248 /* Finally, call its init function */
1249 DPRINT("RegistryKey: %wZ\n", RegistryPath
);
1250 DPRINT("Calling driver entrypoint at %p\n", InitializationFunction
);
1251 Status
= (*InitializationFunction
)(DriverObject
, RegistryPath
);
1252 if (!NT_SUCCESS(Status
))
1254 /* If it didn't work, then kill the object */
1255 DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName
, Status
);
1256 ObMakeTemporaryObject(DriverObject
);
1257 ObDereferenceObject(DriverObject
);
1261 /* Returns to caller the object */
1262 *pDriverObject
= DriverObject
;
1265 /* Return the Status */
1269 /* PUBLIC FUNCTIONS ***********************************************************/
1276 IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL
,
1277 IN PDRIVER_INITIALIZE InitializationFunction
)
1279 PDRIVER_OBJECT DriverObject
;
1280 return IopCreateDriver(DriverName
, InitializationFunction
, NULL
, 0, 0, &DriverObject
);
1288 IoDeleteDriver(IN PDRIVER_OBJECT DriverObject
)
1290 /* Simply derefence the Object */
1291 ObDereferenceObject(DriverObject
);
1299 IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject
,
1300 IN PDRIVER_REINITIALIZE ReinitRoutine
,
1303 PDRIVER_REINIT_ITEM ReinitItem
;
1305 /* Allocate the entry */
1306 ReinitItem
= ExAllocatePoolWithTag(NonPagedPool
,
1307 sizeof(DRIVER_REINIT_ITEM
),
1309 if (!ReinitItem
) return;
1312 ReinitItem
->DriverObject
= DriverObject
;
1313 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1314 ReinitItem
->Context
= Context
;
1316 /* Set the Driver Object flag and insert the entry into the list */
1317 DriverObject
->Flags
|= DRVO_BOOTREINIT_REGISTERED
;
1318 ExInterlockedInsertTailList(&DriverBootReinitListHead
,
1319 &ReinitItem
->ItemEntry
,
1320 &DriverBootReinitListLock
);
1328 IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject
,
1329 IN PDRIVER_REINITIALIZE ReinitRoutine
,
1332 PDRIVER_REINIT_ITEM ReinitItem
;
1334 /* Allocate the entry */
1335 ReinitItem
= ExAllocatePoolWithTag(NonPagedPool
,
1336 sizeof(DRIVER_REINIT_ITEM
),
1338 if (!ReinitItem
) return;
1341 ReinitItem
->DriverObject
= DriverObject
;
1342 ReinitItem
->ReinitRoutine
= ReinitRoutine
;
1343 ReinitItem
->Context
= Context
;
1345 /* Set the Driver Object flag and insert the entry into the list */
1346 DriverObject
->Flags
|= DRVO_REINIT_REGISTERED
;
1347 ExInterlockedInsertTailList(&DriverReinitListHead
,
1348 &ReinitItem
->ItemEntry
,
1349 &DriverReinitListLock
);
1357 IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject
,
1358 IN PVOID ClientIdentificationAddress
,
1359 IN ULONG DriverObjectExtensionSize
,
1360 OUT PVOID
*DriverObjectExtension
)
1363 PIO_CLIENT_EXTENSION DriverExtensions
, NewDriverExtension
;
1364 BOOLEAN Inserted
= FALSE
;
1366 /* Assume failure */
1367 *DriverObjectExtension
= NULL
;
1369 /* Allocate the extension */
1370 NewDriverExtension
= ExAllocatePoolWithTag(NonPagedPool
,
1371 sizeof(IO_CLIENT_EXTENSION
) +
1372 DriverObjectExtensionSize
,
1373 TAG_DRIVER_EXTENSION
);
1374 if (!NewDriverExtension
) return STATUS_INSUFFICIENT_RESOURCES
;
1376 /* Clear the extension for teh caller */
1377 RtlZeroMemory(NewDriverExtension
,
1378 sizeof(IO_CLIENT_EXTENSION
) + DriverObjectExtensionSize
);
1381 OldIrql
= KeRaiseIrqlToDpcLevel();
1383 /* Fill out the extension */
1384 NewDriverExtension
->ClientIdentificationAddress
= ClientIdentificationAddress
;
1386 /* Loop the current extensions */
1387 DriverExtensions
= IoGetDrvObjExtension(DriverObject
)->
1388 ClientDriverExtension
;
1389 while (DriverExtensions
)
1391 /* Check if the identifier matches */
1392 if (DriverExtensions
->ClientIdentificationAddress
==
1393 ClientIdentificationAddress
)
1395 /* We have a collision, break out */
1399 /* Go to the next one */
1400 DriverExtensions
= DriverExtensions
->NextExtension
;
1403 /* Check if we didn't collide */
1404 if (!DriverExtensions
)
1406 /* Link this one in */
1407 NewDriverExtension
->NextExtension
=
1408 IoGetDrvObjExtension(DriverObject
)->ClientDriverExtension
;
1409 IoGetDrvObjExtension(DriverObject
)->ClientDriverExtension
=
1414 /* Release the lock */
1415 KeLowerIrql(OldIrql
);
1417 /* Check if insertion failed */
1420 /* Free the entry and fail */
1421 ExFreePool(NewDriverExtension
);
1422 return STATUS_OBJECT_NAME_COLLISION
;
1425 /* Otherwise, return the pointer */
1426 *DriverObjectExtension
= NewDriverExtension
+ 1;
1427 return STATUS_SUCCESS
;
1435 IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject
,
1436 IN PVOID ClientIdentificationAddress
)
1439 PIO_CLIENT_EXTENSION DriverExtensions
;
1442 OldIrql
= KeRaiseIrqlToDpcLevel();
1444 /* Loop the list until we find the right one */
1445 DriverExtensions
= IoGetDrvObjExtension(DriverObject
)->ClientDriverExtension
;
1446 while (DriverExtensions
)
1448 /* Check for a match */
1449 if (DriverExtensions
->ClientIdentificationAddress
==
1450 ClientIdentificationAddress
)
1457 DriverExtensions
= DriverExtensions
->NextExtension
;
1461 KeLowerIrql(OldIrql
);
1463 /* Return nothing or the extension */
1464 if (!DriverExtensions
) return NULL
;
1465 return DriverExtensions
+ 1;
1471 * Loads a device driver.
1475 * Name of the service to load (registry key).
1484 NtLoadDriver(IN PUNICODE_STRING DriverServiceName
)
1486 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1487 UNICODE_STRING ImagePath
;
1488 UNICODE_STRING ServiceName
;
1489 UNICODE_STRING CapturedDriverServiceName
= {0};
1490 KPROCESSOR_MODE PreviousMode
;
1493 PDEVICE_NODE DeviceNode
;
1494 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1495 PDRIVER_OBJECT DriverObject
;
1500 PreviousMode
= KeGetPreviousMode();
1503 * Check security privileges
1506 /* FIXME: Uncomment when privileges will be correctly implemented. */
1508 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1510 DPRINT("Privilege not held\n");
1511 return STATUS_PRIVILEGE_NOT_HELD
;
1515 Status
= ProbeAndCaptureUnicodeString(&CapturedDriverServiceName
,
1518 if (!NT_SUCCESS(Status
))
1523 DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName
);
1525 RtlInitUnicodeString(&ImagePath
, NULL
);
1528 * Get the service name from the registry key name.
1530 ASSERT(CapturedDriverServiceName
.Length
>= sizeof(WCHAR
));
1532 ServiceName
= CapturedDriverServiceName
;
1533 cur
= CapturedDriverServiceName
.Buffer
+ (CapturedDriverServiceName
.Length
/ sizeof(WCHAR
)) - 1;
1534 while (CapturedDriverServiceName
.Buffer
!= cur
)
1538 ServiceName
.Buffer
= cur
+ 1;
1539 ServiceName
.Length
= CapturedDriverServiceName
.Length
-
1540 (USHORT
)((ULONG_PTR
)ServiceName
.Buffer
-
1541 (ULONG_PTR
)CapturedDriverServiceName
.Buffer
);
1551 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
1553 RtlInitUnicodeString(&ImagePath
, NULL
);
1555 QueryTable
[0].Name
= L
"Type";
1556 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1557 QueryTable
[0].EntryContext
= &Type
;
1559 QueryTable
[1].Name
= L
"ImagePath";
1560 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1561 QueryTable
[1].EntryContext
= &ImagePath
;
1563 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1564 CapturedDriverServiceName
.Buffer
, QueryTable
, NULL
, NULL
);
1566 if (!NT_SUCCESS(Status
))
1568 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
1569 ExFreePool(ImagePath
.Buffer
);
1570 goto ReleaseCapturedString
;
1574 * Normalize the image path for all later processing.
1577 Status
= IopNormalizeImagePath(&ImagePath
, &ServiceName
);
1579 if (!NT_SUCCESS(Status
))
1581 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status
);
1582 goto ReleaseCapturedString
;
1585 DPRINT("FullImagePath: '%wZ'\n", &ImagePath
);
1586 DPRINT("Type: %lx\n", Type
);
1589 * Create device node
1592 /* Use IopRootDeviceNode for now */
1593 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &ServiceName
, &DeviceNode
);
1595 if (!NT_SUCCESS(Status
))
1597 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status
);
1598 goto ReleaseCapturedString
;
1601 /* Get existing DriverObject pointer (in case the driver has
1602 already been loaded and initialized) */
1603 Status
= IopGetDriverObject(
1606 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1607 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */));
1609 if (!NT_SUCCESS(Status
))
1612 * Load the driver module
1615 Status
= MmLoadSystemImage(&ImagePath
, NULL
, NULL
, 0, (PVOID
)&ModuleObject
, NULL
);
1616 if (!NT_SUCCESS(Status
) && Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1618 DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status
);
1619 IopFreeDeviceNode(DeviceNode
);
1620 goto ReleaseCapturedString
;
1624 * Set a service name for the device node
1627 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, ServiceName
.Buffer
);
1630 * Initialize the driver module if it's loaded for the first time
1632 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1634 Status
= IopInitializeDriverModule(
1637 &DeviceNode
->ServiceName
,
1638 (Type
== 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1639 Type
== 8 /* SERVICE_RECOGNIZER_DRIVER */),
1642 if (!NT_SUCCESS(Status
))
1644 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status
);
1645 MmUnloadSystemImage(ModuleObject
);
1646 IopFreeDeviceNode(DeviceNode
);
1647 goto ReleaseCapturedString
;
1651 /* We have a driver for this DeviceNode */
1652 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
1655 IopInitializeDevice(DeviceNode
, DriverObject
);
1656 Status
= IopStartDevice(DeviceNode
);
1658 ReleaseCapturedString
:
1659 ReleaseCapturedUnicodeString(&CapturedDriverServiceName
,
1668 * Unloads a legacy device driver.
1672 * Name of the service to unload (registry key).
1682 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName
)
1684 return IopUnloadDriver(DriverServiceName
, FALSE
);