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