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