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