merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / ntoskrnl / io / driver.c
1 /* $Id$
2 *
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 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 * Filip Navara (xnavara@volny.cz)
10 */
11
12 /* INCLUDES *******************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* ke/main.c */
19 extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
20 extern ULONG KeTickCount;
21
22 NTSTATUS
23 LdrProcessModule(PVOID ModuleLoadBase,
24 PUNICODE_STRING ModuleName,
25 PMODULE_OBJECT *ModuleObject);
26
27 typedef struct _SERVICE_GROUP
28 {
29 LIST_ENTRY GroupListEntry;
30 UNICODE_STRING GroupName;
31 BOOLEAN ServicesRunning;
32 ULONG TagCount;
33 PULONG TagArray;
34 } SERVICE_GROUP, *PSERVICE_GROUP;
35
36 typedef struct _SERVICE
37 {
38 LIST_ENTRY ServiceListEntry;
39 UNICODE_STRING ServiceName;
40 UNICODE_STRING RegistryPath;
41 UNICODE_STRING ServiceGroup;
42 UNICODE_STRING ImagePath;
43
44 ULONG Start;
45 ULONG Type;
46 ULONG ErrorControl;
47 ULONG Tag;
48
49 /* BOOLEAN ServiceRunning;*/ // needed ??
50 } SERVICE, *PSERVICE;
51
52 typedef struct _DRIVER_REINIT_ITEM
53 {
54 LIST_ENTRY ItemEntry;
55 PDRIVER_OBJECT DriverObject;
56 PDRIVER_REINITIALIZE ReinitRoutine;
57 PVOID Context;
58 } DRIVER_REINIT_ITEM, *PDRIVER_REINIT_ITEM;
59
60 /* GLOBALS ********************************************************************/
61
62 static LIST_ENTRY DriverReinitListHead;
63 static KSPIN_LOCK DriverReinitListLock;
64 static PLIST_ENTRY DriverReinitTailEntry;
65
66 static PLIST_ENTRY DriverBootReinitTailEntry;
67 static LIST_ENTRY DriverBootReinitListHead;
68 static KSPIN_LOCK DriverBootReinitListLock;
69
70 static LIST_ENTRY GroupListHead = {NULL, NULL};
71 static LIST_ENTRY ServiceListHead = {NULL, NULL};
72
73 static UNICODE_STRING IopHardwareDatabaseKey =
74 ROS_STRING_INITIALIZER(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
75
76 POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
77
78 #define TAG_DRIVER TAG('D', 'R', 'V', 'R')
79 #define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
80
81 /* DECLARATIONS ***************************************************************/
82
83 NTSTATUS STDCALL
84 IopCreateDriver(
85 PVOID ObjectBody,
86 PVOID Parent,
87 PWSTR RemainingPath,
88 POBJECT_ATTRIBUTES ObjectAttributes);
89
90 VOID STDCALL
91 IopDeleteDriver(PVOID ObjectBody);
92
93 /* PRIVATE FUNCTIONS **********************************************************/
94
95 VOID INIT_FUNCTION
96 IopInitDriverImplementation(VOID)
97 {
98 /* Register the process object type */
99 IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
100 IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'R');
101 IoDriverObjectType->TotalObjects = 0;
102 IoDriverObjectType->TotalHandles = 0;
103 IoDriverObjectType->PeakObjects = 0;
104 IoDriverObjectType->PeakHandles = 0;
105 IoDriverObjectType->PagedPoolCharge = 0;
106 IoDriverObjectType->NonpagedPoolCharge = sizeof(DRIVER_OBJECT);
107 IoDriverObjectType->Dump = NULL;
108 IoDriverObjectType->Open = NULL;
109 IoDriverObjectType->Close = NULL;
110 IoDriverObjectType->Delete = IopDeleteDriver;
111 IoDriverObjectType->Parse = NULL;
112 IoDriverObjectType->Security = NULL;
113 IoDriverObjectType->QueryName = NULL;
114 IoDriverObjectType->OkayToClose = NULL;
115 IoDriverObjectType->Create = IopCreateDriver;
116 IoDriverObjectType->DuplicationNotify = NULL;
117 RtlInitUnicodeString(&IoDriverObjectType->TypeName, L"Driver");
118
119 ObpCreateTypeObject(IoDriverObjectType);
120
121 InitializeListHead(&DriverReinitListHead);
122 KeInitializeSpinLock(&DriverReinitListLock);
123 DriverReinitTailEntry = NULL;
124
125 InitializeListHead(&DriverBootReinitListHead);
126 KeInitializeSpinLock(&DriverBootReinitListLock);
127 DriverBootReinitTailEntry = NULL;
128 }
129
130 NTSTATUS STDCALL
131 IopInvalidDeviceRequest(
132 PDEVICE_OBJECT DeviceObject,
133 PIRP Irp)
134 {
135 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
136 Irp->IoStatus.Information = 0;
137 IoCompleteRequest(Irp, IO_NO_INCREMENT);
138 return STATUS_INVALID_DEVICE_REQUEST;
139 }
140
141 NTSTATUS STDCALL
142 IopCreateDriver(
143 PVOID ObjectBody,
144 PVOID Parent,
145 PWSTR RemainingPath,
146 POBJECT_ATTRIBUTES ObjectAttributes)
147 {
148 PDRIVER_OBJECT Object = ObjectBody;
149 ULONG i;
150
151 DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
152 ObjectBody, Parent, RemainingPath);
153
154 if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
155 return STATUS_UNSUCCESSFUL;
156
157 /* Create driver extension */
158 Object->DriverExtension = (PDRIVER_EXTENSION)
159 ExAllocatePoolWithTag(
160 NonPagedPool,
161 sizeof(DRIVER_EXTENSION),
162 TAG_DRIVER_EXTENSION);
163
164 if (Object->DriverExtension == NULL)
165 {
166 return STATUS_NO_MEMORY;
167 }
168
169 RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
170
171 Object->Type = IO_TYPE_DRIVER;
172
173 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
174 Object->MajorFunction[i] = IopInvalidDeviceRequest;
175
176 Object->HardwareDatabase = &IopHardwareDatabaseKey;
177
178 return STATUS_SUCCESS;
179 }
180
181 VOID STDCALL
182 IopDeleteDriver(PVOID ObjectBody)
183 {
184 PDRIVER_OBJECT Object = ObjectBody;
185 KIRQL OldIrql;
186 PPRIVATE_DRIVER_EXTENSIONS DriverExtension, NextDriverExtension;
187
188 DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody);
189
190 ExFreePool(Object->DriverExtension);
191 RtlFreeUnicodeString(&Object->DriverName);
192
193 OldIrql = KeRaiseIrqlToDpcLevel();
194
195 for (DriverExtension = Object->DriverSection;
196 DriverExtension != NULL;
197 DriverExtension = NextDriverExtension)
198 {
199 NextDriverExtension = DriverExtension->Link;
200 ExFreePool(DriverExtension);
201 }
202
203 KfLowerIrql(OldIrql);
204 }
205
206 NTSTATUS FASTCALL
207 IopCreateDriverObject(
208 PDRIVER_OBJECT *DriverObject,
209 PUNICODE_STRING ServiceName,
210 ULONG CreateAttributes,
211 BOOLEAN FileSystem,
212 PVOID DriverImageStart,
213 ULONG DriverImageSize)
214 {
215 PDRIVER_OBJECT Object;
216 WCHAR NameBuffer[MAX_PATH];
217 UNICODE_STRING DriverName;
218 OBJECT_ATTRIBUTES ObjectAttributes;
219 NTSTATUS Status;
220 PWSTR Buffer = NULL;
221
222 DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n",
223 DriverObject, ServiceName, FileSystem, DriverImageStart, DriverImageSize);
224
225 *DriverObject = NULL;
226
227 /* Create ModuleName string */
228 if (ServiceName != NULL && ServiceName->Buffer != NULL)
229 {
230 if (FileSystem == TRUE)
231 wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
232 else
233 wcscpy(NameBuffer, DRIVER_ROOT_NAME);
234 wcscat(NameBuffer, ServiceName->Buffer);
235
236 RtlInitUnicodeString(&DriverName, NameBuffer);
237 DPRINT("Driver name: '%wZ'\n", &DriverName);
238
239 Buffer = (PWSTR)ExAllocatePool(NonPagedPool, DriverName.Length);
240 /* If we don't success, it is not a problem. Our driver
241 * object will not have associated driver name... */
242 }
243 else
244 {
245 RtlInitUnicodeString(&DriverName, NULL);
246 }
247
248 /* Initialize ObjectAttributes for driver object */
249 InitializeObjectAttributes(
250 &ObjectAttributes,
251 &DriverName,
252 CreateAttributes | OBJ_PERMANENT,
253 NULL,
254 NULL);
255
256 /* Create driver object */
257 Status = ObCreateObject(
258 KernelMode,
259 IoDriverObjectType,
260 &ObjectAttributes,
261 KernelMode,
262 NULL,
263 sizeof(DRIVER_OBJECT),
264 0,
265 0,
266 (PVOID*)&Object);
267
268 if (!NT_SUCCESS(Status))
269 {
270 return Status;
271 }
272
273 Object->DriverStart = DriverImageStart;
274 Object->DriverSize = DriverImageSize;
275 if (Buffer)
276 {
277 if (!Object->DriverName.Buffer)
278 {
279 Object->DriverName.Buffer = Buffer;
280 Object->DriverName.Length = Object->DriverName.MaximumLength = DriverName.Length;
281 RtlCopyMemory(Object->DriverName.Buffer, DriverName.Buffer, DriverName.Length);
282 }
283 else
284 ExFreePool(Buffer);
285 }
286
287 *DriverObject = Object;
288
289 return STATUS_SUCCESS;
290 }
291
292 /*
293 * IopDisplayLoadingMessage
294 *
295 * Display 'Loading XXX...' message.
296 */
297
298 VOID FASTCALL
299 IopDisplayLoadingMessage(PWCHAR ServiceName)
300 {
301 CHAR TextBuffer[256];
302 sprintf(TextBuffer, "Loading %S...\n", ServiceName);
303 HalDisplayString(TextBuffer);
304 }
305
306 /*
307 * IopNormalizeImagePath
308 *
309 * Normalize an image path to contain complete path.
310 *
311 * Parameters
312 * ImagePath
313 * The input path and on exit the result path. ImagePath.Buffer
314 * must be allocated by ExAllocatePool on input. Caller is responsible
315 * for freeing the buffer when it's no longer needed.
316 *
317 * ServiceName
318 * Name of the service that ImagePath belongs to.
319 *
320 * Return Value
321 * Status
322 *
323 * Remarks
324 * The input image path isn't freed on error.
325 */
326
327 NTSTATUS FASTCALL
328 IopNormalizeImagePath(
329 IN OUT PUNICODE_STRING ImagePath,
330 IN PUNICODE_STRING ServiceName)
331 {
332 UNICODE_STRING InputImagePath;
333
334 RtlCopyMemory(
335 &InputImagePath,
336 ImagePath,
337 sizeof(UNICODE_STRING));
338
339 if (InputImagePath.Length == 0)
340 {
341 ImagePath->Length = (33 * sizeof(WCHAR)) + ServiceName->Length;
342 ImagePath->MaximumLength = ImagePath->Length + sizeof(UNICODE_NULL);
343 ImagePath->Buffer = ExAllocatePool(NonPagedPool, ImagePath->MaximumLength);
344 if (ImagePath->Buffer == NULL)
345 return STATUS_NO_MEMORY;
346
347 wcscpy(ImagePath->Buffer, L"\\SystemRoot\\system32\\drivers\\");
348 wcscat(ImagePath->Buffer, ServiceName->Buffer);
349 wcscat(ImagePath->Buffer, L".sys");
350 } else
351 if (InputImagePath.Buffer[0] != L'\\')
352 {
353 ImagePath->Length = (12 * sizeof(WCHAR)) + InputImagePath.Length;
354 ImagePath->MaximumLength = ImagePath->Length + sizeof(UNICODE_NULL);
355 ImagePath->Buffer = ExAllocatePool(NonPagedPool, ImagePath->MaximumLength);
356 if (ImagePath->Buffer == NULL)
357 return STATUS_NO_MEMORY;
358
359 wcscpy(ImagePath->Buffer, L"\\SystemRoot\\");
360 wcscat(ImagePath->Buffer, InputImagePath.Buffer);
361 RtlFreeUnicodeString(&InputImagePath);
362 }
363
364 return STATUS_SUCCESS;
365 }
366
367 /*
368 * IopLoadServiceModule
369 *
370 * Load a module specified by registry settings for service.
371 *
372 * Parameters
373 * ServiceName
374 * Name of the service to load.
375 *
376 * Return Value
377 * Status
378 */
379
380 NTSTATUS FASTCALL
381 IopLoadServiceModule(
382 IN PUNICODE_STRING ServiceName,
383 OUT PMODULE_OBJECT *ModuleObject)
384 {
385 RTL_QUERY_REGISTRY_TABLE QueryTable[3];
386 ULONG ServiceStart;
387 UNICODE_STRING ServiceImagePath;
388 NTSTATUS Status;
389
390 DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName, ModuleObject);
391
392 /*
393 * Get information about the service.
394 */
395
396 RtlZeroMemory(QueryTable, sizeof(QueryTable));
397
398 RtlInitUnicodeString(&ServiceImagePath, NULL);
399
400 QueryTable[0].Name = L"Start";
401 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
402 QueryTable[0].EntryContext = &ServiceStart;
403
404 QueryTable[1].Name = L"ImagePath";
405 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
406 QueryTable[1].EntryContext = &ServiceImagePath;
407
408 Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
409 ServiceName->Buffer, QueryTable, NULL, NULL);
410
411 if (!NT_SUCCESS(Status))
412 {
413 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status);
414 return Status;
415 }
416
417 IopDisplayLoadingMessage(ServiceName->Buffer);
418
419 /*
420 * Normalize the image path for all later processing.
421 */
422
423 Status = IopNormalizeImagePath(&ServiceImagePath, ServiceName);
424
425 if (!NT_SUCCESS(Status))
426 {
427 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
428 return Status;
429 }
430
431 /*
432 * Load the module.
433 */
434
435 *ModuleObject = LdrGetModuleObject(&ServiceImagePath);
436
437 if (*ModuleObject == NULL)
438 {
439 Status = STATUS_UNSUCCESSFUL;
440
441 /*
442 * Special case for boot modules that were loaded by boot loader.
443 */
444
445 if (ServiceStart == 0)
446 {
447 ULONG i;
448 CHAR SearchName[256];
449 PCHAR ModuleName;
450 PLOADER_MODULE KeLoaderModules =
451 (PLOADER_MODULE)KeLoaderBlock.ModsAddr;
452
453 /*
454 * FIXME:
455 * Improve this searching algorithm by using the image name
456 * stored in registry entry ImageName and use the whole path
457 * (requires change in FreeLoader).
458 */
459
460 _snprintf(SearchName, sizeof(SearchName), "%wZ.sys", ServiceName);
461 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
462 {
463 ModuleName = (PCHAR)KeLoaderModules[i].String;
464 if (!_stricmp(ModuleName, SearchName))
465 {
466 DPRINT("Initializing boot module\n");
467
468 /* Tell, that the module is already loaded */
469 KeLoaderModules[i].Reserved = 1;
470
471 Status = LdrProcessModule(
472 (PVOID)KeLoaderModules[i].ModStart,
473 &ServiceImagePath,
474 ModuleObject);
475
476 KDB_SYMBOLFILE_HOOK(SearchName);
477
478 break;
479 }
480 }
481 }
482
483 /*
484 * Case for rest of the drivers (except disabled)
485 */
486
487 else if (ServiceStart < 4)
488 {
489 DPRINT("Loading module\n");
490 Status = LdrLoadModule(&ServiceImagePath, ModuleObject);
491 }
492 }
493 else
494 {
495 DPRINT("Module already loaded\n");
496 Status = STATUS_IMAGE_ALREADY_LOADED;
497 }
498
499 RtlFreeUnicodeString(&ServiceImagePath);
500
501 /*
502 * Now check if the module was loaded successfully.
503 */
504
505 if (!NT_SUCCESS(Status))
506 {
507 DPRINT("Module loading failed (Status %x)\n", Status);
508 }
509
510 DPRINT("Module loading (Status %x)\n", Status);
511
512 return Status;
513 }
514
515 /*
516 * IopInitializeDriverModule
517 *
518 * Initalize a loaded driver.
519 *
520 * Parameters
521 * DeviceNode
522 * Pointer to device node.
523 *
524 * ModuleObject
525 * Module object representing the driver. It can be retrieve by
526 * IopLoadServiceModule.
527 *
528 * ServiceName
529 * Name of the service (as in registry).
530 *
531 * FileSystemDriver
532 * Set to TRUE for file system drivers.
533 *
534 * DriverObject
535 * On successful return this contains the driver object representing
536 * the loaded driver.
537 */
538
539 NTSTATUS FASTCALL
540 IopInitializeDriverModule(
541 IN PDEVICE_NODE DeviceNode,
542 IN PMODULE_OBJECT ModuleObject,
543 IN PUNICODE_STRING ServiceName,
544 IN BOOLEAN FileSystemDriver,
545 OUT PDRIVER_OBJECT *DriverObject)
546 {
547 UNICODE_STRING RegistryKey;
548 PDRIVER_INITIALIZE DriverEntry = ModuleObject->EntryPoint;
549 NTSTATUS Status;
550 WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
551
552 Status = IopCreateDriverObject(
553 DriverObject,
554 ServiceName,
555 0,
556 FileSystemDriver,
557 ModuleObject->Base,
558 ModuleObject->Length);
559
560 if (!NT_SUCCESS(Status))
561 {
562 DPRINT("IopCreateDriverObject failed (Status %x)\n", Status);
563 return Status;
564 }
565
566 if (ServiceName->Buffer)
567 {
568 RegistryKey.Length = ServiceName->Length +
569 sizeof(ServicesKeyName) - sizeof(UNICODE_NULL);
570 RegistryKey.MaximumLength = RegistryKey.Length + sizeof(UNICODE_NULL);
571 RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength);
572 wcscpy(RegistryKey.Buffer, ServicesKeyName);
573 wcscat(RegistryKey.Buffer, ServiceName->Buffer);
574 }
575 else
576 {
577 RtlInitUnicodeString(&RegistryKey, NULL);
578 }
579
580 DPRINT("RegistryKey: %wZ\n", &RegistryKey);
581 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
582
583 IopMarkLastReinitializeDriver();
584
585 Status = DriverEntry(*DriverObject, &RegistryKey);
586 if (!NT_SUCCESS(Status))
587 {
588 ObMakeTemporaryObject(*DriverObject);
589 ObDereferenceObject(*DriverObject);
590 return Status;
591 }
592
593 IopReinitializeDrivers();
594
595 return STATUS_SUCCESS;
596 }
597
598 /*
599 * IopAttachFilterDriversCallback
600 *
601 * Internal routine used by IopAttachFilterDrivers.
602 */
603
604 NTSTATUS STDCALL
605 IopAttachFilterDriversCallback(
606 PWSTR ValueName,
607 ULONG ValueType,
608 PVOID ValueData,
609 ULONG ValueLength,
610 PVOID Context,
611 PVOID EntryContext)
612 {
613 PDEVICE_NODE DeviceNode = Context;
614 UNICODE_STRING ServiceName;
615 PWCHAR Filters;
616 PMODULE_OBJECT ModuleObject;
617 PDRIVER_OBJECT DriverObject;
618 NTSTATUS Status;
619
620 for (Filters = ValueData;
621 ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
622 *Filters != 0;
623 Filters += (ServiceName.Length / sizeof(WCHAR)) + 1)
624 {
625 DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath);
626 ServiceName.Buffer = Filters;
627 ServiceName.MaximumLength =
628 ServiceName.Length = wcslen(Filters) * sizeof(WCHAR);
629
630 /* Load and initialize the filter driver */
631 Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
632 if (Status != STATUS_IMAGE_ALREADY_LOADED)
633 {
634 if (!NT_SUCCESS(Status))
635 continue;
636
637 Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName,
638 FALSE, &DriverObject);
639 if (!NT_SUCCESS(Status))
640 continue;
641 }
642 else
643 {
644 /* get existing DriverObject pointer */
645 Status = IopCreateDriverObject(
646 &DriverObject,
647 &ServiceName,
648 OBJ_OPENIF,
649 FALSE,
650 ModuleObject->Base,
651 ModuleObject->Length);
652 if (!NT_SUCCESS(Status))
653 continue;
654 }
655
656 Status = IopInitializeDevice(DeviceNode, DriverObject);
657 if (!NT_SUCCESS(Status))
658 continue;
659 }
660
661 return STATUS_SUCCESS;
662 }
663
664 /*
665 * IopAttachFilterDrivers
666 *
667 * Load filter drivers for specified device node.
668 *
669 * Parameters
670 * Lower
671 * Set to TRUE for loading lower level filters or FALSE for upper
672 * level filters.
673 */
674
675 NTSTATUS FASTCALL
676 IopAttachFilterDrivers(
677 PDEVICE_NODE DeviceNode,
678 BOOLEAN Lower)
679 {
680 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
681 PWCHAR KeyBuffer;
682 UNICODE_STRING Class;
683 WCHAR ClassBuffer[40];
684 NTSTATUS Status;
685
686 /*
687 * First load the device filters
688 */
689
690 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
691 if (Lower)
692 QueryTable[0].Name = L"LowerFilters";
693 else
694 QueryTable[0].Name = L"UpperFilters";
695 QueryTable[0].EntryContext = NULL;
696 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
697 QueryTable[1].QueryRoutine = NULL;
698 QueryTable[1].Name = NULL;
699
700 KeyBuffer = ExAllocatePool(
701 PagedPool,
702 (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
703 wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
704 wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
705
706 RtlQueryRegistryValues(
707 RTL_REGISTRY_ABSOLUTE,
708 KeyBuffer,
709 QueryTable,
710 DeviceNode,
711 NULL);
712
713 /*
714 * Now get the class GUID
715 */
716
717 Class.Length = 0;
718 Class.MaximumLength = 40 * sizeof(WCHAR);
719 Class.Buffer = ClassBuffer;
720 QueryTable[0].QueryRoutine = NULL;
721 QueryTable[0].Name = L"ClassGUID";
722 QueryTable[0].EntryContext = &Class;
723 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
724
725 Status = RtlQueryRegistryValues(
726 RTL_REGISTRY_ABSOLUTE,
727 KeyBuffer,
728 QueryTable,
729 DeviceNode,
730 NULL);
731
732 ExFreePool(KeyBuffer);
733
734 /*
735 * Load the class filter driver
736 */
737
738 if (NT_SUCCESS(Status))
739 {
740 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
741 if (Lower)
742 QueryTable[0].Name = L"LowerFilters";
743 else
744 QueryTable[0].Name = L"UpperFilters";
745 QueryTable[0].EntryContext = NULL;
746 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
747
748 KeyBuffer = ExAllocatePool(PagedPool, (58 * sizeof(WCHAR)) + Class.Length);
749 wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
750 wcscat(KeyBuffer, ClassBuffer);
751
752 RtlQueryRegistryValues(
753 RTL_REGISTRY_ABSOLUTE,
754 KeyBuffer,
755 QueryTable,
756 DeviceNode,
757 NULL);
758
759 ExFreePool(KeyBuffer);
760 }
761
762 return STATUS_SUCCESS;
763 }
764
765 static NTSTATUS STDCALL
766 IopGetGroupOrderList(PWSTR ValueName,
767 ULONG ValueType,
768 PVOID ValueData,
769 ULONG ValueLength,
770 PVOID Context,
771 PVOID EntryContext)
772 {
773 PSERVICE_GROUP Group;
774
775 DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
776 ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
777
778 if (ValueType == REG_BINARY &&
779 ValueData != NULL &&
780 ValueLength >= sizeof(DWORD) &&
781 ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
782 {
783 Group = (PSERVICE_GROUP)Context;
784 Group->TagCount = ((PULONG)ValueData)[0];
785 if (Group->TagCount > 0)
786 {
787 if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
788 {
789 Group->TagArray = ExAllocatePool(NonPagedPool, Group->TagCount * sizeof(DWORD));
790 if (Group->TagArray == NULL)
791 {
792 Group->TagCount = 0;
793 return STATUS_INSUFFICIENT_RESOURCES;
794 }
795 memcpy(Group->TagArray, (PULONG)ValueData + 1, Group->TagCount * sizeof(DWORD));
796 }
797 else
798 {
799 Group->TagCount = 0;
800 return STATUS_UNSUCCESSFUL;
801 }
802 }
803 }
804 return STATUS_SUCCESS;
805 }
806
807 static NTSTATUS STDCALL
808 IopCreateGroupListEntry(PWSTR ValueName,
809 ULONG ValueType,
810 PVOID ValueData,
811 ULONG ValueLength,
812 PVOID Context,
813 PVOID EntryContext)
814 {
815 PSERVICE_GROUP Group;
816 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
817 NTSTATUS Status;
818
819
820 if (ValueType == REG_SZ)
821 {
822 DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData);
823
824 Group = ExAllocatePool(NonPagedPool,
825 sizeof(SERVICE_GROUP));
826 if (Group == NULL)
827 {
828 return(STATUS_INSUFFICIENT_RESOURCES);
829 }
830
831 RtlZeroMemory(Group, sizeof(SERVICE_GROUP));
832
833 if (!RtlpCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData, NonPagedPool))
834 {
835 ExFreePool(Group);
836 return(STATUS_INSUFFICIENT_RESOURCES);
837 }
838
839 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
840 QueryTable[0].Name = (PWSTR)ValueData;
841 QueryTable[0].QueryRoutine = IopGetGroupOrderList;
842
843 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
844 L"GroupOrderList",
845 QueryTable,
846 (PVOID)Group,
847 NULL);
848 DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
849
850 InsertTailList(&GroupListHead,
851 &Group->GroupListEntry);
852 }
853
854 return(STATUS_SUCCESS);
855 }
856
857
858 static NTSTATUS STDCALL
859 IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
860 {
861 RTL_QUERY_REGISTRY_TABLE QueryTable[7];
862 PSERVICE Service;
863 NTSTATUS Status;
864
865 DPRINT("ServiceName: '%wZ'\n", ServiceName);
866
867 /* Allocate service entry */
868 Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE));
869 if (Service == NULL)
870 {
871 DPRINT1("ExAllocatePool() failed\n");
872 return(STATUS_INSUFFICIENT_RESOURCES);
873 }
874 RtlZeroMemory(Service, sizeof(SERVICE));
875
876 /* Get service data */
877 RtlZeroMemory(&QueryTable,
878 sizeof(QueryTable));
879
880 QueryTable[0].Name = L"Start";
881 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
882 QueryTable[0].EntryContext = &Service->Start;
883
884 QueryTable[1].Name = L"Type";
885 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
886 QueryTable[1].EntryContext = &Service->Type;
887
888 QueryTable[2].Name = L"ErrorControl";
889 QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
890 QueryTable[2].EntryContext = &Service->ErrorControl;
891
892 QueryTable[3].Name = L"Group";
893 QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
894 QueryTable[3].EntryContext = &Service->ServiceGroup;
895
896 QueryTable[4].Name = L"ImagePath";
897 QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
898 QueryTable[4].EntryContext = &Service->ImagePath;
899
900 QueryTable[5].Name = L"Tag";
901 QueryTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
902 QueryTable[5].EntryContext = &Service->Tag;
903
904 Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
905 ServiceName->Buffer,
906 QueryTable,
907 NULL,
908 NULL);
909 if (!NT_SUCCESS(Status) || Service->Start > 1)
910 {
911 RtlFreeUnicodeString(&Service->ServiceGroup);
912 RtlFreeUnicodeString(&Service->ImagePath);
913 ExFreePool(Service);
914 return(Status);
915 }
916
917 /* Copy service name */
918 Service->ServiceName.Length = ServiceName->Length;
919 Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR);
920 Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool,
921 Service->ServiceName.MaximumLength);
922 RtlCopyMemory(Service->ServiceName.Buffer,
923 ServiceName->Buffer,
924 ServiceName->Length);
925 Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0;
926
927 /* Build registry path */
928 Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
929 Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool,
930 MAX_PATH * sizeof(WCHAR));
931 wcscpy(Service->RegistryPath.Buffer,
932 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
933 wcscat(Service->RegistryPath.Buffer,
934 Service->ServiceName.Buffer);
935 Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR);
936
937 DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
938 DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
939 DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
940 DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath);
941 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
942 Service->Start, Service->Type, Service->Tag, Service->ErrorControl);
943
944 /* Append service entry */
945 InsertTailList(&ServiceListHead,
946 &Service->ServiceListEntry);
947
948 return(STATUS_SUCCESS);
949 }
950
951
952 NTSTATUS INIT_FUNCTION
953 IoCreateDriverList(VOID)
954 {
955 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
956 PKEY_BASIC_INFORMATION KeyInfo = NULL;
957 OBJECT_ATTRIBUTES ObjectAttributes;
958 UNICODE_STRING ServicesKeyName;
959 UNICODE_STRING SubKeyName;
960 HANDLE KeyHandle;
961 NTSTATUS Status;
962 ULONG Index;
963
964 ULONG KeyInfoLength = 0;
965 ULONG ReturnedLength;
966
967 DPRINT("IoCreateDriverList() called\n");
968
969 /* Initialize basic variables */
970 InitializeListHead(&GroupListHead);
971 InitializeListHead(&ServiceListHead);
972
973 /* Build group order list */
974 RtlZeroMemory(&QueryTable,
975 sizeof(QueryTable));
976
977 QueryTable[0].Name = L"List";
978 QueryTable[0].QueryRoutine = IopCreateGroupListEntry;
979
980 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
981 L"ServiceGroupOrder",
982 QueryTable,
983 NULL,
984 NULL);
985 if (!NT_SUCCESS(Status))
986 return(Status);
987
988 /* Enumerate services and create the service list */
989 RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName,
990 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
991
992 InitializeObjectAttributes(&ObjectAttributes,
993 &ServicesKeyName,
994 OBJ_CASE_INSENSITIVE,
995 NULL,
996 NULL);
997
998 Status = ZwOpenKey(&KeyHandle,
999 KEY_ENUMERATE_SUB_KEYS,
1000 &ObjectAttributes);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 return(Status);
1004 }
1005
1006 KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
1007 KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength);
1008 if (KeyInfo == NULL)
1009 {
1010 ZwClose(KeyHandle);
1011 return(STATUS_INSUFFICIENT_RESOURCES);
1012 }
1013
1014 Index = 0;
1015 while (TRUE)
1016 {
1017 Status = ZwEnumerateKey(KeyHandle,
1018 Index,
1019 KeyBasicInformation,
1020 KeyInfo,
1021 KeyInfoLength,
1022 &ReturnedLength);
1023 if (NT_SUCCESS(Status))
1024 {
1025 if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR))
1026 {
1027
1028 SubKeyName.Length = KeyInfo->NameLength;
1029 SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR);
1030 SubKeyName.Buffer = KeyInfo->Name;
1031 SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
1032
1033 DPRINT("KeyName: '%wZ'\n", &SubKeyName);
1034 IopCreateServiceListEntry(&SubKeyName);
1035 }
1036 }
1037
1038 if (!NT_SUCCESS(Status))
1039 break;
1040
1041 Index++;
1042 }
1043
1044 ExFreePool(KeyInfo);
1045 ZwClose(KeyHandle);
1046
1047 DPRINT("IoCreateDriverList() done\n");
1048
1049 return(STATUS_SUCCESS);
1050 }
1051
1052 NTSTATUS INIT_FUNCTION
1053 IoDestroyDriverList(VOID)
1054 {
1055 PLIST_ENTRY GroupEntry;
1056 PLIST_ENTRY ServiceEntry;
1057 PSERVICE_GROUP CurrentGroup;
1058 PSERVICE CurrentService;
1059
1060 DPRINT("IoDestroyDriverList() called\n");
1061
1062 /* Destroy group list */
1063 GroupEntry = GroupListHead.Flink;
1064 while (GroupEntry != &GroupListHead)
1065 {
1066 CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
1067
1068 RtlFreeUnicodeString(&CurrentGroup->GroupName);
1069 RemoveEntryList(GroupEntry);
1070 if (CurrentGroup->TagArray)
1071 {
1072 ExFreePool(CurrentGroup->TagArray);
1073 }
1074 ExFreePool(CurrentGroup);
1075
1076 GroupEntry = GroupListHead.Flink;
1077 }
1078
1079 /* Destroy service list */
1080 ServiceEntry = ServiceListHead.Flink;
1081 while (ServiceEntry != &ServiceListHead)
1082 {
1083 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1084
1085 RtlFreeUnicodeString(&CurrentService->ServiceName);
1086 RtlFreeUnicodeString(&CurrentService->RegistryPath);
1087 RtlFreeUnicodeString(&CurrentService->ServiceGroup);
1088 RtlFreeUnicodeString(&CurrentService->ImagePath);
1089 RemoveEntryList(ServiceEntry);
1090 ExFreePool(CurrentService);
1091
1092 ServiceEntry = ServiceListHead.Flink;
1093 }
1094
1095 DPRINT("IoDestroyDriverList() done\n");
1096
1097 return(STATUS_SUCCESS);
1098 }
1099
1100 VOID STATIC INIT_FUNCTION
1101 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
1102 {
1103 ULONG i;
1104
1105 for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
1106 {
1107 MmDeleteVirtualMapping(NULL, (char*)StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
1108 }
1109 }
1110
1111 /*
1112 * IopInitializeBuiltinDriver
1113 *
1114 * Initialize a driver that is already loaded in memory.
1115 */
1116
1117 NTSTATUS FASTCALL INIT_FUNCTION
1118 IopInitializeBuiltinDriver(
1119 PDEVICE_NODE ModuleDeviceNode,
1120 PVOID ModuleLoadBase,
1121 PCHAR FileName,
1122 ULONG ModuleLength)
1123 {
1124 PMODULE_OBJECT ModuleObject;
1125 PDEVICE_NODE DeviceNode;
1126 PDRIVER_OBJECT DriverObject;
1127 NTSTATUS Status;
1128 CHAR TextBuffer[256];
1129 PCHAR FileNameWithoutPath;
1130 LPWSTR FileExtension;
1131
1132 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1133 FileName, ModuleLoadBase, ModuleLength);
1134
1135 /*
1136 * Display 'Initializing XXX...' message
1137 */
1138
1139 sprintf(TextBuffer, "Initializing %s...\n", FileName);
1140 HalDisplayString(TextBuffer);
1141
1142 /*
1143 * Determine the right device object
1144 */
1145
1146 if (ModuleDeviceNode == NULL)
1147 {
1148 /* Use IopRootDeviceNode for now */
1149 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
1150 if (!NT_SUCCESS(Status))
1151 {
1152 CPRINT("Driver load failed, status (%x)\n", Status);
1153 return(Status);
1154 }
1155 } else
1156 {
1157 DeviceNode = ModuleDeviceNode;
1158 }
1159
1160 /*
1161 * Generate filename without path (not needed by freeldr)
1162 */
1163
1164 FileNameWithoutPath = strrchr(FileName, '\\');
1165 if (FileNameWithoutPath == NULL)
1166 {
1167 FileNameWithoutPath = FileName;
1168 }
1169
1170 /*
1171 * Load the module
1172 */
1173
1174 RtlCreateUnicodeStringFromAsciiz(&DeviceNode->ServiceName,
1175 FileNameWithoutPath);
1176 Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName,
1177 &ModuleObject);
1178 if (!NT_SUCCESS(Status))
1179 {
1180 if (ModuleDeviceNode == NULL)
1181 IopFreeDeviceNode(DeviceNode);
1182 CPRINT("Driver load failed, status (%x)\n", Status);
1183 return Status;
1184 }
1185
1186 /* Load symbols */
1187 KDB_SYMBOLFILE_HOOK(FileName);
1188
1189 /*
1190 * Strip the file extension from ServiceName
1191 */
1192
1193 FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.');
1194 if (FileExtension != NULL)
1195 {
1196 DeviceNode->ServiceName.Length -= wcslen(FileExtension) * sizeof(WCHAR);
1197 FileExtension[0] = 0;
1198 }
1199
1200 /*
1201 * Initialize the driver
1202 */
1203
1204 Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
1205 &DeviceNode->ServiceName, FALSE, &DriverObject);
1206
1207 if (!NT_SUCCESS(Status))
1208 {
1209 if (ModuleDeviceNode == NULL)
1210 IopFreeDeviceNode(DeviceNode);
1211 CPRINT("Driver load failed, status (%x)\n", Status);
1212 return Status;
1213 }
1214
1215 Status = IopInitializeDevice(DeviceNode, DriverObject);
1216
1217 return Status;
1218 }
1219
1220 /*
1221 * IopInitializeBootDrivers
1222 *
1223 * Initialize boot drivers and free memory for boot files.
1224 *
1225 * Parameters
1226 * None
1227 *
1228 * Return Value
1229 * None
1230 */
1231
1232 VOID FASTCALL
1233 IopInitializeBootDrivers(VOID)
1234 {
1235 ULONG BootDriverCount;
1236 ULONG ModuleStart;
1237 ULONG ModuleSize;
1238 ULONG ModuleLoaded;
1239 PCHAR ModuleName;
1240 PCHAR Extension;
1241 PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr;
1242 ULONG i;
1243 UNICODE_STRING DriverName;
1244 NTSTATUS Status;
1245
1246 DPRINT("IopInitializeBootDrivers()\n");
1247
1248 BootDriverCount = 0;
1249 for (i = 0; i < KeLoaderBlock.ModsCount; i++)
1250 {
1251 ModuleStart = KeLoaderModules[i].ModStart;
1252 ModuleSize = KeLoaderModules[i].ModEnd - ModuleStart;
1253 ModuleName = (PCHAR)KeLoaderModules[i].String;
1254 ModuleLoaded = KeLoaderModules[i].Reserved;
1255 Extension = strrchr(ModuleName, '.');
1256 if (Extension == NULL)
1257 Extension = "";
1258
1259 if (!_stricmp(Extension, ".sym") || !_stricmp(Extension, ".dll"))
1260 {
1261 /* Process symbols for *.exe and *.dll */
1262 KDB_SYMBOLFILE_HOOK(ModuleName);
1263
1264 /* Log *.exe and *.dll files */
1265 RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName);
1266 IopBootLog(&DriverName, TRUE);
1267 RtlFreeUnicodeString(&DriverName);
1268 }
1269 else if (!_stricmp(Extension, ".sys"))
1270 {
1271 /* Initialize and log boot start driver */
1272 if (!ModuleLoaded)
1273 {
1274 Status = IopInitializeBuiltinDriver(NULL,
1275 (PVOID)ModuleStart,
1276 ModuleName,
1277 ModuleSize);
1278 RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName);
1279 IopBootLog(&DriverName, NT_SUCCESS(Status) ? TRUE : FALSE);
1280 RtlFreeUnicodeString(&DriverName);
1281 }
1282 BootDriverCount++;
1283 }
1284 }
1285
1286 /*
1287 * Free memory for all boot files, except ntoskrnl.exe.
1288 */
1289 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
1290 {
1291 MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
1292 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
1293 }
1294
1295 KeLoaderBlock.ModsCount = 0;
1296
1297 if (BootDriverCount == 0)
1298 {
1299 DbgPrint("No boot drivers available.\n");
1300 KEBUGCHECK(0);
1301 }
1302 }
1303
1304 static INIT_FUNCTION NTSTATUS
1305 IopLoadDriver(PSERVICE Service)
1306 {
1307 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1308
1309 IopDisplayLoadingMessage(Service->ServiceName.Buffer);
1310 Status = ZwLoadDriver(&Service->RegistryPath);
1311 IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE);
1312 if (!NT_SUCCESS(Status))
1313 {
1314 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status);
1315 #if 0
1316 if (Service->ErrorControl == 1)
1317 {
1318 /* Log error */
1319 }
1320 else if (Service->ErrorControl == 2)
1321 {
1322 if (IsLastKnownGood == FALSE)
1323 {
1324 /* Boot last known good configuration */
1325 }
1326 }
1327 else if (Service->ErrorControl == 3)
1328 {
1329 if (IsLastKnownGood == FALSE)
1330 {
1331 /* Boot last known good configuration */
1332 }
1333 else
1334 {
1335 /* BSOD! */
1336 }
1337 }
1338 #endif
1339 }
1340 return Status;
1341 }
1342
1343
1344 /*
1345 * IopInitializeSystemDrivers
1346 *
1347 * Load drivers marked as system start.
1348 *
1349 * Parameters
1350 * None
1351 *
1352 * Return Value
1353 * None
1354 */
1355
1356 VOID FASTCALL
1357 IopInitializeSystemDrivers(VOID)
1358 {
1359 PLIST_ENTRY GroupEntry;
1360 PLIST_ENTRY ServiceEntry;
1361 PSERVICE_GROUP CurrentGroup;
1362 PSERVICE CurrentService;
1363 NTSTATUS Status;
1364 ULONG i;
1365
1366 DPRINT("IopInitializeSystemDrivers()\n");
1367
1368 GroupEntry = GroupListHead.Flink;
1369 while (GroupEntry != &GroupListHead)
1370 {
1371 CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
1372
1373 DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
1374
1375 /* Load all drivers with a valid tag */
1376 for (i = 0; i < CurrentGroup->TagCount; i++)
1377 {
1378 ServiceEntry = ServiceListHead.Flink;
1379 while (ServiceEntry != &ServiceListHead)
1380 {
1381 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1382
1383 if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
1384 &CurrentService->ServiceGroup, TRUE) == 0) &&
1385 (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/) &&
1386 (CurrentService->Tag == CurrentGroup->TagArray[i]))
1387 {
1388 DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath);
1389 Status = IopLoadDriver(CurrentService);
1390 }
1391 ServiceEntry = ServiceEntry->Flink;
1392 }
1393 }
1394
1395 /* Load all drivers without a tag or with an invalid tag */
1396 ServiceEntry = ServiceListHead.Flink;
1397 while (ServiceEntry != &ServiceListHead)
1398 {
1399 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1400 if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
1401 &CurrentService->ServiceGroup, TRUE) == 0) &&
1402 (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))
1403 {
1404 for (i = 0; i < CurrentGroup->TagCount; i++)
1405 {
1406 if (CurrentGroup->TagArray[i] == CurrentService->Tag)
1407 {
1408 break;
1409 }
1410 }
1411 if (i >= CurrentGroup->TagCount)
1412 {
1413 DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath);
1414 Status = IopLoadDriver(CurrentService);
1415 }
1416 }
1417 ServiceEntry = ServiceEntry->Flink;
1418 }
1419
1420 GroupEntry = GroupEntry->Flink;
1421 }
1422
1423 DPRINT("IopInitializeSystemDrivers() done\n");
1424 }
1425
1426 /*
1427 * IopUnloadDriver
1428 *
1429 * Unloads a device driver.
1430 *
1431 * Parameters
1432 * DriverServiceName
1433 * Name of the service to unload (registry key).
1434 *
1435 * UnloadPnpDrivers
1436 * Whether to unload Plug & Plug or only legacy drivers. If this
1437 * parameter is set to FALSE, the routine will unload only legacy
1438 * drivers.
1439 *
1440 * Return Value
1441 * Status
1442 *
1443 * To do
1444 * Guard the whole function by SEH.
1445 */
1446
1447 NTSTATUS STDCALL
1448 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
1449 {
1450 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1451 UNICODE_STRING ImagePath;
1452 UNICODE_STRING ServiceName;
1453 UNICODE_STRING ObjectName;
1454 PDRIVER_OBJECT DriverObject;
1455 PMODULE_OBJECT ModuleObject;
1456 NTSTATUS Status;
1457 LPWSTR Start;
1458
1459 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers);
1460
1461 /*
1462 * Get the service name from the registry key name
1463 */
1464
1465 Start = wcsrchr(DriverServiceName->Buffer, L'\\');
1466 if (Start == NULL)
1467 Start = DriverServiceName->Buffer;
1468 else
1469 Start++;
1470
1471 RtlInitUnicodeString(&ServiceName, Start);
1472
1473 /*
1474 * Construct the driver object name
1475 */
1476
1477 ObjectName.Length = (wcslen(Start) + 8) * sizeof(WCHAR);
1478 ObjectName.MaximumLength = ObjectName.Length + sizeof(WCHAR);
1479 ObjectName.Buffer = ExAllocatePool(NonPagedPool, ObjectName.MaximumLength);
1480 wcscpy(ObjectName.Buffer, L"\\Driver\\");
1481 memcpy(ObjectName.Buffer + 8, Start, (ObjectName.Length - 8) * sizeof(WCHAR));
1482 ObjectName.Buffer[ObjectName.Length/sizeof(WCHAR)] = 0;
1483
1484 /*
1485 * Find the driver object
1486 */
1487
1488 Status = ObReferenceObjectByName(&ObjectName, 0, 0, 0, IoDriverObjectType,
1489 KernelMode, 0, (PVOID*)&DriverObject);
1490
1491 if (!NT_SUCCESS(Status))
1492 {
1493 DPRINT("Can't locate driver object for %wZ\n", ObjectName);
1494 return Status;
1495 }
1496
1497 /*
1498 * Free the buffer for driver object name
1499 */
1500
1501 ExFreePool(ObjectName.Buffer);
1502
1503 /*
1504 * Get path of service...
1505 */
1506
1507 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1508
1509 RtlInitUnicodeString(&ImagePath, NULL);
1510
1511 QueryTable[0].Name = L"ImagePath";
1512 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1513 QueryTable[0].EntryContext = &ImagePath;
1514
1515 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1516 DriverServiceName->Buffer, QueryTable, NULL, NULL);
1517
1518 if (!NT_SUCCESS(Status))
1519 {
1520 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1521 return Status;
1522 }
1523
1524 /*
1525 * Normalize the image path for all later processing.
1526 */
1527
1528 Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1529
1530 if (!NT_SUCCESS(Status))
1531 {
1532 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1533 return Status;
1534 }
1535
1536 /*
1537 * ... and check if it's loaded
1538 */
1539
1540 ModuleObject = LdrGetModuleObject(&ImagePath);
1541 if (ModuleObject == NULL)
1542 {
1543 return STATUS_UNSUCCESSFUL;
1544 }
1545
1546 /*
1547 * Free the service path
1548 */
1549
1550 RtlFreeUnicodeString(&ImagePath);
1551
1552 /*
1553 * Unload the module and release the references to the device object
1554 */
1555
1556 if (DriverObject->DriverUnload)
1557 (*DriverObject->DriverUnload)(DriverObject);
1558 ObDereferenceObject(DriverObject);
1559 ObDereferenceObject(DriverObject);
1560 LdrUnloadModule(ModuleObject);
1561
1562 return STATUS_SUCCESS;
1563 }
1564
1565 VOID FASTCALL
1566 IopMarkLastReinitializeDriver(VOID)
1567 {
1568 KIRQL Irql;
1569
1570 KeAcquireSpinLock(&DriverReinitListLock,
1571 &Irql);
1572
1573 if (IsListEmpty(&DriverReinitListHead))
1574 {
1575 DriverReinitTailEntry = NULL;
1576 }
1577 else
1578 {
1579 DriverReinitTailEntry = DriverReinitListHead.Blink;
1580 }
1581
1582 KeReleaseSpinLock(&DriverReinitListLock,
1583 Irql);
1584 }
1585
1586
1587 VOID FASTCALL
1588 IopReinitializeDrivers(VOID)
1589 {
1590 PDRIVER_REINIT_ITEM ReinitItem;
1591 PLIST_ENTRY Entry;
1592 KIRQL Irql;
1593
1594 KeAcquireSpinLock(&DriverReinitListLock,
1595 &Irql);
1596
1597 if (DriverReinitTailEntry == NULL)
1598 {
1599 KeReleaseSpinLock(&DriverReinitListLock,
1600 Irql);
1601 return;
1602 }
1603
1604 KeReleaseSpinLock(&DriverReinitListLock,
1605 Irql);
1606
1607 for (;;)
1608 {
1609 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
1610 &DriverReinitListLock);
1611 if (Entry == NULL)
1612 return;
1613
1614 ReinitItem = (PDRIVER_REINIT_ITEM)CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1615
1616 /* Increment reinitialization counter */
1617 ReinitItem->DriverObject->DriverExtension->Count++;
1618
1619 ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1620 ReinitItem->Context,
1621 ReinitItem->DriverObject->DriverExtension->Count);
1622
1623 ExFreePool(Entry);
1624
1625 if (Entry == DriverReinitTailEntry)
1626 return;
1627 }
1628 }
1629
1630 /* PUBLIC FUNCTIONS ***********************************************************/
1631
1632
1633 /*
1634 * @implemented
1635 */
1636 NTSTATUS
1637 STDCALL
1638 IoCreateDriver (
1639 IN PUNICODE_STRING DriverName, OPTIONAL
1640 IN PDRIVER_INITIALIZE InitializationFunction
1641 )
1642 {
1643 WCHAR NameBuffer[100];
1644 USHORT NameLength;
1645 UNICODE_STRING LocalDriverName; /* To reduce code if no name given */
1646 NTSTATUS Status;
1647 OBJECT_ATTRIBUTES ObjectAttributes;
1648 ULONG ObjectSize;
1649 PDRIVER_OBJECT DriverObject;
1650 UNICODE_STRING ServiceKeyName;
1651 HANDLE hDriver;
1652 ULONG i;
1653
1654 /* First, create a unique name for the driver if we don't have one */
1655 if (!DriverName) {
1656
1657 /* Create a random name and set up the string*/
1658 NameLength = swprintf(NameBuffer, L"\\Driver\\%08u", KeTickCount);
1659 LocalDriverName.Length = NameLength * sizeof(WCHAR);
1660 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1661 LocalDriverName.Buffer = NameBuffer;
1662
1663 } else {
1664
1665 /* So we can avoid another code path, use a local var */
1666 LocalDriverName = *DriverName;
1667 }
1668
1669 /* Initialize the Attributes */
1670 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(DRIVER_EXTENSION);
1671 InitializeObjectAttributes(&ObjectAttributes,
1672 &LocalDriverName,
1673 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
1674 NULL,
1675 NULL);
1676
1677 /* Create the Object */
1678 Status = ObCreateObject(KernelMode,
1679 IoDriverObjectType,
1680 &ObjectAttributes,
1681 KernelMode,
1682 NULL,
1683 ObjectSize,
1684 0,
1685 0,
1686 (PVOID*)&DriverObject);
1687
1688 /* Return on failure */
1689 if (!NT_SUCCESS(Status)) return Status;
1690
1691 /* Set up the Object */
1692 RtlZeroMemory(DriverObject, ObjectSize);
1693 DriverObject->Type = IO_TYPE_DRIVER;
1694 DriverObject->Size = sizeof(DRIVER_OBJECT);
1695 DriverObject->Flags = DRVO_BUILTIN_DRIVER;
1696 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
1697 DriverObject->DriverExtension->DriverObject = DriverObject;
1698 DriverObject->DriverInit = InitializationFunction;
1699
1700 /* Invalidate all Major Functions */
1701 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1702 {
1703 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1704 }
1705
1706 /* Set up the Service Key Name */
1707 ServiceKeyName.Buffer = ExAllocatePool(PagedPool, LocalDriverName.Length + sizeof(WCHAR));
1708 ServiceKeyName.Length = LocalDriverName.Length;
1709 ServiceKeyName.MaximumLength = LocalDriverName.MaximumLength;
1710 RtlMoveMemory(ServiceKeyName.Buffer, LocalDriverName.Buffer, LocalDriverName.Length);
1711 ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = L'\0';
1712 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
1713
1714 /* Also store it in the Driver Object. This is a bit of a hack. */
1715 RtlMoveMemory(&DriverObject->DriverName, &ServiceKeyName, sizeof(UNICODE_STRING));
1716
1717 /* Add the Object and get its handle */
1718 Status = ObInsertObject(DriverObject,
1719 NULL,
1720 FILE_READ_DATA,
1721 0,
1722 NULL,
1723 &hDriver);
1724
1725 /* Return on Failure */
1726 if (!NT_SUCCESS(Status)) return Status;
1727
1728 /* Now reference it */
1729 Status = ObReferenceObjectByHandle(hDriver,
1730 0,
1731 IoDriverObjectType,
1732 KernelMode,
1733 (PVOID*)&DriverObject,
1734 NULL);
1735 ZwClose(hDriver);
1736
1737 /* Finally, call its init function */
1738 Status = (*InitializationFunction)(DriverObject, NULL);
1739
1740 if (!NT_SUCCESS(Status)) {
1741 /* If it didn't work, then kill the object */
1742 ObMakeTemporaryObject(DriverObject);
1743 ObDereferenceObject(DriverObject);
1744 }
1745
1746 /* Return the Status */
1747 return Status;
1748 }
1749
1750 /*
1751 * @implemented
1752 */
1753 VOID
1754 STDCALL
1755 IoDeleteDriver (
1756 IN PDRIVER_OBJECT DriverObject
1757 )
1758 {
1759 /* Simply derefence the Object */
1760 ObDereferenceObject(DriverObject);
1761 }
1762
1763
1764 /*
1765 * NtLoadDriver
1766 *
1767 * Loads a device driver.
1768 *
1769 * Parameters
1770 * DriverServiceName
1771 * Name of the service to load (registry key).
1772 *
1773 * Return Value
1774 * Status
1775 *
1776 * Status
1777 * implemented
1778 */
1779
1780 NTSTATUS STDCALL
1781 NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
1782 {
1783 RTL_QUERY_REGISTRY_TABLE QueryTable[3];
1784 UNICODE_STRING ImagePath;
1785 UNICODE_STRING ServiceName;
1786 NTSTATUS Status;
1787 ULONG Type;
1788 PDEVICE_NODE DeviceNode;
1789 PMODULE_OBJECT ModuleObject;
1790 PDRIVER_OBJECT DriverObject;
1791 LPWSTR Start;
1792
1793 DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName);
1794
1795 /*
1796 * Check security privileges
1797 */
1798
1799 /* FIXME: Uncomment when privileges will be correctly implemented. */
1800 #if 0
1801 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, KeGetPreviousMode()))
1802 {
1803 DPRINT("Privilege not held\n");
1804 return STATUS_PRIVILEGE_NOT_HELD;
1805 }
1806 #endif
1807
1808 RtlInitUnicodeString(&ImagePath, NULL);
1809
1810 /*
1811 * Get the service name from the registry key name.
1812 */
1813
1814 Start = wcsrchr(DriverServiceName->Buffer, L'\\');
1815 if (Start == NULL)
1816 Start = DriverServiceName->Buffer;
1817 else
1818 Start++;
1819
1820 RtlInitUnicodeString(&ServiceName, Start);
1821
1822 /*
1823 * Get service type.
1824 */
1825
1826 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
1827
1828 RtlInitUnicodeString(&ImagePath, NULL);
1829
1830 QueryTable[0].Name = L"Type";
1831 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
1832 QueryTable[0].EntryContext = &Type;
1833
1834 QueryTable[1].Name = L"ImagePath";
1835 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
1836 QueryTable[1].EntryContext = &ImagePath;
1837
1838 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1839 DriverServiceName->Buffer, QueryTable, NULL, NULL);
1840
1841 if (!NT_SUCCESS(Status))
1842 {
1843 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
1844 RtlFreeUnicodeString(&ImagePath);
1845 return Status;
1846 }
1847
1848 /*
1849 * Normalize the image path for all later processing.
1850 */
1851
1852 Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1853
1854 if (!NT_SUCCESS(Status))
1855 {
1856 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1857 return Status;
1858 }
1859
1860 DPRINT("FullImagePath: '%S'\n", ImagePath.Buffer);
1861 DPRINT("Type: %lx\n", Type);
1862
1863 /*
1864 * See, if the driver module isn't already loaded
1865 */
1866
1867 ModuleObject = LdrGetModuleObject(&ImagePath);
1868 if (ModuleObject != NULL)
1869 {
1870 DPRINT("Image already loaded\n");
1871 return STATUS_IMAGE_ALREADY_LOADED;
1872 }
1873
1874 /*
1875 * Create device node
1876 */
1877
1878 /* Use IopRootDeviceNode for now */
1879 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
1880
1881 if (!NT_SUCCESS(Status))
1882 {
1883 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
1884 return Status;
1885 }
1886
1887 /*
1888 * Load the driver module
1889 */
1890
1891 Status = LdrLoadModule(&ImagePath, &ModuleObject);
1892
1893 if (!NT_SUCCESS(Status))
1894 {
1895 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status);
1896 IopFreeDeviceNode(DeviceNode);
1897 return Status;
1898 }
1899
1900 /*
1901 * Set a service name for the device node
1902 */
1903
1904 Start = wcsrchr(DriverServiceName->Buffer, L'\\');
1905 if (Start == NULL)
1906 Start = DriverServiceName->Buffer;
1907 else
1908 Start++;
1909 RtlpCreateUnicodeString(&DeviceNode->ServiceName, Start, NonPagedPool);
1910
1911 /*
1912 * Initialize the driver module
1913 */
1914
1915 Status = IopInitializeDriverModule(
1916 DeviceNode,
1917 ModuleObject,
1918 &DeviceNode->ServiceName,
1919 (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1920 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
1921 &DriverObject);
1922
1923 if (!NT_SUCCESS(Status))
1924 {
1925 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status);
1926 LdrUnloadModule(ModuleObject);
1927 IopFreeDeviceNode(DeviceNode);
1928 return Status;
1929 }
1930
1931 IopInitializeDevice(DeviceNode, DriverObject);
1932
1933 return Status;
1934 }
1935
1936 /*
1937 * NtUnloadDriver
1938 *
1939 * Unloads a legacy device driver.
1940 *
1941 * Parameters
1942 * DriverServiceName
1943 * Name of the service to unload (registry key).
1944 *
1945 * Return Value
1946 * Status
1947 *
1948 * Status
1949 * implemented
1950 */
1951
1952 NTSTATUS STDCALL
1953 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
1954 {
1955 return IopUnloadDriver(DriverServiceName, FALSE);
1956 }
1957
1958 /*
1959 * IoRegisterDriverReinitialization
1960 *
1961 * Status
1962 * @implemented
1963 */
1964
1965 VOID STDCALL
1966 IoRegisterDriverReinitialization(
1967 PDRIVER_OBJECT DriverObject,
1968 PDRIVER_REINITIALIZE ReinitRoutine,
1969 PVOID Context)
1970 {
1971 PDRIVER_REINIT_ITEM ReinitItem;
1972
1973 ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
1974 if (ReinitItem == NULL)
1975 return;
1976
1977 ReinitItem->DriverObject = DriverObject;
1978 ReinitItem->ReinitRoutine = ReinitRoutine;
1979 ReinitItem->Context = Context;
1980
1981 DriverObject->Flags |= DRVO_REINIT_REGISTERED;
1982
1983 ExInterlockedInsertTailList(
1984 &DriverReinitListHead,
1985 &ReinitItem->ItemEntry,
1986 &DriverReinitListLock);
1987 }
1988
1989 /*
1990 * @implemented
1991 */
1992 VOID
1993 STDCALL
1994 IoRegisterBootDriverReinitialization(
1995 IN PDRIVER_OBJECT DriverObject,
1996 IN PDRIVER_REINITIALIZE DriverReinitializationRoutine,
1997 IN PVOID Context
1998 )
1999 {
2000 PDRIVER_REINIT_ITEM ReinitItem;
2001
2002 ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
2003 if (ReinitItem == NULL)
2004 return;
2005
2006 ReinitItem->DriverObject = DriverObject;
2007 ReinitItem->ReinitRoutine = DriverReinitializationRoutine;
2008 ReinitItem->Context = Context;
2009
2010 DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED;
2011
2012 ExInterlockedInsertTailList(
2013 &DriverBootReinitListHead,
2014 &ReinitItem->ItemEntry,
2015 &DriverReinitListLock);
2016 }
2017
2018 /*
2019 * IoAllocateDriverObjectExtension
2020 *
2021 * Status
2022 * @implemented
2023 */
2024
2025 NTSTATUS STDCALL
2026 IoAllocateDriverObjectExtension(
2027 PDRIVER_OBJECT DriverObject,
2028 PVOID ClientIdentificationAddress,
2029 ULONG DriverObjectExtensionSize,
2030 PVOID *DriverObjectExtension)
2031 {
2032 KIRQL OldIrql;
2033 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions;
2034 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension;
2035
2036 NewDriverExtension = ExAllocatePoolWithTag(
2037 NonPagedPool,
2038 sizeof(PRIVATE_DRIVER_EXTENSIONS) - sizeof(CHAR) +
2039 DriverObjectExtensionSize,
2040 TAG_DRIVER_EXTENSION);
2041
2042 if (NewDriverExtension == NULL)
2043 {
2044 return STATUS_INSUFFICIENT_RESOURCES;
2045 }
2046
2047 OldIrql = KeRaiseIrqlToDpcLevel();
2048
2049 NewDriverExtension->Link = DriverObject->DriverSection;
2050 NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress;
2051
2052 for (DriverExtensions = DriverObject->DriverSection;
2053 DriverExtensions != NULL;
2054 DriverExtensions = DriverExtensions->Link)
2055 {
2056 if (DriverExtensions->ClientIdentificationAddress ==
2057 ClientIdentificationAddress)
2058 {
2059 KfLowerIrql(OldIrql);
2060 return STATUS_OBJECT_NAME_COLLISION;
2061 }
2062 }
2063
2064 DriverObject->DriverSection = NewDriverExtension;
2065
2066 KfLowerIrql(OldIrql);
2067
2068 *DriverObjectExtension = &NewDriverExtension->Extension;
2069
2070 return STATUS_SUCCESS;
2071 }
2072
2073 /*
2074 * IoGetDriverObjectExtension
2075 *
2076 * Status
2077 * @implemented
2078 */
2079
2080 PVOID STDCALL
2081 IoGetDriverObjectExtension(
2082 PDRIVER_OBJECT DriverObject,
2083 PVOID ClientIdentificationAddress)
2084 {
2085 KIRQL OldIrql;
2086 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions;
2087
2088 OldIrql = KeRaiseIrqlToDpcLevel();
2089
2090 for (DriverExtensions = DriverObject->DriverSection;
2091 DriverExtensions != NULL &&
2092 DriverExtensions->ClientIdentificationAddress !=
2093 ClientIdentificationAddress;
2094 DriverExtensions = DriverExtensions->Link)
2095 ;
2096
2097 KfLowerIrql(OldIrql);
2098
2099 if (DriverExtensions == NULL)
2100 return NULL;
2101
2102 return &DriverExtensions->Extension;
2103 }
2104
2105 /* EOF */