- Make the NDK compatible with the MSDDK again.
[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 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 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 if (!NT_SUCCESS(Status))
533 /* Try to load it. It may just have been installed by PnP manager */
534 Status = LdrLoadModule(&ServiceImagePath, ModuleObject);
535 }
536
537 /*
538 * Case for rest of the drivers (except disabled)
539 */
540
541 else if (ServiceStart < 4)
542 {
543 DPRINT("Loading module\n");
544 Status = LdrLoadModule(&ServiceImagePath, ModuleObject);
545 }
546 }
547 else
548 {
549 DPRINT("Module already loaded\n");
550 Status = STATUS_IMAGE_ALREADY_LOADED;
551 }
552
553 ExFreePool(ServiceImagePath.Buffer);
554
555 /*
556 * Now check if the module was loaded successfully.
557 */
558
559 if (!NT_SUCCESS(Status))
560 {
561 DPRINT("Module loading failed (Status %x)\n", Status);
562 }
563
564 DPRINT("Module loading (Status %x)\n", Status);
565
566 return Status;
567 }
568
569 /*
570 * IopInitializeDriverModule
571 *
572 * Initalize a loaded driver.
573 *
574 * Parameters
575 * DeviceNode
576 * Pointer to device node.
577 *
578 * ModuleObject
579 * Module object representing the driver. It can be retrieve by
580 * IopLoadServiceModule.
581 *
582 * ServiceName
583 * Name of the service (as in registry).
584 *
585 * FileSystemDriver
586 * Set to TRUE for file system drivers.
587 *
588 * DriverObject
589 * On successful return this contains the driver object representing
590 * the loaded driver.
591 */
592
593 NTSTATUS FASTCALL
594 IopInitializeDriverModule(
595 IN PDEVICE_NODE DeviceNode,
596 IN PLDR_DATA_TABLE_ENTRY ModuleObject,
597 IN PUNICODE_STRING ServiceName,
598 IN BOOLEAN FileSystemDriver,
599 OUT PDRIVER_OBJECT *DriverObject)
600 {
601 const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
602 UNICODE_STRING RegistryKey;
603 PDRIVER_INITIALIZE DriverEntry;
604 NTSTATUS Status;
605
606 DriverEntry = ModuleObject->EntryPoint;
607
608 if (ServiceName != NULL && ServiceName->Length != 0)
609 {
610 RegistryKey.Length = 0;
611 RegistryKey.MaximumLength = sizeof(ServicesKeyName) + ServiceName->Length;
612 RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength);
613 if (RegistryKey.Buffer == NULL)
614 {
615 return STATUS_INSUFFICIENT_RESOURCES;
616 }
617 RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName);
618 RtlAppendUnicodeStringToString(&RegistryKey, ServiceName);
619 }
620 else
621 {
622 RtlInitUnicodeString(&RegistryKey, NULL);
623 }
624
625 Status = IopCreateDriverObject(
626 DriverObject,
627 ServiceName,
628 0,
629 FileSystemDriver,
630 ModuleObject->DllBase,
631 ModuleObject->SizeOfImage);
632
633 if (!NT_SUCCESS(Status))
634 {
635 DPRINT("IopCreateDriverObject failed (Status %x)\n", Status);
636 return Status;
637 }
638
639 DPRINT("RegistryKey: %wZ\n", &RegistryKey);
640 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
641
642 IopMarkLastReinitializeDriver();
643
644 Status = DriverEntry(*DriverObject, &RegistryKey);
645
646 RtlFreeUnicodeString(&RegistryKey);
647
648 if (!NT_SUCCESS(Status))
649 {
650 ObMakeTemporaryObject(*DriverObject);
651 ObDereferenceObject(*DriverObject);
652 return Status;
653 }
654
655 IopReinitializeDrivers();
656
657 return STATUS_SUCCESS;
658 }
659
660 /*
661 * IopAttachFilterDriversCallback
662 *
663 * Internal routine used by IopAttachFilterDrivers.
664 */
665
666 NTSTATUS STDCALL
667 IopAttachFilterDriversCallback(
668 PWSTR ValueName,
669 ULONG ValueType,
670 PVOID ValueData,
671 ULONG ValueLength,
672 PVOID Context,
673 PVOID EntryContext)
674 {
675 PDEVICE_NODE DeviceNode = Context;
676 UNICODE_STRING ServiceName;
677 PWCHAR Filters;
678 PLDR_DATA_TABLE_ENTRY ModuleObject;
679 PDRIVER_OBJECT DriverObject;
680 NTSTATUS Status;
681
682 for (Filters = ValueData;
683 ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
684 *Filters != 0;
685 Filters += (ServiceName.Length / sizeof(WCHAR)) + 1)
686 {
687 DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath);
688 ServiceName.Buffer = Filters;
689 ServiceName.MaximumLength =
690 ServiceName.Length = wcslen(Filters) * sizeof(WCHAR);
691
692 /* Load and initialize the filter driver */
693 Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
694 if (Status != STATUS_IMAGE_ALREADY_LOADED)
695 {
696 if (!NT_SUCCESS(Status))
697 continue;
698
699 Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName,
700 FALSE, &DriverObject);
701 if (!NT_SUCCESS(Status))
702 continue;
703 }
704 else
705 {
706 /* get existing DriverObject pointer */
707 Status = IopGetDriverObject(
708 &DriverObject,
709 &ServiceName,
710 FALSE);
711 if (!NT_SUCCESS(Status))
712 continue;
713 }
714
715 Status = IopInitializeDevice(DeviceNode, DriverObject);
716 if (!NT_SUCCESS(Status))
717 continue;
718 }
719
720 return STATUS_SUCCESS;
721 }
722
723 /*
724 * IopAttachFilterDrivers
725 *
726 * Load filter drivers for specified device node.
727 *
728 * Parameters
729 * Lower
730 * Set to TRUE for loading lower level filters or FALSE for upper
731 * level filters.
732 */
733
734 NTSTATUS FASTCALL
735 IopAttachFilterDrivers(
736 PDEVICE_NODE DeviceNode,
737 BOOLEAN Lower)
738 {
739 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
740 PWCHAR KeyBuffer;
741 UNICODE_STRING Class;
742 WCHAR ClassBuffer[40];
743 NTSTATUS Status;
744
745 /*
746 * First load the device filters
747 */
748
749 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
750 if (Lower)
751 QueryTable[0].Name = L"LowerFilters";
752 else
753 QueryTable[0].Name = L"UpperFilters";
754 QueryTable[0].EntryContext = NULL;
755 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
756 QueryTable[1].QueryRoutine = NULL;
757 QueryTable[1].Name = NULL;
758
759 KeyBuffer = ExAllocatePool(
760 PagedPool,
761 (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
762 wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
763 wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
764
765 RtlQueryRegistryValues(
766 RTL_REGISTRY_ABSOLUTE,
767 KeyBuffer,
768 QueryTable,
769 DeviceNode,
770 NULL);
771
772 /*
773 * Now get the class GUID
774 */
775
776 Class.Length = 0;
777 Class.MaximumLength = 40 * sizeof(WCHAR);
778 Class.Buffer = ClassBuffer;
779 QueryTable[0].QueryRoutine = NULL;
780 QueryTable[0].Name = L"ClassGUID";
781 QueryTable[0].EntryContext = &Class;
782 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
783
784 Status = RtlQueryRegistryValues(
785 RTL_REGISTRY_ABSOLUTE,
786 KeyBuffer,
787 QueryTable,
788 DeviceNode,
789 NULL);
790
791 ExFreePool(KeyBuffer);
792
793 /*
794 * Load the class filter driver
795 */
796
797 if (NT_SUCCESS(Status))
798 {
799 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
800 if (Lower)
801 QueryTable[0].Name = L"LowerFilters";
802 else
803 QueryTable[0].Name = L"UpperFilters";
804 QueryTable[0].EntryContext = NULL;
805 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
806
807 KeyBuffer = ExAllocatePool(PagedPool, (58 * sizeof(WCHAR)) + Class.Length);
808 wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\");
809 wcscat(KeyBuffer, ClassBuffer);
810
811 RtlQueryRegistryValues(
812 RTL_REGISTRY_ABSOLUTE,
813 KeyBuffer,
814 QueryTable,
815 DeviceNode,
816 NULL);
817
818 ExFreePool(KeyBuffer);
819 }
820
821 return STATUS_SUCCESS;
822 }
823
824 static NTSTATUS STDCALL
825 IopGetGroupOrderList(PWSTR ValueName,
826 ULONG ValueType,
827 PVOID ValueData,
828 ULONG ValueLength,
829 PVOID Context,
830 PVOID EntryContext)
831 {
832 PSERVICE_GROUP Group;
833
834 DPRINT("IopGetGroupOrderList(%S, %x, 0x%p, %x, 0x%p, 0x%p)\n",
835 ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
836
837 if (ValueType == REG_BINARY &&
838 ValueData != NULL &&
839 ValueLength >= sizeof(DWORD) &&
840 ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
841 {
842 Group = (PSERVICE_GROUP)Context;
843 Group->TagCount = ((PULONG)ValueData)[0];
844 if (Group->TagCount > 0)
845 {
846 if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
847 {
848 Group->TagArray = ExAllocatePool(NonPagedPool, Group->TagCount * sizeof(DWORD));
849 if (Group->TagArray == NULL)
850 {
851 Group->TagCount = 0;
852 return STATUS_INSUFFICIENT_RESOURCES;
853 }
854 memcpy(Group->TagArray, (PULONG)ValueData + 1, Group->TagCount * sizeof(DWORD));
855 }
856 else
857 {
858 Group->TagCount = 0;
859 return STATUS_UNSUCCESSFUL;
860 }
861 }
862 }
863 return STATUS_SUCCESS;
864 }
865
866 static NTSTATUS STDCALL
867 IopCreateGroupListEntry(PWSTR ValueName,
868 ULONG ValueType,
869 PVOID ValueData,
870 ULONG ValueLength,
871 PVOID Context,
872 PVOID EntryContext)
873 {
874 PSERVICE_GROUP Group;
875 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
876 NTSTATUS Status;
877
878
879 if (ValueType == REG_SZ)
880 {
881 DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData);
882
883 Group = ExAllocatePool(NonPagedPool,
884 sizeof(SERVICE_GROUP));
885 if (Group == NULL)
886 {
887 return(STATUS_INSUFFICIENT_RESOURCES);
888 }
889
890 RtlZeroMemory(Group, sizeof(SERVICE_GROUP));
891
892 if (!RtlCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData))
893 {
894 ExFreePool(Group);
895 return(STATUS_INSUFFICIENT_RESOURCES);
896 }
897
898 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
899 QueryTable[0].Name = (PWSTR)ValueData;
900 QueryTable[0].QueryRoutine = IopGetGroupOrderList;
901
902 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
903 L"GroupOrderList",
904 QueryTable,
905 (PVOID)Group,
906 NULL);
907 DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
908
909 InsertTailList(&GroupListHead,
910 &Group->GroupListEntry);
911 }
912
913 return(STATUS_SUCCESS);
914 }
915
916
917 static NTSTATUS STDCALL
918 IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
919 {
920 RTL_QUERY_REGISTRY_TABLE QueryTable[7];
921 PSERVICE Service;
922 NTSTATUS Status;
923
924 DPRINT("ServiceName: '%wZ'\n", ServiceName);
925
926 /* Allocate service entry */
927 Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE));
928 if (Service == NULL)
929 {
930 DPRINT1("ExAllocatePool() failed\n");
931 return(STATUS_INSUFFICIENT_RESOURCES);
932 }
933 RtlZeroMemory(Service, sizeof(SERVICE));
934
935 /* Get service data */
936 RtlZeroMemory(&QueryTable,
937 sizeof(QueryTable));
938
939 QueryTable[0].Name = L"Start";
940 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
941 QueryTable[0].EntryContext = &Service->Start;
942
943 QueryTable[1].Name = L"Type";
944 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
945 QueryTable[1].EntryContext = &Service->Type;
946
947 QueryTable[2].Name = L"ErrorControl";
948 QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
949 QueryTable[2].EntryContext = &Service->ErrorControl;
950
951 QueryTable[3].Name = L"Group";
952 QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
953 QueryTable[3].EntryContext = &Service->ServiceGroup;
954
955 QueryTable[4].Name = L"ImagePath";
956 QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
957 QueryTable[4].EntryContext = &Service->ImagePath;
958
959 QueryTable[5].Name = L"Tag";
960 QueryTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
961 QueryTable[5].EntryContext = &Service->Tag;
962
963 Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
964 ServiceName->Buffer,
965 QueryTable,
966 NULL,
967 NULL);
968 if (!NT_SUCCESS(Status) || Service->Start > 1)
969 {
970 /*
971 * If something goes wrong during RtlQueryRegistryValues
972 * it'll just drop everything on the floor and return,
973 * so you have to check if the buffers were filled.
974 * Luckily we zerofilled the Service.
975 */
976 if (Service->ServiceGroup.Buffer)
977 {
978 ExFreePool(Service->ServiceGroup.Buffer);
979 }
980 if (Service->ImagePath.Buffer)
981 {
982 ExFreePool(Service->ImagePath.Buffer);
983 }
984 ExFreePool(Service);
985 return(Status);
986 }
987
988 /* Copy service name */
989 Service->ServiceName.Length = ServiceName->Length;
990 Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR);
991 Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool,
992 Service->ServiceName.MaximumLength);
993 RtlCopyMemory(Service->ServiceName.Buffer,
994 ServiceName->Buffer,
995 ServiceName->Length);
996 Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0;
997
998 /* Build registry path */
999 Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
1000 Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool,
1001 MAX_PATH * sizeof(WCHAR));
1002 wcscpy(Service->RegistryPath.Buffer,
1003 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
1004 wcscat(Service->RegistryPath.Buffer,
1005 Service->ServiceName.Buffer);
1006 Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR);
1007
1008 DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
1009 DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
1010 DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
1011 DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath);
1012 DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
1013 Service->Start, Service->Type, Service->Tag, Service->ErrorControl);
1014
1015 /* Append service entry */
1016 InsertTailList(&ServiceListHead,
1017 &Service->ServiceListEntry);
1018
1019 return(STATUS_SUCCESS);
1020 }
1021
1022
1023 NTSTATUS INIT_FUNCTION
1024 IoCreateDriverList(VOID)
1025 {
1026 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1027 PKEY_BASIC_INFORMATION KeyInfo = NULL;
1028 OBJECT_ATTRIBUTES ObjectAttributes;
1029 UNICODE_STRING ServicesKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
1030 UNICODE_STRING SubKeyName;
1031 HANDLE KeyHandle;
1032 NTSTATUS Status;
1033 ULONG Index;
1034
1035 ULONG KeyInfoLength = 0;
1036 ULONG ReturnedLength;
1037
1038 DPRINT("IoCreateDriverList() called\n");
1039
1040 /* Initialize basic variables */
1041 InitializeListHead(&GroupListHead);
1042 InitializeListHead(&ServiceListHead);
1043
1044 /* Build group order list */
1045 RtlZeroMemory(&QueryTable,
1046 sizeof(QueryTable));
1047
1048 QueryTable[0].Name = L"List";
1049 QueryTable[0].QueryRoutine = IopCreateGroupListEntry;
1050
1051 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
1052 L"ServiceGroupOrder",
1053 QueryTable,
1054 NULL,
1055 NULL);
1056 if (!NT_SUCCESS(Status))
1057 return(Status);
1058
1059 /* Enumerate services and create the service list */
1060 InitializeObjectAttributes(&ObjectAttributes,
1061 &ServicesKeyName,
1062 OBJ_CASE_INSENSITIVE,
1063 NULL,
1064 NULL);
1065
1066 Status = ZwOpenKey(&KeyHandle,
1067 KEY_ENUMERATE_SUB_KEYS,
1068 &ObjectAttributes);
1069 if (!NT_SUCCESS(Status))
1070 {
1071 return(Status);
1072 }
1073
1074 KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
1075 KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength);
1076 if (KeyInfo == NULL)
1077 {
1078 ZwClose(KeyHandle);
1079 return(STATUS_INSUFFICIENT_RESOURCES);
1080 }
1081
1082 Index = 0;
1083 while (TRUE)
1084 {
1085 Status = ZwEnumerateKey(KeyHandle,
1086 Index,
1087 KeyBasicInformation,
1088 KeyInfo,
1089 KeyInfoLength,
1090 &ReturnedLength);
1091 if (NT_SUCCESS(Status))
1092 {
1093 if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR))
1094 {
1095
1096 SubKeyName.Length = KeyInfo->NameLength;
1097 SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR);
1098 SubKeyName.Buffer = KeyInfo->Name;
1099 SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
1100
1101 DPRINT("KeyName: '%wZ'\n", &SubKeyName);
1102 IopCreateServiceListEntry(&SubKeyName);
1103 }
1104 }
1105
1106 if (!NT_SUCCESS(Status))
1107 break;
1108
1109 Index++;
1110 }
1111
1112 ExFreePool(KeyInfo);
1113 ZwClose(KeyHandle);
1114
1115 DPRINT("IoCreateDriverList() done\n");
1116
1117 return(STATUS_SUCCESS);
1118 }
1119
1120 NTSTATUS INIT_FUNCTION
1121 IoDestroyDriverList(VOID)
1122 {
1123 PSERVICE_GROUP CurrentGroup, tmp1;
1124 PSERVICE CurrentService, tmp2;
1125
1126 DPRINT("IoDestroyDriverList() called\n");
1127
1128 /* Destroy group list */
1129 LIST_FOR_EACH_SAFE(CurrentGroup, tmp1, &GroupListHead, SERVICE_GROUP, GroupListEntry)
1130 {
1131 ExFreePool(CurrentGroup->GroupName.Buffer);
1132 RemoveEntryList(&CurrentGroup->GroupListEntry);
1133 if (CurrentGroup->TagArray)
1134 {
1135 ExFreePool(CurrentGroup->TagArray);
1136 }
1137 ExFreePool(CurrentGroup);
1138 }
1139
1140 /* Destroy service list */
1141 LIST_FOR_EACH_SAFE(CurrentService, tmp2, &ServiceListHead, SERVICE, ServiceListEntry)
1142 {
1143 ExFreePool(CurrentService->ServiceName.Buffer);
1144 ExFreePool(CurrentService->RegistryPath.Buffer);
1145 ExFreePool(CurrentService->ServiceGroup.Buffer);
1146 ExFreePool(CurrentService->ImagePath.Buffer);
1147 RemoveEntryList(&CurrentService->ServiceListEntry);
1148 ExFreePool(CurrentService);
1149 }
1150
1151 DPRINT("IoDestroyDriverList() done\n");
1152
1153 return(STATUS_SUCCESS);
1154 }
1155
1156 VOID STATIC INIT_FUNCTION
1157 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
1158 {
1159 ULONG i;
1160
1161 for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
1162 {
1163 MmDeleteVirtualMapping(NULL, (char*)StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
1164 }
1165 }
1166
1167 /*
1168 * IopInitializeBuiltinDriver
1169 *
1170 * Initialize a driver that is already loaded in memory.
1171 */
1172
1173 NTSTATUS FASTCALL INIT_FUNCTION
1174 IopInitializeBuiltinDriver(
1175 PDEVICE_NODE ModuleDeviceNode,
1176 PVOID ModuleLoadBase,
1177 PCHAR FileName,
1178 ULONG ModuleLength)
1179 {
1180 PLDR_DATA_TABLE_ENTRY ModuleObject;
1181 PDEVICE_NODE DeviceNode;
1182 PDRIVER_OBJECT DriverObject;
1183 NTSTATUS Status;
1184 PCHAR FileNameWithoutPath;
1185 LPWSTR FileExtension;
1186
1187 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1188 FileName, ModuleLoadBase, ModuleLength);
1189
1190 /*
1191 * Display 'Loading XXX...' message
1192 */
1193 IopDisplayLoadingMessage(FileName, FALSE);
1194
1195 /*
1196 * Determine the right device object
1197 */
1198
1199 if (ModuleDeviceNode == NULL)
1200 {
1201 /* Use IopRootDeviceNode for now */
1202 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
1203 if (!NT_SUCCESS(Status))
1204 {
1205 CPRINT("Driver '%s' load failed, status (%x)\n", FileName, Status);
1206 return(Status);
1207 }
1208 } else
1209 {
1210 DeviceNode = ModuleDeviceNode;
1211 }
1212
1213 /*
1214 * Generate filename without path (not needed by freeldr)
1215 */
1216
1217 FileNameWithoutPath = strrchr(FileName, '\\');
1218 if (FileNameWithoutPath == NULL)
1219 {
1220 FileNameWithoutPath = FileName;
1221 }
1222
1223 /*
1224 * Load the module
1225 */
1226
1227 RtlCreateUnicodeStringFromAsciiz(&DeviceNode->ServiceName,
1228 FileNameWithoutPath);
1229 Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName,
1230 &ModuleObject);
1231 if (!NT_SUCCESS(Status))
1232 {
1233 if (ModuleDeviceNode == NULL)
1234 IopFreeDeviceNode(DeviceNode);
1235 CPRINT("Driver '%s' load failed, status (%x)\n", FileName, Status);
1236 return Status;
1237 }
1238
1239 /* Load symbols */
1240 KDB_SYMBOLFILE_HOOK(FileName);
1241
1242 /*
1243 * Strip the file extension from ServiceName
1244 */
1245
1246 FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.');
1247 if (FileExtension != NULL)
1248 {
1249 DeviceNode->ServiceName.Length -= wcslen(FileExtension) * sizeof(WCHAR);
1250 FileExtension[0] = 0;
1251 }
1252
1253 /*
1254 * Initialize the driver
1255 */
1256
1257 Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
1258 &DeviceNode->ServiceName, FALSE, &DriverObject);
1259
1260 if (!NT_SUCCESS(Status))
1261 {
1262 if (ModuleDeviceNode == NULL)
1263 IopFreeDeviceNode(DeviceNode);
1264 CPRINT("Driver '%s' load failed, status (%x)\n", FileName, Status);
1265 return Status;
1266 }
1267
1268 Status = IopInitializeDevice(DeviceNode, DriverObject);
1269 if (NT_SUCCESS(Status))
1270 {
1271 Status = IopStartDevice(DeviceNode);
1272 }
1273
1274 return Status;
1275 }
1276
1277 /*
1278 * IopInitializeBootDrivers
1279 *
1280 * Initialize boot drivers and free memory for boot files.
1281 *
1282 * Parameters
1283 * None
1284 *
1285 * Return Value
1286 * None
1287 */
1288
1289 VOID FASTCALL
1290 IopInitializeBootDrivers(VOID)
1291 {
1292 ULONG BootDriverCount;
1293 ULONG ModuleStart;
1294 ULONG ModuleSize;
1295 ULONG ModuleLoaded;
1296 PCHAR ModuleName;
1297 PCHAR Extension;
1298 PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr;
1299 ULONG i;
1300 UNICODE_STRING DriverName;
1301 NTSTATUS Status;
1302
1303 DPRINT("IopInitializeBootDrivers()\n");
1304
1305 BootDriverCount = 0;
1306 for (i = 0; i < KeLoaderBlock.ModsCount; i++)
1307 {
1308 ModuleStart = KeLoaderModules[i].ModStart;
1309 ModuleSize = KeLoaderModules[i].ModEnd - ModuleStart;
1310 ModuleName = (PCHAR)KeLoaderModules[i].String;
1311 ModuleLoaded = KeLoaderModules[i].Reserved;
1312 Extension = strrchr(ModuleName, '.');
1313 if (Extension == NULL)
1314 Extension = "";
1315
1316 if (!_stricmp(Extension, ".sym") || !_stricmp(Extension, ".dll"))
1317 {
1318 /* Process symbols for *.exe and *.dll */
1319 KDB_SYMBOLFILE_HOOK(ModuleName);
1320
1321 /* Log *.exe and *.dll files */
1322 RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName);
1323 IopBootLog(&DriverName, TRUE);
1324 RtlFreeUnicodeString(&DriverName);
1325 }
1326 else if (!_stricmp(Extension, ".sys"))
1327 {
1328 /* Initialize and log boot start driver */
1329 if (!ModuleLoaded)
1330 {
1331 Status = IopInitializeBuiltinDriver(NULL,
1332 (PVOID)ModuleStart,
1333 ModuleName,
1334 ModuleSize);
1335 RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName);
1336 IopBootLog(&DriverName, NT_SUCCESS(Status) ? TRUE : FALSE);
1337 RtlFreeUnicodeString(&DriverName);
1338 }
1339 BootDriverCount++;
1340 }
1341 }
1342
1343 /*
1344 * Free memory for all boot files, except ntoskrnl.exe.
1345 */
1346 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
1347 {
1348 MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
1349 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
1350 }
1351
1352 KeLoaderBlock.ModsCount = 0;
1353
1354 if (BootDriverCount == 0)
1355 {
1356 DbgPrint("No boot drivers available.\n");
1357 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
1358 }
1359 }
1360
1361 static INIT_FUNCTION NTSTATUS
1362 IopLoadDriver(PSERVICE Service)
1363 {
1364 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1365
1366 IopDisplayLoadingMessage(Service->ServiceName.Buffer, TRUE);
1367 Status = ZwLoadDriver(&Service->RegistryPath);
1368 IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE);
1369 if (!NT_SUCCESS(Status))
1370 {
1371 DPRINT("IopLoadDriver() failed (Status %lx)\n", Status);
1372 #if 0
1373 if (Service->ErrorControl == 1)
1374 {
1375 /* Log error */
1376 }
1377 else if (Service->ErrorControl == 2)
1378 {
1379 if (IsLastKnownGood == FALSE)
1380 {
1381 /* Boot last known good configuration */
1382 }
1383 }
1384 else if (Service->ErrorControl == 3)
1385 {
1386 if (IsLastKnownGood == FALSE)
1387 {
1388 /* Boot last known good configuration */
1389 }
1390 else
1391 {
1392 /* BSOD! */
1393 }
1394 }
1395 #endif
1396 }
1397 return Status;
1398 }
1399
1400
1401 /*
1402 * IopInitializeSystemDrivers
1403 *
1404 * Load drivers marked as system start.
1405 *
1406 * Parameters
1407 * None
1408 *
1409 * Return Value
1410 * None
1411 */
1412
1413 VOID FASTCALL
1414 IopInitializeSystemDrivers(VOID)
1415 {
1416 PSERVICE_GROUP CurrentGroup;
1417 PSERVICE CurrentService;
1418 NTSTATUS Status;
1419 ULONG i;
1420
1421 DPRINT("IopInitializeSystemDrivers()\n");
1422
1423 LIST_FOR_EACH(CurrentGroup, &GroupListHead, SERVICE_GROUP, GroupListEntry)
1424 {
1425 DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
1426
1427 /* Load all drivers with a valid tag */
1428 for (i = 0; i < CurrentGroup->TagCount; i++)
1429 {
1430 LIST_FOR_EACH(CurrentService, &ServiceListHead, SERVICE, ServiceListEntry)
1431 {
1432 if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
1433 &CurrentService->ServiceGroup, TRUE) == 0) &&
1434 (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/) &&
1435 (CurrentService->Tag == CurrentGroup->TagArray[i]))
1436 {
1437 DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath);
1438 Status = IopLoadDriver(CurrentService);
1439 }
1440 }
1441 }
1442
1443 /* Load all drivers without a tag or with an invalid tag */
1444 LIST_FOR_EACH(CurrentService, &ServiceListHead, SERVICE, ServiceListEntry)
1445 {
1446 if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
1447 &CurrentService->ServiceGroup, TRUE) == 0) &&
1448 (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))
1449 {
1450 for (i = 0; i < CurrentGroup->TagCount; i++)
1451 {
1452 if (CurrentGroup->TagArray[i] == CurrentService->Tag)
1453 {
1454 break;
1455 }
1456 }
1457 if (i >= CurrentGroup->TagCount)
1458 {
1459 DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath);
1460 Status = IopLoadDriver(CurrentService);
1461 }
1462 }
1463 }
1464
1465 }
1466
1467 DPRINT("IopInitializeSystemDrivers() done\n");
1468 }
1469
1470 /*
1471 * IopUnloadDriver
1472 *
1473 * Unloads a device driver.
1474 *
1475 * Parameters
1476 * DriverServiceName
1477 * Name of the service to unload (registry key).
1478 *
1479 * UnloadPnpDrivers
1480 * Whether to unload Plug & Plug or only legacy drivers. If this
1481 * parameter is set to FALSE, the routine will unload only legacy
1482 * drivers.
1483 *
1484 * Return Value
1485 * Status
1486 *
1487 * To do
1488 * Guard the whole function by SEH.
1489 */
1490
1491 NTSTATUS STDCALL
1492 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
1493 {
1494 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1495 UNICODE_STRING ImagePath;
1496 UNICODE_STRING ServiceName;
1497 UNICODE_STRING ObjectName;
1498 PDRIVER_OBJECT DriverObject;
1499 PLDR_DATA_TABLE_ENTRY ModuleObject;
1500 NTSTATUS Status;
1501 LPWSTR Start;
1502
1503 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers);
1504
1505 PAGED_CODE();
1506
1507 /*
1508 * Get the service name from the registry key name
1509 */
1510
1511 Start = wcsrchr(DriverServiceName->Buffer, L'\\');
1512 if (Start == NULL)
1513 Start = DriverServiceName->Buffer;
1514 else
1515 Start++;
1516
1517 RtlInitUnicodeString(&ServiceName, Start);
1518
1519 /*
1520 * Construct the driver object name
1521 */
1522
1523 ObjectName.Length = (wcslen(Start) + 8) * sizeof(WCHAR);
1524 ObjectName.MaximumLength = ObjectName.Length + sizeof(WCHAR);
1525 ObjectName.Buffer = ExAllocatePool(PagedPool, ObjectName.MaximumLength);
1526 wcscpy(ObjectName.Buffer, L"\\Driver\\");
1527 memcpy(ObjectName.Buffer + 8, Start, (ObjectName.Length - 8) * sizeof(WCHAR));
1528 ObjectName.Buffer[ObjectName.Length/sizeof(WCHAR)] = 0;
1529
1530 /*
1531 * Find the driver object
1532 */
1533
1534 Status = ObReferenceObjectByName(&ObjectName, 0, 0, 0, IoDriverObjectType,
1535 KernelMode, 0, (PVOID*)&DriverObject);
1536
1537 if (!NT_SUCCESS(Status))
1538 {
1539 DPRINT("Can't locate driver object for %wZ\n", ObjectName);
1540 return Status;
1541 }
1542
1543 /*
1544 * Free the buffer for driver object name
1545 */
1546
1547 ExFreePool(ObjectName.Buffer);
1548
1549 /*
1550 * Get path of service...
1551 */
1552
1553 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1554
1555 RtlInitUnicodeString(&ImagePath, NULL);
1556
1557 QueryTable[0].Name = L"ImagePath";
1558 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1559 QueryTable[0].EntryContext = &ImagePath;
1560
1561 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1562 DriverServiceName->Buffer, QueryTable, NULL, NULL);
1563
1564 if (!NT_SUCCESS(Status))
1565 {
1566 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1567 return Status;
1568 }
1569
1570 /*
1571 * Normalize the image path for all later processing.
1572 */
1573
1574 Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1575
1576 if (!NT_SUCCESS(Status))
1577 {
1578 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1579 return Status;
1580 }
1581
1582 /*
1583 * ... and check if it's loaded
1584 */
1585
1586 ModuleObject = LdrGetModuleObject(&ImagePath);
1587 if (ModuleObject == NULL)
1588 {
1589 return STATUS_UNSUCCESSFUL;
1590 }
1591
1592 /*
1593 * Free the service path
1594 */
1595
1596 ExFreePool(ImagePath.Buffer);
1597
1598 /*
1599 * Unload the module and release the references to the device object
1600 */
1601
1602 if (DriverObject->DriverUnload)
1603 (*DriverObject->DriverUnload)(DriverObject);
1604 ObDereferenceObject(DriverObject);
1605 ObDereferenceObject(DriverObject);
1606 LdrUnloadModule(ModuleObject);
1607
1608 return STATUS_SUCCESS;
1609 }
1610
1611 VOID FASTCALL
1612 IopMarkLastReinitializeDriver(VOID)
1613 {
1614 KIRQL Irql;
1615
1616 KeAcquireSpinLock(&DriverReinitListLock,
1617 &Irql);
1618
1619 if (IsListEmpty(&DriverReinitListHead))
1620 {
1621 DriverReinitTailEntry = NULL;
1622 }
1623 else
1624 {
1625 DriverReinitTailEntry = DriverReinitListHead.Blink;
1626 }
1627
1628 KeReleaseSpinLock(&DriverReinitListLock,
1629 Irql);
1630 }
1631
1632
1633 VOID FASTCALL
1634 IopReinitializeDrivers(VOID)
1635 {
1636 PDRIVER_REINIT_ITEM ReinitItem;
1637 PLIST_ENTRY Entry;
1638 KIRQL Irql;
1639
1640 KeAcquireSpinLock(&DriverReinitListLock,
1641 &Irql);
1642
1643 Entry = DriverReinitTailEntry;
1644
1645 KeReleaseSpinLock(&DriverReinitListLock,
1646 Irql);
1647
1648 if (Entry == NULL)
1649 {
1650 return;
1651 }
1652
1653 for (;;)
1654 {
1655 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
1656 &DriverReinitListLock);
1657 if (Entry == NULL)
1658 return;
1659
1660 ReinitItem = (PDRIVER_REINIT_ITEM)CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1661
1662 /* Increment reinitialization counter */
1663 ReinitItem->DriverObject->DriverExtension->Count++;
1664
1665 ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1666 ReinitItem->Context,
1667 ReinitItem->DriverObject->DriverExtension->Count);
1668
1669 ExFreePool(Entry);
1670
1671 if (Entry == DriverReinitTailEntry)
1672 return;
1673 }
1674 }
1675
1676 /* PUBLIC FUNCTIONS ***********************************************************/
1677
1678
1679 /*
1680 * @implemented
1681 */
1682 NTSTATUS
1683 STDCALL
1684 IoCreateDriver (
1685 IN PUNICODE_STRING DriverName, OPTIONAL
1686 IN PDRIVER_INITIALIZE InitializationFunction
1687 )
1688 {
1689 WCHAR NameBuffer[100];
1690 USHORT NameLength;
1691 UNICODE_STRING LocalDriverName; /* To reduce code if no name given */
1692 NTSTATUS Status;
1693 OBJECT_ATTRIBUTES ObjectAttributes;
1694 ULONG ObjectSize;
1695 PDRIVER_OBJECT DriverObject;
1696 UNICODE_STRING ServiceKeyName;
1697 HANDLE hDriver;
1698 ULONG i;
1699
1700 /* First, create a unique name for the driver if we don't have one */
1701 if (!DriverName) {
1702
1703 /* Create a random name and set up the string*/
1704 NameLength = swprintf(NameBuffer, L"\\Driver\\%08u", KeTickCount);
1705 LocalDriverName.Length = NameLength * sizeof(WCHAR);
1706 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1707 LocalDriverName.Buffer = NameBuffer;
1708
1709 } else {
1710
1711 /* So we can avoid another code path, use a local var */
1712 LocalDriverName = *DriverName;
1713 }
1714
1715 /* Initialize the Attributes */
1716 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(DRIVER_EXTENSION);
1717 InitializeObjectAttributes(&ObjectAttributes,
1718 &LocalDriverName,
1719 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
1720 NULL,
1721 NULL);
1722
1723 /* Create the Object */
1724 Status = ObCreateObject(KernelMode,
1725 IoDriverObjectType,
1726 &ObjectAttributes,
1727 KernelMode,
1728 NULL,
1729 ObjectSize,
1730 0,
1731 0,
1732 (PVOID*)&DriverObject);
1733
1734 /* Return on failure */
1735 if (!NT_SUCCESS(Status)) return Status;
1736
1737 /* Set up the Object */
1738 RtlZeroMemory(DriverObject, ObjectSize);
1739 DriverObject->Type = IO_TYPE_DRIVER;
1740 DriverObject->Size = sizeof(DRIVER_OBJECT);
1741 DriverObject->Flags = DRVO_BUILTIN_DRIVER;
1742 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
1743 DriverObject->DriverExtension->DriverObject = DriverObject;
1744 DriverObject->DriverInit = InitializationFunction;
1745
1746 /* Invalidate all Major Functions */
1747 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1748 {
1749 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1750 }
1751
1752 /* Set up the Service Key Name */
1753 ServiceKeyName.Buffer = ExAllocatePool(PagedPool, LocalDriverName.Length + sizeof(WCHAR));
1754 ServiceKeyName.Length = LocalDriverName.Length;
1755 ServiceKeyName.MaximumLength = LocalDriverName.MaximumLength;
1756 RtlMoveMemory(ServiceKeyName.Buffer, LocalDriverName.Buffer, LocalDriverName.Length);
1757 ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = L'\0';
1758 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
1759
1760 /* Also store it in the Driver Object. This is a bit of a hack. */
1761 RtlMoveMemory(&DriverObject->DriverName, &ServiceKeyName, sizeof(UNICODE_STRING));
1762
1763 /* Add the Object and get its handle */
1764 Status = ObInsertObject(DriverObject,
1765 NULL,
1766 FILE_READ_DATA,
1767 0,
1768 NULL,
1769 &hDriver);
1770
1771 /* Return on Failure */
1772 if (!NT_SUCCESS(Status)) return Status;
1773
1774 /* Now reference it */
1775 Status = ObReferenceObjectByHandle(hDriver,
1776 0,
1777 IoDriverObjectType,
1778 KernelMode,
1779 (PVOID*)&DriverObject,
1780 NULL);
1781 ZwClose(hDriver);
1782
1783 /* Finally, call its init function */
1784 Status = (*InitializationFunction)(DriverObject, NULL);
1785
1786 if (!NT_SUCCESS(Status)) {
1787 /* If it didn't work, then kill the object */
1788 ObMakeTemporaryObject(DriverObject);
1789 ObDereferenceObject(DriverObject);
1790 }
1791
1792 /* Return the Status */
1793 return Status;
1794 }
1795
1796 /*
1797 * @implemented
1798 */
1799 VOID
1800 STDCALL
1801 IoDeleteDriver (
1802 IN PDRIVER_OBJECT DriverObject
1803 )
1804 {
1805 /* Simply derefence the Object */
1806 ObDereferenceObject(DriverObject);
1807 }
1808
1809
1810 /*
1811 * NtLoadDriver
1812 *
1813 * Loads a device driver.
1814 *
1815 * Parameters
1816 * DriverServiceName
1817 * Name of the service to load (registry key).
1818 *
1819 * Return Value
1820 * Status
1821 *
1822 * Status
1823 * implemented
1824 */
1825
1826 NTSTATUS STDCALL
1827 NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
1828 {
1829 RTL_QUERY_REGISTRY_TABLE QueryTable[3];
1830 UNICODE_STRING ImagePath;
1831 UNICODE_STRING ServiceName;
1832 UNICODE_STRING CapturedDriverServiceName = {0};
1833 KPROCESSOR_MODE PreviousMode;
1834 NTSTATUS Status;
1835 ULONG Type;
1836 PDEVICE_NODE DeviceNode;
1837 PLDR_DATA_TABLE_ENTRY ModuleObject;
1838 PDRIVER_OBJECT DriverObject;
1839 WCHAR *cur;
1840
1841 PAGED_CODE();
1842
1843 PreviousMode = KeGetPreviousMode();
1844
1845 /*
1846 * Check security privileges
1847 */
1848
1849 /* FIXME: Uncomment when privileges will be correctly implemented. */
1850 #if 0
1851 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
1852 {
1853 DPRINT("Privilege not held\n");
1854 return STATUS_PRIVILEGE_NOT_HELD;
1855 }
1856 #endif
1857
1858 Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,
1859 PreviousMode,
1860 DriverServiceName);
1861 if (!NT_SUCCESS(Status))
1862 {
1863 return Status;
1864 }
1865
1866 DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName);
1867
1868 RtlInitUnicodeString(&ImagePath, NULL);
1869
1870 /*
1871 * Get the service name from the registry key name.
1872 */
1873 ASSERT(CapturedDriverServiceName.Length >= sizeof(WCHAR));
1874
1875 ServiceName = CapturedDriverServiceName;
1876 cur = CapturedDriverServiceName.Buffer + (CapturedDriverServiceName.Length / sizeof(WCHAR)) - 1;
1877 while (CapturedDriverServiceName.Buffer != cur)
1878 {
1879 if(*cur == L'\\')
1880 {
1881 ServiceName.Buffer = cur + 1;
1882 ServiceName.Length = CapturedDriverServiceName.Length -
1883 (USHORT)((ULONG_PTR)ServiceName.Buffer -
1884 (ULONG_PTR)CapturedDriverServiceName.Buffer);
1885 break;
1886 }
1887 cur--;
1888 }
1889
1890 /*
1891 * Get service type.
1892 */
1893
1894 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
1895
1896 RtlInitUnicodeString(&ImagePath, NULL);
1897
1898 QueryTable[0].Name = L"Type";
1899 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
1900 QueryTable[0].EntryContext = &Type;
1901
1902 QueryTable[1].Name = L"ImagePath";
1903 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
1904 QueryTable[1].EntryContext = &ImagePath;
1905
1906 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1907 CapturedDriverServiceName.Buffer, QueryTable, NULL, NULL);
1908
1909 if (!NT_SUCCESS(Status))
1910 {
1911 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
1912 ExFreePool(ImagePath.Buffer);
1913 goto ReleaseCapturedString;
1914 }
1915
1916 /*
1917 * Normalize the image path for all later processing.
1918 */
1919
1920 Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1921
1922 if (!NT_SUCCESS(Status))
1923 {
1924 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1925 goto ReleaseCapturedString;
1926 }
1927
1928 DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
1929 DPRINT("Type: %lx\n", Type);
1930
1931 /*
1932 * See, if the driver module isn't already loaded
1933 */
1934
1935 ModuleObject = LdrGetModuleObject(&ImagePath);
1936 if (ModuleObject != NULL)
1937 {
1938 DPRINT("Image already loaded\n");
1939 Status = STATUS_IMAGE_ALREADY_LOADED;
1940 goto ReleaseCapturedString;
1941 }
1942
1943 /*
1944 * Create device node
1945 */
1946
1947 /* Use IopRootDeviceNode for now */
1948 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
1949
1950 if (!NT_SUCCESS(Status))
1951 {
1952 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
1953 goto ReleaseCapturedString;
1954 }
1955
1956 /*
1957 * Load the driver module
1958 */
1959
1960 Status = LdrLoadModule(&ImagePath, &ModuleObject);
1961
1962 if (!NT_SUCCESS(Status))
1963 {
1964 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status);
1965 IopFreeDeviceNode(DeviceNode);
1966 goto ReleaseCapturedString;
1967 }
1968
1969 /*
1970 * Set a service name for the device node
1971 */
1972
1973 RtlCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer);
1974
1975 /*
1976 * Initialize the driver module
1977 */
1978
1979 Status = IopInitializeDriverModule(
1980 DeviceNode,
1981 ModuleObject,
1982 &DeviceNode->ServiceName,
1983 (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
1984 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
1985 &DriverObject);
1986
1987 if (!NT_SUCCESS(Status))
1988 {
1989 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status);
1990 LdrUnloadModule(ModuleObject);
1991 IopFreeDeviceNode(DeviceNode);
1992 goto ReleaseCapturedString;
1993 }
1994
1995 IopInitializeDevice(DeviceNode, DriverObject);
1996 Status = IopStartDevice(DeviceNode);
1997
1998 ReleaseCapturedString:
1999 ReleaseCapturedUnicodeString(&CapturedDriverServiceName,
2000 PreviousMode);
2001
2002 return Status;
2003 }
2004
2005 /*
2006 * NtUnloadDriver
2007 *
2008 * Unloads a legacy device driver.
2009 *
2010 * Parameters
2011 * DriverServiceName
2012 * Name of the service to unload (registry key).
2013 *
2014 * Return Value
2015 * Status
2016 *
2017 * Status
2018 * implemented
2019 */
2020
2021 NTSTATUS STDCALL
2022 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
2023 {
2024 return IopUnloadDriver(DriverServiceName, FALSE);
2025 }
2026
2027 /*
2028 * IoRegisterDriverReinitialization
2029 *
2030 * Status
2031 * @implemented
2032 */
2033
2034 VOID STDCALL
2035 IoRegisterDriverReinitialization(
2036 PDRIVER_OBJECT DriverObject,
2037 PDRIVER_REINITIALIZE ReinitRoutine,
2038 PVOID Context)
2039 {
2040 PDRIVER_REINIT_ITEM ReinitItem;
2041
2042 ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
2043 if (ReinitItem == NULL)
2044 return;
2045
2046 ReinitItem->DriverObject = DriverObject;
2047 ReinitItem->ReinitRoutine = ReinitRoutine;
2048 ReinitItem->Context = Context;
2049
2050 DriverObject->Flags |= DRVO_REINIT_REGISTERED;
2051
2052 ExInterlockedInsertTailList(
2053 &DriverReinitListHead,
2054 &ReinitItem->ItemEntry,
2055 &DriverReinitListLock);
2056 }
2057
2058 /*
2059 * @implemented
2060 */
2061 VOID
2062 STDCALL
2063 IoRegisterBootDriverReinitialization(
2064 IN PDRIVER_OBJECT DriverObject,
2065 IN PDRIVER_REINITIALIZE DriverReinitializationRoutine,
2066 IN PVOID Context
2067 )
2068 {
2069 PDRIVER_REINIT_ITEM ReinitItem;
2070
2071 ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
2072 if (ReinitItem == NULL)
2073 return;
2074
2075 ReinitItem->DriverObject = DriverObject;
2076 ReinitItem->ReinitRoutine = DriverReinitializationRoutine;
2077 ReinitItem->Context = Context;
2078
2079 DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED;
2080
2081 ExInterlockedInsertTailList(
2082 &DriverBootReinitListHead,
2083 &ReinitItem->ItemEntry,
2084 &DriverReinitListLock);
2085 }
2086
2087 /*
2088 * IoAllocateDriverObjectExtension
2089 *
2090 * Status
2091 * @implemented
2092 */
2093
2094 NTSTATUS STDCALL
2095 IoAllocateDriverObjectExtension(
2096 PDRIVER_OBJECT DriverObject,
2097 PVOID ClientIdentificationAddress,
2098 ULONG DriverObjectExtensionSize,
2099 PVOID *DriverObjectExtension)
2100 {
2101 KIRQL OldIrql;
2102 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions;
2103 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension;
2104
2105 NewDriverExtension = ExAllocatePoolWithTag(
2106 NonPagedPool,
2107 sizeof(PRIVATE_DRIVER_EXTENSIONS) - sizeof(CHAR) +
2108 DriverObjectExtensionSize,
2109 TAG_DRIVER_EXTENSION);
2110
2111 if (NewDriverExtension == NULL)
2112 {
2113 return STATUS_INSUFFICIENT_RESOURCES;
2114 }
2115
2116 OldIrql = KeRaiseIrqlToDpcLevel();
2117
2118 NewDriverExtension->Link = DriverObject->DriverSection;
2119 NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress;
2120
2121 for (DriverExtensions = DriverObject->DriverSection;
2122 DriverExtensions != NULL;
2123 DriverExtensions = DriverExtensions->Link)
2124 {
2125 if (DriverExtensions->ClientIdentificationAddress ==
2126 ClientIdentificationAddress)
2127 {
2128 KfLowerIrql(OldIrql);
2129 return STATUS_OBJECT_NAME_COLLISION;
2130 }
2131 }
2132
2133 DriverObject->DriverSection = NewDriverExtension;
2134
2135 KfLowerIrql(OldIrql);
2136
2137 *DriverObjectExtension = &NewDriverExtension->Extension;
2138
2139 return STATUS_SUCCESS;
2140 }
2141
2142 /*
2143 * IoGetDriverObjectExtension
2144 *
2145 * Status
2146 * @implemented
2147 */
2148
2149 PVOID STDCALL
2150 IoGetDriverObjectExtension(
2151 PDRIVER_OBJECT DriverObject,
2152 PVOID ClientIdentificationAddress)
2153 {
2154 KIRQL OldIrql;
2155 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions;
2156
2157 OldIrql = KeRaiseIrqlToDpcLevel();
2158
2159 for (DriverExtensions = DriverObject->DriverSection;
2160 DriverExtensions != NULL &&
2161 DriverExtensions->ClientIdentificationAddress !=
2162 ClientIdentificationAddress;
2163 DriverExtensions = DriverExtensions->Link)
2164 ;
2165
2166 KfLowerIrql(OldIrql);
2167
2168 if (DriverExtensions == NULL)
2169 return NULL;
2170
2171 return &DriverExtensions->Extension;
2172 }
2173
2174 /* EOF */