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