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