started moving tags to a private internal header
[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 ROS_STRING_INITIALIZER(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 DPRINT1("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 %x)\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 if (SetupMode) return;
341 CHAR TextBuffer[256];
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, %x)\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, %x, %x, %x, %x)\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;
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 RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName,
1054 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
1055
1056 InitializeObjectAttributes(&ObjectAttributes,
1057 &ServicesKeyName,
1058 OBJ_CASE_INSENSITIVE,
1059 NULL,
1060 NULL);
1061
1062 Status = ZwOpenKey(&KeyHandle,
1063 KEY_ENUMERATE_SUB_KEYS,
1064 &ObjectAttributes);
1065 if (!NT_SUCCESS(Status))
1066 {
1067 return(Status);
1068 }
1069
1070 KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
1071 KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength);
1072 if (KeyInfo == NULL)
1073 {
1074 ZwClose(KeyHandle);
1075 return(STATUS_INSUFFICIENT_RESOURCES);
1076 }
1077
1078 Index = 0;
1079 while (TRUE)
1080 {
1081 Status = ZwEnumerateKey(KeyHandle,
1082 Index,
1083 KeyBasicInformation,
1084 KeyInfo,
1085 KeyInfoLength,
1086 &ReturnedLength);
1087 if (NT_SUCCESS(Status))
1088 {
1089 if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR))
1090 {
1091
1092 SubKeyName.Length = KeyInfo->NameLength;
1093 SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR);
1094 SubKeyName.Buffer = KeyInfo->Name;
1095 SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
1096
1097 DPRINT("KeyName: '%wZ'\n", &SubKeyName);
1098 IopCreateServiceListEntry(&SubKeyName);
1099 }
1100 }
1101
1102 if (!NT_SUCCESS(Status))
1103 break;
1104
1105 Index++;
1106 }
1107
1108 ExFreePool(KeyInfo);
1109 ZwClose(KeyHandle);
1110
1111 DPRINT("IoCreateDriverList() done\n");
1112
1113 return(STATUS_SUCCESS);
1114 }
1115
1116 NTSTATUS INIT_FUNCTION
1117 IoDestroyDriverList(VOID)
1118 {
1119 PLIST_ENTRY GroupEntry;
1120 PLIST_ENTRY ServiceEntry;
1121 PSERVICE_GROUP CurrentGroup;
1122 PSERVICE CurrentService;
1123
1124 DPRINT("IoDestroyDriverList() called\n");
1125
1126 /* Destroy group list */
1127 GroupEntry = GroupListHead.Flink;
1128 while (GroupEntry != &GroupListHead)
1129 {
1130 CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
1131
1132 ExFreePool(CurrentGroup->GroupName.Buffer);
1133 RemoveEntryList(GroupEntry);
1134 if (CurrentGroup->TagArray)
1135 {
1136 ExFreePool(CurrentGroup->TagArray);
1137 }
1138 ExFreePool(CurrentGroup);
1139
1140 GroupEntry = GroupListHead.Flink;
1141 }
1142
1143 /* Destroy service list */
1144 ServiceEntry = ServiceListHead.Flink;
1145 while (ServiceEntry != &ServiceListHead)
1146 {
1147 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1148
1149 ExFreePool(CurrentService->ServiceName.Buffer);
1150 ExFreePool(CurrentService->RegistryPath.Buffer);
1151 ExFreePool(CurrentService->ServiceGroup.Buffer);
1152 ExFreePool(CurrentService->ImagePath.Buffer);
1153 RemoveEntryList(ServiceEntry);
1154 ExFreePool(CurrentService);
1155
1156 ServiceEntry = ServiceListHead.Flink;
1157 }
1158
1159 DPRINT("IoDestroyDriverList() done\n");
1160
1161 return(STATUS_SUCCESS);
1162 }
1163
1164 VOID STATIC INIT_FUNCTION
1165 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
1166 {
1167 ULONG i;
1168
1169 for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
1170 {
1171 MmDeleteVirtualMapping(NULL, (char*)StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
1172 }
1173 }
1174
1175 /*
1176 * IopInitializeBuiltinDriver
1177 *
1178 * Initialize a driver that is already loaded in memory.
1179 */
1180
1181 NTSTATUS FASTCALL INIT_FUNCTION
1182 IopInitializeBuiltinDriver(
1183 PDEVICE_NODE ModuleDeviceNode,
1184 PVOID ModuleLoadBase,
1185 PCHAR FileName,
1186 ULONG ModuleLength)
1187 {
1188 PMODULE_OBJECT ModuleObject;
1189 PDEVICE_NODE DeviceNode;
1190 PDRIVER_OBJECT DriverObject;
1191 NTSTATUS Status;
1192 PCHAR FileNameWithoutPath;
1193 LPWSTR FileExtension;
1194
1195 DPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
1196 FileName, ModuleLoadBase, ModuleLength);
1197
1198 /*
1199 * Display 'Loading XXX...' message
1200 */
1201 IopDisplayLoadingMessage(FileName, FALSE);
1202
1203 /*
1204 * Determine the right device object
1205 */
1206
1207 if (ModuleDeviceNode == NULL)
1208 {
1209 /* Use IopRootDeviceNode for now */
1210 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
1211 if (!NT_SUCCESS(Status))
1212 {
1213 CPRINT("Driver load failed, status (%x)\n", Status);
1214 return(Status);
1215 }
1216 } else
1217 {
1218 DeviceNode = ModuleDeviceNode;
1219 }
1220
1221 /*
1222 * Generate filename without path (not needed by freeldr)
1223 */
1224
1225 FileNameWithoutPath = strrchr(FileName, '\\');
1226 if (FileNameWithoutPath == NULL)
1227 {
1228 FileNameWithoutPath = FileName;
1229 }
1230
1231 /*
1232 * Load the module
1233 */
1234
1235 RtlCreateUnicodeStringFromAsciiz(&DeviceNode->ServiceName,
1236 FileNameWithoutPath);
1237 Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName,
1238 &ModuleObject);
1239 if (!NT_SUCCESS(Status))
1240 {
1241 if (ModuleDeviceNode == NULL)
1242 IopFreeDeviceNode(DeviceNode);
1243 CPRINT("Driver load failed, status (%x)\n", Status);
1244 return Status;
1245 }
1246
1247 /* Load symbols */
1248 KDB_SYMBOLFILE_HOOK(FileName);
1249
1250 /*
1251 * Strip the file extension from ServiceName
1252 */
1253
1254 FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.');
1255 if (FileExtension != NULL)
1256 {
1257 DeviceNode->ServiceName.Length -= wcslen(FileExtension) * sizeof(WCHAR);
1258 FileExtension[0] = 0;
1259 }
1260
1261 /*
1262 * Initialize the driver
1263 */
1264
1265 Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
1266 &DeviceNode->ServiceName, FALSE, &DriverObject);
1267
1268 if (!NT_SUCCESS(Status))
1269 {
1270 if (ModuleDeviceNode == NULL)
1271 IopFreeDeviceNode(DeviceNode);
1272 CPRINT("Driver load failed, status (%x)\n", Status);
1273 return Status;
1274 }
1275
1276 Status = IopInitializeDevice(DeviceNode, DriverObject);
1277 if (NT_SUCCESS(Status))
1278 {
1279 Status = IopStartDevice(DeviceNode);
1280 }
1281
1282 return Status;
1283 }
1284
1285 /*
1286 * IopInitializeBootDrivers
1287 *
1288 * Initialize boot drivers and free memory for boot files.
1289 *
1290 * Parameters
1291 * None
1292 *
1293 * Return Value
1294 * None
1295 */
1296
1297 VOID FASTCALL
1298 IopInitializeBootDrivers(VOID)
1299 {
1300 ULONG BootDriverCount;
1301 ULONG ModuleStart;
1302 ULONG ModuleSize;
1303 ULONG ModuleLoaded;
1304 PCHAR ModuleName;
1305 PCHAR Extension;
1306 PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr;
1307 ULONG i;
1308 UNICODE_STRING DriverName;
1309 NTSTATUS Status;
1310
1311 DPRINT("IopInitializeBootDrivers()\n");
1312
1313 BootDriverCount = 0;
1314 for (i = 0; i < KeLoaderBlock.ModsCount; i++)
1315 {
1316 ModuleStart = KeLoaderModules[i].ModStart;
1317 ModuleSize = KeLoaderModules[i].ModEnd - ModuleStart;
1318 ModuleName = (PCHAR)KeLoaderModules[i].String;
1319 ModuleLoaded = KeLoaderModules[i].Reserved;
1320 Extension = strrchr(ModuleName, '.');
1321 if (Extension == NULL)
1322 Extension = "";
1323
1324 if (!_stricmp(Extension, ".sym") || !_stricmp(Extension, ".dll"))
1325 {
1326 /* Process symbols for *.exe and *.dll */
1327 KDB_SYMBOLFILE_HOOK(ModuleName);
1328
1329 /* Log *.exe and *.dll files */
1330 RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName);
1331 IopBootLog(&DriverName, TRUE);
1332 RtlFreeUnicodeString(&DriverName);
1333 }
1334 else if (!_stricmp(Extension, ".sys"))
1335 {
1336 /* Initialize and log boot start driver */
1337 if (!ModuleLoaded)
1338 {
1339 Status = IopInitializeBuiltinDriver(NULL,
1340 (PVOID)ModuleStart,
1341 ModuleName,
1342 ModuleSize);
1343 RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName);
1344 IopBootLog(&DriverName, NT_SUCCESS(Status) ? TRUE : FALSE);
1345 RtlFreeUnicodeString(&DriverName);
1346 }
1347 BootDriverCount++;
1348 }
1349 }
1350
1351 /*
1352 * Free memory for all boot files, except ntoskrnl.exe.
1353 */
1354 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
1355 {
1356 MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
1357 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
1358 }
1359
1360 KeLoaderBlock.ModsCount = 0;
1361
1362 if (BootDriverCount == 0)
1363 {
1364 DbgPrint("No boot drivers available.\n");
1365 KEBUGCHECK(0);
1366 }
1367 }
1368
1369 static INIT_FUNCTION NTSTATUS
1370 IopLoadDriver(PSERVICE Service)
1371 {
1372 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1373
1374 IopDisplayLoadingMessage(Service->ServiceName.Buffer, TRUE);
1375 Status = ZwLoadDriver(&Service->RegistryPath);
1376 IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE);
1377 if (!NT_SUCCESS(Status))
1378 {
1379 DPRINT("IopLoadDriver() failed (Status %lx)\n", Status);
1380 #if 0
1381 if (Service->ErrorControl == 1)
1382 {
1383 /* Log error */
1384 }
1385 else if (Service->ErrorControl == 2)
1386 {
1387 if (IsLastKnownGood == FALSE)
1388 {
1389 /* Boot last known good configuration */
1390 }
1391 }
1392 else if (Service->ErrorControl == 3)
1393 {
1394 if (IsLastKnownGood == FALSE)
1395 {
1396 /* Boot last known good configuration */
1397 }
1398 else
1399 {
1400 /* BSOD! */
1401 }
1402 }
1403 #endif
1404 }
1405 return Status;
1406 }
1407
1408
1409 /*
1410 * IopInitializeSystemDrivers
1411 *
1412 * Load drivers marked as system start.
1413 *
1414 * Parameters
1415 * None
1416 *
1417 * Return Value
1418 * None
1419 */
1420
1421 VOID FASTCALL
1422 IopInitializeSystemDrivers(VOID)
1423 {
1424 PLIST_ENTRY GroupEntry;
1425 PLIST_ENTRY ServiceEntry;
1426 PSERVICE_GROUP CurrentGroup;
1427 PSERVICE CurrentService;
1428 NTSTATUS Status;
1429 ULONG i;
1430
1431 DPRINT("IopInitializeSystemDrivers()\n");
1432
1433 GroupEntry = GroupListHead.Flink;
1434 while (GroupEntry != &GroupListHead)
1435 {
1436 CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
1437
1438 DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
1439
1440 /* Load all drivers with a valid tag */
1441 for (i = 0; i < CurrentGroup->TagCount; i++)
1442 {
1443 ServiceEntry = ServiceListHead.Flink;
1444 while (ServiceEntry != &ServiceListHead)
1445 {
1446 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1447
1448 if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
1449 &CurrentService->ServiceGroup, TRUE) == 0) &&
1450 (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/) &&
1451 (CurrentService->Tag == CurrentGroup->TagArray[i]))
1452 {
1453 DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath);
1454 Status = IopLoadDriver(CurrentService);
1455 }
1456 ServiceEntry = ServiceEntry->Flink;
1457 }
1458 }
1459
1460 /* Load all drivers without a tag or with an invalid tag */
1461 ServiceEntry = ServiceListHead.Flink;
1462 while (ServiceEntry != &ServiceListHead)
1463 {
1464 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
1465 if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
1466 &CurrentService->ServiceGroup, TRUE) == 0) &&
1467 (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))
1468 {
1469 for (i = 0; i < CurrentGroup->TagCount; i++)
1470 {
1471 if (CurrentGroup->TagArray[i] == CurrentService->Tag)
1472 {
1473 break;
1474 }
1475 }
1476 if (i >= CurrentGroup->TagCount)
1477 {
1478 DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath);
1479 Status = IopLoadDriver(CurrentService);
1480 }
1481 }
1482 ServiceEntry = ServiceEntry->Flink;
1483 }
1484
1485 GroupEntry = GroupEntry->Flink;
1486 }
1487
1488 DPRINT("IopInitializeSystemDrivers() done\n");
1489 }
1490
1491 /*
1492 * IopUnloadDriver
1493 *
1494 * Unloads a device driver.
1495 *
1496 * Parameters
1497 * DriverServiceName
1498 * Name of the service to unload (registry key).
1499 *
1500 * UnloadPnpDrivers
1501 * Whether to unload Plug & Plug or only legacy drivers. If this
1502 * parameter is set to FALSE, the routine will unload only legacy
1503 * drivers.
1504 *
1505 * Return Value
1506 * Status
1507 *
1508 * To do
1509 * Guard the whole function by SEH.
1510 */
1511
1512 NTSTATUS STDCALL
1513 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
1514 {
1515 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1516 UNICODE_STRING ImagePath;
1517 UNICODE_STRING ServiceName;
1518 UNICODE_STRING ObjectName;
1519 PDRIVER_OBJECT DriverObject;
1520 PMODULE_OBJECT ModuleObject;
1521 NTSTATUS Status;
1522 LPWSTR Start;
1523
1524 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers);
1525
1526 /*
1527 * Get the service name from the registry key name
1528 */
1529
1530 Start = wcsrchr(DriverServiceName->Buffer, L'\\');
1531 if (Start == NULL)
1532 Start = DriverServiceName->Buffer;
1533 else
1534 Start++;
1535
1536 RtlInitUnicodeString(&ServiceName, Start);
1537
1538 /*
1539 * Construct the driver object name
1540 */
1541
1542 ObjectName.Length = (wcslen(Start) + 8) * sizeof(WCHAR);
1543 ObjectName.MaximumLength = ObjectName.Length + sizeof(WCHAR);
1544 ObjectName.Buffer = ExAllocatePool(NonPagedPool, ObjectName.MaximumLength);
1545 wcscpy(ObjectName.Buffer, L"\\Driver\\");
1546 memcpy(ObjectName.Buffer + 8, Start, (ObjectName.Length - 8) * sizeof(WCHAR));
1547 ObjectName.Buffer[ObjectName.Length/sizeof(WCHAR)] = 0;
1548
1549 /*
1550 * Find the driver object
1551 */
1552
1553 Status = ObReferenceObjectByName(&ObjectName, 0, 0, 0, IoDriverObjectType,
1554 KernelMode, 0, (PVOID*)&DriverObject);
1555
1556 if (!NT_SUCCESS(Status))
1557 {
1558 DPRINT("Can't locate driver object for %wZ\n", ObjectName);
1559 return Status;
1560 }
1561
1562 /*
1563 * Free the buffer for driver object name
1564 */
1565
1566 ExFreePool(ObjectName.Buffer);
1567
1568 /*
1569 * Get path of service...
1570 */
1571
1572 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1573
1574 RtlInitUnicodeString(&ImagePath, NULL);
1575
1576 QueryTable[0].Name = L"ImagePath";
1577 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1578 QueryTable[0].EntryContext = &ImagePath;
1579
1580 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1581 DriverServiceName->Buffer, QueryTable, NULL, NULL);
1582
1583 if (!NT_SUCCESS(Status))
1584 {
1585 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1586 return Status;
1587 }
1588
1589 /*
1590 * Normalize the image path for all later processing.
1591 */
1592
1593 Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1594
1595 if (!NT_SUCCESS(Status))
1596 {
1597 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1598 return Status;
1599 }
1600
1601 /*
1602 * ... and check if it's loaded
1603 */
1604
1605 ModuleObject = LdrGetModuleObject(&ImagePath);
1606 if (ModuleObject == NULL)
1607 {
1608 return STATUS_UNSUCCESSFUL;
1609 }
1610
1611 /*
1612 * Free the service path
1613 */
1614
1615 ExFreePool(ImagePath.Buffer);
1616
1617 /*
1618 * Unload the module and release the references to the device object
1619 */
1620
1621 if (DriverObject->DriverUnload)
1622 (*DriverObject->DriverUnload)(DriverObject);
1623 ObDereferenceObject(DriverObject);
1624 ObDereferenceObject(DriverObject);
1625 LdrUnloadModule(ModuleObject);
1626
1627 return STATUS_SUCCESS;
1628 }
1629
1630 VOID FASTCALL
1631 IopMarkLastReinitializeDriver(VOID)
1632 {
1633 KIRQL Irql;
1634
1635 KeAcquireSpinLock(&DriverReinitListLock,
1636 &Irql);
1637
1638 if (IsListEmpty(&DriverReinitListHead))
1639 {
1640 DriverReinitTailEntry = NULL;
1641 }
1642 else
1643 {
1644 DriverReinitTailEntry = DriverReinitListHead.Blink;
1645 }
1646
1647 KeReleaseSpinLock(&DriverReinitListLock,
1648 Irql);
1649 }
1650
1651
1652 VOID FASTCALL
1653 IopReinitializeDrivers(VOID)
1654 {
1655 PDRIVER_REINIT_ITEM ReinitItem;
1656 PLIST_ENTRY Entry;
1657 KIRQL Irql;
1658
1659 KeAcquireSpinLock(&DriverReinitListLock,
1660 &Irql);
1661
1662 if (DriverReinitTailEntry == NULL)
1663 {
1664 KeReleaseSpinLock(&DriverReinitListLock,
1665 Irql);
1666 return;
1667 }
1668
1669 KeReleaseSpinLock(&DriverReinitListLock,
1670 Irql);
1671
1672 for (;;)
1673 {
1674 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
1675 &DriverReinitListLock);
1676 if (Entry == NULL)
1677 return;
1678
1679 ReinitItem = (PDRIVER_REINIT_ITEM)CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1680
1681 /* Increment reinitialization counter */
1682 ReinitItem->DriverObject->DriverExtension->Count++;
1683
1684 ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1685 ReinitItem->Context,
1686 ReinitItem->DriverObject->DriverExtension->Count);
1687
1688 ExFreePool(Entry);
1689
1690 if (Entry == DriverReinitTailEntry)
1691 return;
1692 }
1693 }
1694
1695 /* PUBLIC FUNCTIONS ***********************************************************/
1696
1697
1698 /*
1699 * @implemented
1700 */
1701 NTSTATUS
1702 STDCALL
1703 IoCreateDriver (
1704 IN PUNICODE_STRING DriverName, OPTIONAL
1705 IN PDRIVER_INITIALIZE InitializationFunction
1706 )
1707 {
1708 WCHAR NameBuffer[100];
1709 USHORT NameLength;
1710 UNICODE_STRING LocalDriverName; /* To reduce code if no name given */
1711 NTSTATUS Status;
1712 OBJECT_ATTRIBUTES ObjectAttributes;
1713 ULONG ObjectSize;
1714 PDRIVER_OBJECT DriverObject;
1715 UNICODE_STRING ServiceKeyName;
1716 HANDLE hDriver;
1717 ULONG i;
1718
1719 /* First, create a unique name for the driver if we don't have one */
1720 if (!DriverName) {
1721
1722 /* Create a random name and set up the string*/
1723 NameLength = swprintf(NameBuffer, L"\\Driver\\%08u", KeTickCount);
1724 LocalDriverName.Length = NameLength * sizeof(WCHAR);
1725 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1726 LocalDriverName.Buffer = NameBuffer;
1727
1728 } else {
1729
1730 /* So we can avoid another code path, use a local var */
1731 LocalDriverName = *DriverName;
1732 }
1733
1734 /* Initialize the Attributes */
1735 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(DRIVER_EXTENSION);
1736 InitializeObjectAttributes(&ObjectAttributes,
1737 &LocalDriverName,
1738 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
1739 NULL,
1740 NULL);
1741
1742 /* Create the Object */
1743 Status = ObCreateObject(KernelMode,
1744 IoDriverObjectType,
1745 &ObjectAttributes,
1746 KernelMode,
1747 NULL,
1748 ObjectSize,
1749 0,
1750 0,
1751 (PVOID*)&DriverObject);
1752
1753 /* Return on failure */
1754 if (!NT_SUCCESS(Status)) return Status;
1755
1756 /* Set up the Object */
1757 RtlZeroMemory(DriverObject, ObjectSize);
1758 DriverObject->Type = IO_TYPE_DRIVER;
1759 DriverObject->Size = sizeof(DRIVER_OBJECT);
1760 DriverObject->Flags = DRVO_BUILTIN_DRIVER;
1761 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
1762 DriverObject->DriverExtension->DriverObject = DriverObject;
1763 DriverObject->DriverInit = InitializationFunction;
1764
1765 /* Invalidate all Major Functions */
1766 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1767 {
1768 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1769 }
1770
1771 /* Set up the Service Key Name */
1772 ServiceKeyName.Buffer = ExAllocatePool(PagedPool, LocalDriverName.Length + sizeof(WCHAR));
1773 ServiceKeyName.Length = LocalDriverName.Length;
1774 ServiceKeyName.MaximumLength = LocalDriverName.MaximumLength;
1775 RtlMoveMemory(ServiceKeyName.Buffer, LocalDriverName.Buffer, LocalDriverName.Length);
1776 ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = L'\0';
1777 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
1778
1779 /* Also store it in the Driver Object. This is a bit of a hack. */
1780 RtlMoveMemory(&DriverObject->DriverName, &ServiceKeyName, sizeof(UNICODE_STRING));
1781
1782 /* Add the Object and get its handle */
1783 Status = ObInsertObject(DriverObject,
1784 NULL,
1785 FILE_READ_DATA,
1786 0,
1787 NULL,
1788 &hDriver);
1789
1790 /* Return on Failure */
1791 if (!NT_SUCCESS(Status)) return Status;
1792
1793 /* Now reference it */
1794 Status = ObReferenceObjectByHandle(hDriver,
1795 0,
1796 IoDriverObjectType,
1797 KernelMode,
1798 (PVOID*)&DriverObject,
1799 NULL);
1800 ZwClose(hDriver);
1801
1802 /* Finally, call its init function */
1803 Status = (*InitializationFunction)(DriverObject, NULL);
1804
1805 if (!NT_SUCCESS(Status)) {
1806 /* If it didn't work, then kill the object */
1807 ObMakeTemporaryObject(DriverObject);
1808 ObDereferenceObject(DriverObject);
1809 }
1810
1811 /* Return the Status */
1812 return Status;
1813 }
1814
1815 /*
1816 * @implemented
1817 */
1818 VOID
1819 STDCALL
1820 IoDeleteDriver (
1821 IN PDRIVER_OBJECT DriverObject
1822 )
1823 {
1824 /* Simply derefence the Object */
1825 ObDereferenceObject(DriverObject);
1826 }
1827
1828
1829 /*
1830 * NtLoadDriver
1831 *
1832 * Loads a device driver.
1833 *
1834 * Parameters
1835 * DriverServiceName
1836 * Name of the service to load (registry key).
1837 *
1838 * Return Value
1839 * Status
1840 *
1841 * Status
1842 * implemented
1843 */
1844
1845 NTSTATUS STDCALL
1846 NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
1847 {
1848 RTL_QUERY_REGISTRY_TABLE QueryTable[3];
1849 UNICODE_STRING ImagePath;
1850 UNICODE_STRING ServiceName;
1851 UNICODE_STRING CapturedDriverServiceName;
1852 KPROCESSOR_MODE PreviousMode;
1853 NTSTATUS Status;
1854 ULONG Type;
1855 PDEVICE_NODE DeviceNode;
1856 PMODULE_OBJECT ModuleObject;
1857 PDRIVER_OBJECT DriverObject;
1858 WCHAR *cur;
1859
1860 PAGED_CODE();
1861
1862 PreviousMode = KeGetPreviousMode();
1863
1864 /*
1865 * Check security privileges
1866 */
1867
1868 /* FIXME: Uncomment when privileges will be correctly implemented. */
1869 #if 0
1870 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
1871 {
1872 DPRINT("Privilege not held\n");
1873 return STATUS_PRIVILEGE_NOT_HELD;
1874 }
1875 #endif
1876
1877 Status = RtlCaptureUnicodeString(&CapturedDriverServiceName,
1878 PreviousMode,
1879 PagedPool,
1880 FALSE,
1881 DriverServiceName);
1882 if (!NT_SUCCESS(Status))
1883 {
1884 return Status;
1885 }
1886
1887 DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName);
1888
1889 RtlInitUnicodeString(&ImagePath, NULL);
1890
1891 /*
1892 * Get the service name from the registry key name.
1893 */
1894 ASSERT(CapturedDriverServiceName.Length >= sizeof(WCHAR));
1895
1896 ServiceName = CapturedDriverServiceName;
1897 cur = CapturedDriverServiceName.Buffer + (CapturedDriverServiceName.Length / sizeof(WCHAR)) - 1;
1898 while (CapturedDriverServiceName.Buffer != cur)
1899 {
1900 if(*cur == L'\\')
1901 {
1902 ServiceName.Buffer = cur + 1;
1903 ServiceName.Length = CapturedDriverServiceName.Length -
1904 (USHORT)((ULONG_PTR)ServiceName.Buffer -
1905 (ULONG_PTR)CapturedDriverServiceName.Buffer);
1906 break;
1907 }
1908 cur--;
1909 }
1910
1911 /*
1912 * Get service type.
1913 */
1914
1915 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
1916
1917 RtlInitUnicodeString(&ImagePath, NULL);
1918
1919 QueryTable[0].Name = L"Type";
1920 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
1921 QueryTable[0].EntryContext = &Type;
1922
1923 QueryTable[1].Name = L"ImagePath";
1924 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
1925 QueryTable[1].EntryContext = &ImagePath;
1926
1927 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1928 CapturedDriverServiceName.Buffer, QueryTable, NULL, NULL);
1929
1930 if (!NT_SUCCESS(Status))
1931 {
1932 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
1933 ExFreePool(ImagePath.Buffer);
1934 goto ReleaseCapturedString;
1935 }
1936
1937 /*
1938 * Normalize the image path for all later processing.
1939 */
1940
1941 Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1942
1943 if (!NT_SUCCESS(Status))
1944 {
1945 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1946 goto ReleaseCapturedString;
1947 }
1948
1949 DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
1950 DPRINT("Type: %lx\n", Type);
1951
1952 /*
1953 * See, if the driver module isn't already loaded
1954 */
1955
1956 ModuleObject = LdrGetModuleObject(&ImagePath);
1957 if (ModuleObject != NULL)
1958 {
1959 DPRINT("Image already loaded\n");
1960 Status = STATUS_IMAGE_ALREADY_LOADED;
1961 goto ReleaseCapturedString;
1962 }
1963
1964 /*
1965 * Create device node
1966 */
1967
1968 /* Use IopRootDeviceNode for now */
1969 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
1970
1971 if (!NT_SUCCESS(Status))
1972 {
1973 DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
1974 goto ReleaseCapturedString;
1975 }
1976
1977 /*
1978 * Load the driver module
1979 */
1980
1981 Status = LdrLoadModule(&ImagePath, &ModuleObject);
1982
1983 if (!NT_SUCCESS(Status))
1984 {
1985 DPRINT("LdrLoadModule() failed (Status %lx)\n", Status);
1986 IopFreeDeviceNode(DeviceNode);
1987 goto ReleaseCapturedString;
1988 }
1989
1990 /*
1991 * Set a service name for the device node
1992 */
1993
1994 RtlpCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer, NonPagedPool);
1995
1996 /*
1997 * Initialize the driver module
1998 */
1999
2000 Status = IopInitializeDriverModule(
2001 DeviceNode,
2002 ModuleObject,
2003 &DeviceNode->ServiceName,
2004 (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
2005 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
2006 &DriverObject);
2007
2008 if (!NT_SUCCESS(Status))
2009 {
2010 DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status);
2011 LdrUnloadModule(ModuleObject);
2012 IopFreeDeviceNode(DeviceNode);
2013 goto ReleaseCapturedString;
2014 }
2015
2016 IopInitializeDevice(DeviceNode, DriverObject);
2017 Status = IopStartDevice(DeviceNode);
2018
2019 ReleaseCapturedString:
2020 RtlReleaseCapturedUnicodeString(&CapturedDriverServiceName,
2021 PreviousMode,
2022 FALSE);
2023
2024 return Status;
2025 }
2026
2027 /*
2028 * NtUnloadDriver
2029 *
2030 * Unloads a legacy device driver.
2031 *
2032 * Parameters
2033 * DriverServiceName
2034 * Name of the service to unload (registry key).
2035 *
2036 * Return Value
2037 * Status
2038 *
2039 * Status
2040 * implemented
2041 */
2042
2043 NTSTATUS STDCALL
2044 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
2045 {
2046 return IopUnloadDriver(DriverServiceName, FALSE);
2047 }
2048
2049 /*
2050 * IoRegisterDriverReinitialization
2051 *
2052 * Status
2053 * @implemented
2054 */
2055
2056 VOID STDCALL
2057 IoRegisterDriverReinitialization(
2058 PDRIVER_OBJECT DriverObject,
2059 PDRIVER_REINITIALIZE ReinitRoutine,
2060 PVOID Context)
2061 {
2062 PDRIVER_REINIT_ITEM ReinitItem;
2063
2064 ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
2065 if (ReinitItem == NULL)
2066 return;
2067
2068 ReinitItem->DriverObject = DriverObject;
2069 ReinitItem->ReinitRoutine = ReinitRoutine;
2070 ReinitItem->Context = Context;
2071
2072 DriverObject->Flags |= DRVO_REINIT_REGISTERED;
2073
2074 ExInterlockedInsertTailList(
2075 &DriverReinitListHead,
2076 &ReinitItem->ItemEntry,
2077 &DriverReinitListLock);
2078 }
2079
2080 /*
2081 * @implemented
2082 */
2083 VOID
2084 STDCALL
2085 IoRegisterBootDriverReinitialization(
2086 IN PDRIVER_OBJECT DriverObject,
2087 IN PDRIVER_REINITIALIZE DriverReinitializationRoutine,
2088 IN PVOID Context
2089 )
2090 {
2091 PDRIVER_REINIT_ITEM ReinitItem;
2092
2093 ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
2094 if (ReinitItem == NULL)
2095 return;
2096
2097 ReinitItem->DriverObject = DriverObject;
2098 ReinitItem->ReinitRoutine = DriverReinitializationRoutine;
2099 ReinitItem->Context = Context;
2100
2101 DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED;
2102
2103 ExInterlockedInsertTailList(
2104 &DriverBootReinitListHead,
2105 &ReinitItem->ItemEntry,
2106 &DriverReinitListLock);
2107 }
2108
2109 /*
2110 * IoAllocateDriverObjectExtension
2111 *
2112 * Status
2113 * @implemented
2114 */
2115
2116 NTSTATUS STDCALL
2117 IoAllocateDriverObjectExtension(
2118 PDRIVER_OBJECT DriverObject,
2119 PVOID ClientIdentificationAddress,
2120 ULONG DriverObjectExtensionSize,
2121 PVOID *DriverObjectExtension)
2122 {
2123 KIRQL OldIrql;
2124 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions;
2125 PPRIVATE_DRIVER_EXTENSIONS NewDriverExtension;
2126
2127 NewDriverExtension = ExAllocatePoolWithTag(
2128 NonPagedPool,
2129 sizeof(PRIVATE_DRIVER_EXTENSIONS) - sizeof(CHAR) +
2130 DriverObjectExtensionSize,
2131 TAG_DRIVER_EXTENSION);
2132
2133 if (NewDriverExtension == NULL)
2134 {
2135 return STATUS_INSUFFICIENT_RESOURCES;
2136 }
2137
2138 OldIrql = KeRaiseIrqlToDpcLevel();
2139
2140 NewDriverExtension->Link = DriverObject->DriverSection;
2141 NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress;
2142
2143 for (DriverExtensions = DriverObject->DriverSection;
2144 DriverExtensions != NULL;
2145 DriverExtensions = DriverExtensions->Link)
2146 {
2147 if (DriverExtensions->ClientIdentificationAddress ==
2148 ClientIdentificationAddress)
2149 {
2150 KfLowerIrql(OldIrql);
2151 return STATUS_OBJECT_NAME_COLLISION;
2152 }
2153 }
2154
2155 DriverObject->DriverSection = NewDriverExtension;
2156
2157 KfLowerIrql(OldIrql);
2158
2159 *DriverObjectExtension = &NewDriverExtension->Extension;
2160
2161 return STATUS_SUCCESS;
2162 }
2163
2164 /*
2165 * IoGetDriverObjectExtension
2166 *
2167 * Status
2168 * @implemented
2169 */
2170
2171 PVOID STDCALL
2172 IoGetDriverObjectExtension(
2173 PDRIVER_OBJECT DriverObject,
2174 PVOID ClientIdentificationAddress)
2175 {
2176 KIRQL OldIrql;
2177 PPRIVATE_DRIVER_EXTENSIONS DriverExtensions;
2178
2179 OldIrql = KeRaiseIrqlToDpcLevel();
2180
2181 for (DriverExtensions = DriverObject->DriverSection;
2182 DriverExtensions != NULL &&
2183 DriverExtensions->ClientIdentificationAddress !=
2184 ClientIdentificationAddress;
2185 DriverExtensions = DriverExtensions->Link)
2186 ;
2187
2188 KfLowerIrql(OldIrql);
2189
2190 if (DriverExtensions == NULL)
2191 return NULL;
2192
2193 return &DriverExtensions->Extension;
2194 }
2195
2196 /* EOF */