ReactOS 0.4.17-dev-769-g1500a35
driver.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/driver.c
5 * PURPOSE: Driver Object Management
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Filip Navara (navaraf@reactos.org)
8 * Hervé Poussineau (hpoussin@reactos.org)
9 */
10
11/* INCLUDES *******************************************************************/
12
13#include <ntoskrnl.h>
14#define NDEBUG
15#include <debug.h>
16#include <mm/ARM3/miarm.h>
17
18/* GLOBALS ********************************************************************/
19
21
25
29
31 RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
32static const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
33
35
39
42
43/* TYPES *********************************************************************/
44
45// Parameters packet for Load/Unload work item's context
46typedef struct _LOAD_UNLOAD_PARAMS
47{
55
60
61/* PRIVATE FUNCTIONS **********************************************************/
62
67 PIRP Irp)
68{
69 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
70 Irp->IoStatus.Information = 0;
73}
74
75VOID
78{
79 PDRIVER_OBJECT DriverObject = ObjectBody;
80 PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension;
81 PAGED_CODE();
82
83 DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName);
84
85 /* There must be no device objects remaining at this point */
86 ASSERT(!DriverObject->DeviceObject);
87
88 /* Get the extension and loop them */
89 DriverExtension = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
90 while (DriverExtension)
91 {
92 /* Get the next one */
93 NextDriverExtension = DriverExtension->NextExtension;
95
96 /* Move on */
97 DriverExtension = NextDriverExtension;
98 }
99
100 /* Check if the driver image is still loaded */
101 if (DriverObject->DriverSection)
102 {
103 /* Unload it */
104 MmUnloadSystemImage(DriverObject->DriverSection);
105 }
106
107 /* Check if it has a name */
108 if (DriverObject->DriverName.Buffer)
109 {
110 /* Free it */
111 ExFreePool(DriverObject->DriverName.Buffer);
112 }
113
114 /* Check if it has a service key name */
115 if (DriverObject->DriverExtension->ServiceKeyName.Buffer)
116 {
117 /* Free it */
118 ExFreePool(DriverObject->DriverExtension->ServiceKeyName.Buffer);
119 }
120}
121
124 _In_ HANDLE ServiceHandle,
125 _Out_ PUNICODE_STRING DriverName,
127{
128 UNICODE_STRING driverName = {.Buffer = NULL}, serviceName;
131
132 PAGED_CODE();
133
134 /* 1. Check the "ObjectName" field in the driver's registry key (it has priority) */
135 status = IopGetRegistryValue(ServiceHandle, L"ObjectName", &kvInfo);
136 if (NT_SUCCESS(status))
137 {
138 /* We've got the ObjectName, use it as the driver name */
139 if ((kvInfo->Type != REG_SZ) ||
140 (kvInfo->DataLength < sizeof(UNICODE_NULL)) ||
142 ((kvInfo->DataLength % sizeof(WCHAR)) != 0))
143 {
144 DPRINT1("ObjectName invalid (Type = %lu, DataLength = %lu)\n",
145 kvInfo->Type,
146 kvInfo->DataLength);
147 ExFreePool(kvInfo);
149 }
150
151 driverName.Length = (USHORT)(kvInfo->DataLength - sizeof(UNICODE_NULL));
152 driverName.MaximumLength = kvInfo->DataLength;
154 if (!driverName.Buffer)
155 {
156 ExFreePool(kvInfo);
158 }
159
160 RtlMoveMemory(driverName.Buffer,
161 (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
162 driverName.Length);
163 driverName.Buffer[driverName.Length / sizeof(WCHAR)] = UNICODE_NULL;
164 ExFreePool(kvInfo);
165 }
166
167 /* Check whether we need to get ServiceName as well, either to construct
168 * the driver name (because we could not use "ObjectName"), or because
169 * it is requested by the caller. */
170 PKEY_BASIC_INFORMATION basicInfo = NULL;
171 if (!NT_SUCCESS(status) || ServiceName != NULL)
172 {
173 /* Retrieve the necessary buffer size */
174 ULONG infoLength;
175 status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength);
177 {
179 goto Cleanup;
180 }
181
182 /* Allocate the buffer and retrieve the data */
183 basicInfo = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO);
184 if (!basicInfo)
185 {
187 goto Cleanup;
188 }
189
190 status = ZwQueryKey(ServiceHandle, KeyBasicInformation, basicInfo, infoLength, &infoLength);
191 if (!NT_SUCCESS(status))
192 {
193 goto Cleanup;
194 }
195
196 serviceName.Length = basicInfo->NameLength;
197 serviceName.MaximumLength = basicInfo->NameLength;
198 serviceName.Buffer = basicInfo->Name;
199 }
200
201 /* 2. There is no "ObjectName" - construct it ourselves. Depending on the driver type,
202 * it will be either "\Driver<ServiceName>" or "\FileSystem<ServiceName>" */
203 if (driverName.Buffer == NULL)
204 {
205 ASSERT(basicInfo); // Container for serviceName
206
207 /* Retrieve the driver type */
208 ULONG driverType;
209 status = IopGetRegistryValue(ServiceHandle, L"Type", &kvInfo);
210 if (!NT_SUCCESS(status))
211 {
212 goto Cleanup;
213 }
214 if (kvInfo->Type != REG_DWORD || kvInfo->DataLength != sizeof(ULONG))
215 {
216 ExFreePool(kvInfo);
218 goto Cleanup;
219 }
220
221 RtlMoveMemory(&driverType,
222 (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
223 sizeof(ULONG));
224 ExFreePool(kvInfo);
225
226 /* Compute the necessary driver name string size */
227 if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER)
228 driverName.MaximumLength = sizeof(FILESYSTEM_ROOT_NAME);
229 else
230 driverName.MaximumLength = sizeof(DRIVER_ROOT_NAME);
231
232 driverName.MaximumLength += serviceName.Length;
233 driverName.Length = 0;
234
235 /* Allocate and build it */
237 if (!driverName.Buffer)
238 {
240 goto Cleanup;
241 }
242
243 if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER)
245 else
247
249 }
250
251 if (ServiceName != NULL)
252 {
253 ASSERT(basicInfo); // Container for serviceName
254
255 /* Allocate a copy for the caller */
257 if (!buf)
258 {
260 goto Cleanup;
261 }
262 RtlMoveMemory(buf, serviceName.Buffer, serviceName.Length);
263 ServiceName->MaximumLength = serviceName.Length;
264 ServiceName->Length = serviceName.Length;
265 ServiceName->Buffer = buf;
266 }
267
268 *DriverName = driverName;
270
271Cleanup:
272 if (basicInfo)
273 ExFreePoolWithTag(basicInfo, TAG_IO);
274
275 if (!NT_SUCCESS(status) && driverName.Buffer)
276 ExFreePoolWithTag(driverName.Buffer, TAG_IO);
277
278 return status;
279}
280
285static BOOLEAN
287 _In_ PCUNICODE_STRING String1,
290{
291 PWCHAR pc1, pc2;
292 ULONG NumChars;
293
294 if (String2->Length < String1->Length)
295 return FALSE;
296
297 NumChars = String1->Length / sizeof(WCHAR);
298 pc1 = String1->Buffer;
299 pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - NumChars];
300
301 if (pc1 && pc2)
302 {
303 if (CaseInSensitive)
304 {
305 while (NumChars--)
306 {
307 if (RtlUpcaseUnicodeChar(*pc1++) !=
309 {
310 return FALSE;
311 }
312 }
313 }
314 else
315 {
316 while (NumChars--)
317 {
318 if (*pc1++ != *pc2++)
319 return FALSE;
320 }
321 }
322
323 return TRUE;
324 }
325
326 return FALSE;
327}
328
332static VOID
336{
337 extern BOOLEAN SosEnabled; // See ex/init.c
338 static const UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS");
339 CHAR TextBuffer[256];
340
341 if (!SosEnabled) return;
342 if (!KeLoaderBlock) return;
344 "%s%sSystem32\\Drivers\\%wZ%s\r\n",
349 ? "" : ".SYS");
351}
352
353/*
354 * IopNormalizeImagePath
355 *
356 * Normalize an image path to contain complete path.
357 *
358 * Parameters
359 * ImagePath
360 * The input path and on exit the result path. ImagePath.Buffer
361 * must be allocated by ExAllocatePool on input. Caller is responsible
362 * for freeing the buffer when it's no longer needed.
363 *
364 * ServiceName
365 * Name of the service that ImagePath belongs to.
366 *
367 * Return Value
368 * Status
369 *
370 * Remarks
371 * The input image path isn't freed on error.
372 */
376 _Inout_ _When_(return>=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem)))
377 PUNICODE_STRING ImagePath,
379{
380 UNICODE_STRING SystemRootString = RTL_CONSTANT_STRING(L"\\SystemRoot\\");
381 UNICODE_STRING DriversPathString = RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\drivers\\");
382 UNICODE_STRING DotSysString = RTL_CONSTANT_STRING(L".sys");
383 UNICODE_STRING InputImagePath;
384
385 DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
386
387 InputImagePath = *ImagePath;
388 if (InputImagePath.Length == 0)
389 {
390 ImagePath->Length = 0;
391 ImagePath->MaximumLength = DriversPathString.Length +
392 ServiceName->Length +
393 DotSysString.Length +
394 sizeof(UNICODE_NULL);
395 ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
396 ImagePath->MaximumLength,
397 TAG_IO);
398 if (ImagePath->Buffer == NULL)
399 return STATUS_NO_MEMORY;
400
401 RtlCopyUnicodeString(ImagePath, &DriversPathString);
403 RtlAppendUnicodeStringToString(ImagePath, &DotSysString);
404 }
405 else if (InputImagePath.Buffer[0] != L'\\')
406 {
407 ImagePath->Length = 0;
408 ImagePath->MaximumLength = SystemRootString.Length +
409 InputImagePath.Length +
410 sizeof(UNICODE_NULL);
411 ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
412 ImagePath->MaximumLength,
413 TAG_IO);
414 if (ImagePath->Buffer == NULL)
415 return STATUS_NO_MEMORY;
416
417 RtlCopyUnicodeString(ImagePath, &SystemRootString);
418 RtlAppendUnicodeStringToString(ImagePath, &InputImagePath);
419
420 /* Free caller's string */
422 }
423
424 DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
425
426 return STATUS_SUCCESS;
427}
428
450 _In_ PLDR_DATA_TABLE_ENTRY ModuleObject,
451 _In_ HANDLE ServiceHandle,
452 _Out_ PDRIVER_OBJECT *OutDriverObject,
453 _Out_ NTSTATUS *DriverEntryStatus)
454{
457
458 PAGED_CODE();
459
460 Status = IopGetDriverNames(ServiceHandle, &DriverName, &ServiceName);
461 if (!NT_SUCCESS(Status))
462 {
463 MmUnloadSystemImage(ModuleObject);
464 return Status;
465 }
466
467 DPRINT("Driver name: '%wZ'\n", &DriverName);
468
469 /*
470 * Retrieve the driver's PE image NT header and perform some sanity checks.
471 * NOTE: We suppose that since the driver has been successfully loaded,
472 * its NT and optional headers are all valid and have expected sizes.
473 */
474 PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader(ModuleObject->DllBase);
475 ASSERT(NtHeaders);
476 // NOTE: ModuleObject->SizeOfImage is actually (number of PTEs)*PAGE_SIZE.
477 ASSERT(ModuleObject->SizeOfImage == ROUND_TO_PAGES(NtHeaders->OptionalHeader.SizeOfImage));
478 ASSERT(ModuleObject->EntryPoint == RVA(ModuleObject->DllBase, NtHeaders->OptionalHeader.AddressOfEntryPoint));
479
480 /* Obtain the registry path for the DriverInit routine */
481 PKEY_NAME_INFORMATION nameInfo;
482 ULONG infoLength;
483 Status = ZwQueryKey(ServiceHandle, KeyNameInformation, NULL, 0, &infoLength);
485 {
486 nameInfo = ExAllocatePoolWithTag(NonPagedPool, infoLength, TAG_IO);
487 if (nameInfo)
488 {
489 Status = ZwQueryKey(ServiceHandle,
491 nameInfo,
492 infoLength,
493 &infoLength);
494 if (NT_SUCCESS(Status))
495 {
496 RegistryPath.Length = nameInfo->NameLength;
497 RegistryPath.MaximumLength = nameInfo->NameLength;
498 RegistryPath.Buffer = nameInfo->Name;
499 }
500 else
501 {
502 ExFreePoolWithTag(nameInfo, TAG_IO);
503 }
504 }
505 else
506 {
508 }
509 }
510 else
511 {
513 }
514
515 if (!NT_SUCCESS(Status))
516 {
518 RtlFreeUnicodeString(&DriverName);
519 MmUnloadSystemImage(ModuleObject);
520 return Status;
521 }
522
523 /* Create the driver object */
526 &DriverName,
528 NULL,
529 NULL);
530
531 /* Honor the internal I/O System case (in)sensitivity */
533
534 PDRIVER_OBJECT driverObject;
535 ULONG ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
540 NULL,
541 ObjectSize,
542 0,
543 0,
544 (PVOID*)&driverObject);
545 if (!NT_SUCCESS(Status))
546 {
547 ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
549 RtlFreeUnicodeString(&DriverName);
550 MmUnloadSystemImage(ModuleObject);
551 DPRINT1("Error while creating driver object \"%wZ\" status %x\n", &DriverName, Status);
552 return Status;
553 }
554
555 DPRINT("Created driver object 0x%p for \"%wZ\"\n", driverObject, &DriverName);
556
557 RtlZeroMemory(driverObject, ObjectSize);
558 driverObject->Type = IO_TYPE_DRIVER;
559 driverObject->Size = sizeof(DRIVER_OBJECT);
560
561 /* Set the legacy flag if this is not a WDM driver */
563 driverObject->Flags |= DRVO_LEGACY_DRIVER;
564
565 driverObject->DriverSection = ModuleObject;
566 driverObject->DriverStart = ModuleObject->DllBase;
567 driverObject->DriverSize = ModuleObject->SizeOfImage;
568 driverObject->DriverInit = ModuleObject->EntryPoint;
570 driverObject->DriverExtension = (PDRIVER_EXTENSION)(driverObject + 1);
571 driverObject->DriverExtension->DriverObject = driverObject;
572
573 /* Loop all Major Functions */
574 for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
575 {
576 /* Invalidate each function */
577 driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
578 }
579
580 /* Add the Object and get its handle */
582 Status = ObInsertObject(driverObject, NULL, FILE_READ_DATA, 0, NULL, &hDriver);
583 if (!NT_SUCCESS(Status))
584 {
585 ExFreePoolWithTag(nameInfo, TAG_IO);
587 RtlFreeUnicodeString(&DriverName);
588 return Status;
589 }
590
591 /* Now reference it */
593 0,
596 (PVOID*)&driverObject,
597 NULL);
598
599 /* Close the extra handle */
601
602 if (!NT_SUCCESS(Status))
603 {
604 ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
606 RtlFreeUnicodeString(&DriverName);
607 return Status;
608 }
609
610 /* Set up the service key name buffer */
611 UNICODE_STRING serviceKeyName;
612 serviceKeyName.Length = 0;
613 // NULL-terminate for Windows compatibility
614 serviceKeyName.MaximumLength = ServiceName.MaximumLength + sizeof(UNICODE_NULL);
616 serviceKeyName.MaximumLength,
617 TAG_IO);
618 if (!serviceKeyName.Buffer)
619 {
620 ObMakeTemporaryObject(driverObject);
621 ObDereferenceObject(driverObject);
622 ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
624 RtlFreeUnicodeString(&DriverName);
626 }
627
628 /* Copy the name and set it in the driver extension */
629 RtlCopyUnicodeString(&serviceKeyName, &ServiceName);
631 driverObject->DriverExtension->ServiceKeyName = serviceKeyName;
632
633 /* Make a copy of the driver name to store in the driver object */
634 UNICODE_STRING driverNamePaged;
635 driverNamePaged.Length = 0;
636 // NULL-terminate for Windows compatibility
637 driverNamePaged.MaximumLength = DriverName.MaximumLength + sizeof(UNICODE_NULL);
638 driverNamePaged.Buffer = ExAllocatePoolWithTag(PagedPool,
639 driverNamePaged.MaximumLength,
640 TAG_IO);
641 if (!driverNamePaged.Buffer)
642 {
643 ObMakeTemporaryObject(driverObject);
644 ObDereferenceObject(driverObject);
645 ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
646 RtlFreeUnicodeString(&DriverName);
648 }
649
650 RtlCopyUnicodeString(&driverNamePaged, &DriverName);
651 driverObject->DriverName = driverNamePaged;
652
653 /* Finally, call its init function */
654 Status = driverObject->DriverInit(driverObject, &RegistryPath);
655 *DriverEntryStatus = Status;
656 if (!NT_SUCCESS(Status))
657 {
658 DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", &DriverName, Status);
659 // return a special status value in case of failure
661 }
662
663 /* HACK: We're going to say if we don't have any DOs from DriverEntry, then we're not legacy.
664 * Other parts of the I/O manager depend on this behavior */
665 if (!driverObject->DeviceObject)
666 {
667 driverObject->Flags &= ~DRVO_LEGACY_DRIVER;
668 }
669
670 /* Windows does this fixup, keep it for compatibility */
671 for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
672 {
673 /*
674 * Make sure the driver didn't set any dispatch entry point to NULL!
675 * Doing so is illegal; drivers shouldn't touch entry points they
676 * do not implement.
677 */
678
679 /* Check if it did so anyway */
680 if (!driverObject->MajorFunction[i])
681 {
682 /* Print a warning in the debug log */
683 DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n",
684 &driverObject->DriverName, i);
685
686 /* Fix it up */
687 driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
688 }
689 }
690
691 // TODO: for legacy drivers, unload the driver if it didn't create any DO
692
693 ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
694 RtlFreeUnicodeString(&DriverName);
695
696 if (!NT_SUCCESS(Status))
697 {
698 // if the driver entry has been failed, clear the object
699 ObMakeTemporaryObject(driverObject);
700 ObDereferenceObject(driverObject);
701 return Status;
702 }
703
704 *OutDriverObject = driverObject;
705
707
708 /* Set the driver as initialized */
709 IopReadyDeviceObjects(driverObject);
710
712
713 return STATUS_SUCCESS;
714}
715
717NTAPI
719 IN PUNICODE_STRING ImageFileDirectory,
720 IN PUNICODE_STRING NamePrefix OPTIONAL,
721 OUT PCHAR *MissingApi,
722 OUT PWCHAR *MissingDriver,
723 OUT PLOAD_IMPORTS *LoadImports);
724
725//
726// Used for images already loaded (boot drivers)
727//
728CODE_SEG("INIT")
730NTAPI
733 PLDR_DATA_TABLE_ENTRY *ModuleObject)
734{
736 UNICODE_STRING BaseName, BaseDirectory;
737 PLOAD_IMPORTS LoadedImports = MM_SYSLDR_NO_IMPORTS;
738 PCHAR MissingApiName, Buffer;
739 PWCHAR MissingDriverName;
740 PVOID DriverBase = LdrEntry->DllBase;
741
742 /* Allocate a buffer we'll use for names */
746 if (!Buffer)
747 {
748 /* Fail */
750 }
751
752 /* Check for a separator */
753 if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
754 {
755 PWCHAR p;
756 ULONG BaseLength;
757
758 /* Loop the path until we get to the base name */
759 p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
760 while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
761
762 /* Get the length */
763 BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
764 BaseLength *= sizeof(WCHAR);
765
766 /* Setup the string */
767 BaseName.Length = (USHORT)BaseLength;
768 BaseName.Buffer = p;
769 }
770 else
771 {
772 /* Otherwise, we already have a base name */
773 BaseName.Length = FileName->Length;
774 BaseName.Buffer = FileName->Buffer;
775 }
776
777 /* Setup the maximum length */
778 BaseName.MaximumLength = BaseName.Length;
779
780 /* Now compute the base directory */
781 BaseDirectory = *FileName;
782 BaseDirectory.Length -= BaseName.Length;
783 BaseDirectory.MaximumLength = BaseDirectory.Length;
784
785 /* Resolve imports */
786 MissingApiName = Buffer;
787 Status = MiResolveImageReferences(DriverBase,
788 &BaseDirectory,
789 NULL,
790 &MissingApiName,
791 &MissingDriverName,
792 &LoadedImports);
793
794 /* Free the temporary buffer */
796
797 /* Check the result of the imports resolution */
798 if (!NT_SUCCESS(Status)) return Status;
799
800 /* Return */
801 *ModuleObject = LdrEntry;
802 return STATUS_SUCCESS;
803}
804
807
808/*
809 * IopInitializeBuiltinDriver
810 *
811 * Initialize a driver that is already loaded in memory.
812 */
813CODE_SEG("INIT")
814static
817{
820 PWCHAR Buffer, FileNameWithoutPath;
821 PWSTR FileExtension;
822 PUNICODE_STRING ModuleName = &BootLdrEntry->BaseDllName;
823 PLDR_DATA_TABLE_ENTRY LdrEntry;
824 PLIST_ENTRY NextEntry;
827
828 /*
829 * Display 'Loading XXX...' message
830 */
833
835 ModuleName->Length + sizeof(UNICODE_NULL),
836 TAG_IO);
837 if (Buffer == NULL)
838 {
839 return FALSE;
840 }
841
844
845 /*
846 * Generate filename without path (not needed by freeldr)
847 */
848 FileNameWithoutPath = wcsrchr(Buffer, L'\\');
849 if (FileNameWithoutPath == NULL)
850 {
851 FileNameWithoutPath = Buffer;
852 }
853 else
854 {
855 FileNameWithoutPath++;
856 }
857
858 /*
859 * Strip the file extension from ServiceName
860 */
861 Success = RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath);
863 if (!Success)
864 {
865 return FALSE;
866 }
867
868 FileExtension = wcsrchr(ServiceName.Buffer, L'.');
869 if (FileExtension != NULL)
870 {
871 ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR);
872 FileExtension[0] = UNICODE_NULL;
873 }
874
876
877 // Make the registry path for the driver
878 RegistryPath.Length = 0;
879 RegistryPath.MaximumLength = sizeof(ServicesKeyName) + ServiceName.Length;
881 if (RegistryPath.Buffer == NULL)
882 {
883 return FALSE;
884 }
888
889 HANDLE serviceHandle;
892 if (!NT_SUCCESS(Status))
893 {
894 return FALSE;
895 }
896
897 /* Lookup the new Ldr entry in PsLoadedModuleList */
898 for (NextEntry = PsLoadedModuleList.Flink;
899 NextEntry != &PsLoadedModuleList;
900 NextEntry = NextEntry->Flink)
901 {
902 LdrEntry = CONTAINING_RECORD(NextEntry,
904 InLoadOrderLinks);
906 {
907 break;
908 }
909 }
910 ASSERT(NextEntry != &PsLoadedModuleList);
911
912 /*
913 * Initialize the driver
914 */
915 NTSTATUS driverEntryStatus;
917 serviceHandle,
919 &driverEntryStatus);
920
921 if (!NT_SUCCESS(Status))
922 {
923 DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status);
924 return FALSE;
925 }
926
927 // The driver has been loaded, now check if where are any PDOs
928 // for that driver, and queue AddDevice call for them.
929 // The check is possible because HKLM/SYSTEM/CCS/Services/<ServiceName>/Enum directory
930 // is populated upon a new device arrival based on a (critical) device database
931
932 // Legacy drivers may add devices inside DriverEntry.
933 // We're lazy and always assume that they are doing so
934 BOOLEAN deviceAdded = !!(DriverObject->Flags & DRVO_LEGACY_DRIVER);
935
936 HANDLE enumServiceHandle;
937 UNICODE_STRING enumName = RTL_CONSTANT_STRING(L"Enum");
938
939 Status = IopOpenRegistryKeyEx(&enumServiceHandle, serviceHandle, &enumName, KEY_READ);
940 ZwClose(serviceHandle);
941
942 if (NT_SUCCESS(Status))
943 {
944 ULONG instanceCount = 0;
946 Status = IopGetRegistryValue(enumServiceHandle, L"Count", &kvInfo);
947 if (!NT_SUCCESS(Status))
948 {
949 goto Cleanup;
950 }
951 if (kvInfo->Type != REG_DWORD || kvInfo->DataLength != sizeof(ULONG))
952 {
953 ExFreePool(kvInfo);
954 goto Cleanup;
955 }
956
957 RtlMoveMemory(&instanceCount,
958 (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
959 sizeof(ULONG));
960 ExFreePool(kvInfo);
961
962 DPRINT("Processing %u instances for %wZ module\n", instanceCount, ModuleName);
963
964 for (ULONG i = 0; i < instanceCount; i++)
965 {
966 WCHAR num[11];
967 UNICODE_STRING instancePath;
968 RtlStringCbPrintfW(num, sizeof(num), L"%u", i);
969
970 Status = IopGetRegistryValue(enumServiceHandle, num, &kvInfo);
971 if (!NT_SUCCESS(Status))
972 {
973 continue;
974 }
975 if ((kvInfo->Type != REG_SZ) ||
976 (kvInfo->DataLength < sizeof(UNICODE_NULL)) ||
978 ((kvInfo->DataLength % sizeof(WCHAR)) != 0))
979 {
980 DPRINT1("ObjectName invalid (Type = %lu, DataLength = %lu)\n",
981 kvInfo->Type,
982 kvInfo->DataLength);
983 ExFreePool(kvInfo);
984 continue;
985 }
986
987 instancePath.Length = (USHORT)(kvInfo->DataLength - sizeof(UNICODE_NULL));
988 instancePath.MaximumLength = kvInfo->DataLength;
990 instancePath.MaximumLength,
991 TAG_IO);
992 if (instancePath.Buffer)
993 {
994 RtlMoveMemory(instancePath.Buffer,
995 (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
996 instancePath.Length);
997 instancePath.Buffer[instancePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
998
1000 if (pdo != NULL)
1001 {
1004 deviceAdded = TRUE;
1005 }
1006 else
1007 {
1008 DPRINT1("No device node found matching instance path '%wZ'\n", &instancePath);
1009 }
1010 }
1011
1012 ExFreePool(kvInfo);
1013 }
1014
1015 ZwClose(enumServiceHandle);
1016 }
1017Cleanup:
1018 /* Remove extra reference from IopInitializeDriverModule */
1020
1021 return deviceAdded;
1022}
1023
1024/*
1025 * IopInitializeBootDrivers
1026 *
1027 * Initialize boot drivers and free memory for boot files.
1028 *
1029 * Parameters
1030 * None
1031 *
1032 * Return Value
1033 * None
1034 */
1035CODE_SEG("INIT")
1036VOID
1039{
1040 PLIST_ENTRY ListHead, NextEntry, NextEntry2;
1041 PLDR_DATA_TABLE_ENTRY LdrEntry;
1043 UNICODE_STRING DriverName;
1044 ULONG i, Index;
1045 PDRIVER_INFORMATION DriverInfo, DriverInfoTag;
1047 PBOOT_DRIVER_LIST_ENTRY BootEntry;
1048 DPRINT("IopInitializeBootDrivers()\n");
1049
1050 /* Create the RAW FS built-in driver */
1051 RtlInitUnicodeString(&DriverName, L"\\FileSystem\\RAW");
1052
1053 Status = IoCreateDriver(&DriverName, RawFsDriverEntry);
1054 if (!NT_SUCCESS(Status))
1055 {
1056 /* Fail */
1057 return;
1058 }
1059
1060 /* Get highest group order index */
1062 if (IopGroupIndex == 0xFFFF)
1063 {
1065 }
1066
1067 /* Allocate the group table */
1069 IopGroupIndex * sizeof(LIST_ENTRY),
1070 TAG_IO);
1071 if (IopGroupTable == NULL)
1072 {
1074 }
1075
1076 /* Initialize the group table lists */
1077 for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]);
1078
1079 /* Loop the boot modules */
1080 ListHead = &KeLoaderBlock->LoadOrderListHead;
1081 for (NextEntry = ListHead->Flink;
1082 NextEntry != ListHead;
1083 NextEntry = NextEntry->Flink)
1084 {
1085 /* Get the entry */
1086 LdrEntry = CONTAINING_RECORD(NextEntry,
1088 InLoadOrderLinks);
1089
1090 /* Check if the DLL needs to be initialized */
1091 if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
1092 {
1093 /* Call its entrypoint */
1094 MmCallDllInitialize(LdrEntry, NULL);
1095 }
1096 }
1097
1098 /* Loop the boot drivers */
1099 ListHead = &KeLoaderBlock->BootDriverListHead;
1100 for (NextEntry = ListHead->Flink;
1101 NextEntry != ListHead;
1102 NextEntry = NextEntry->Flink)
1103 {
1104 /* Get the entry */
1105 BootEntry = CONTAINING_RECORD(NextEntry,
1107 Link);
1108
1109 // FIXME: TODO: This LdrEntry is to be used in a special handling
1110 // for SETUPLDR (a similar procedure is done on Windows), where
1111 // the loader would, under certain conditions, be loaded in the
1112 // SETUPLDR-specific code block below...
1113#if 0
1114 /* Get the driver loader entry */
1115 LdrEntry = BootEntry->LdrEntry;
1116#endif
1117
1118 /* Allocate our internal accounting structure */
1120 sizeof(DRIVER_INFORMATION),
1121 TAG_IO);
1122 if (DriverInfo)
1123 {
1124 /* Zero it and initialize it */
1127 DriverInfo->DataTableEntry = BootEntry;
1128
1129 /* Open the registry key */
1131 NULL,
1132 &BootEntry->RegistryPath,
1133 KEY_READ);
1134 DPRINT("IopOpenRegistryKeyEx(%wZ) returned 0x%08lx\n", &BootEntry->RegistryPath, Status);
1135#if 0
1136 if (NT_SUCCESS(Status))
1137#else // Hack still needed...
1138 if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */
1139 ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment!
1140#endif
1141 {
1142 /* Save the handle */
1144
1145 /* Get the group oder index */
1147
1148 /* Get the tag position */
1150
1151 /* Insert it into the list, at the right place */
1153 NextEntry2 = IopGroupTable[Index].Flink;
1154 while (NextEntry2 != &IopGroupTable[Index])
1155 {
1156 /* Get the driver info */
1157 DriverInfoTag = CONTAINING_RECORD(NextEntry2,
1159 Link);
1160
1161 /* Check if we found the right tag position */
1162 if (DriverInfoTag->TagPosition > DriverInfo->TagPosition)
1163 {
1164 /* We're done */
1165 break;
1166 }
1167
1168 /* Next entry */
1169 NextEntry2 = NextEntry2->Flink;
1170 }
1171
1172 /* Insert us right before the next entry */
1173 NextEntry2 = NextEntry2->Blink;
1174 InsertHeadList(NextEntry2, &DriverInfo->Link);
1175 }
1176 }
1177 }
1178
1179 /* Loop each group index */
1180 for (i = 0; i < IopGroupIndex; i++)
1181 {
1182 /* Loop each group table */
1183 for (NextEntry = IopGroupTable[i].Flink;
1184 NextEntry != &IopGroupTable[i];
1185 NextEntry = NextEntry->Flink)
1186 {
1187 /* Get the entry */
1188 DriverInfo = CONTAINING_RECORD(NextEntry,
1190 Link);
1191
1192 /* Get the driver loader entry */
1193 LdrEntry = DriverInfo->DataTableEntry->LdrEntry;
1194
1195 /* Initialize it */
1196 if (IopInitializeBuiltinDriver(LdrEntry))
1197 {
1198 // it does not make sense to enumerate the tree if there are no new devices added
1201 NULL,
1202 NULL);
1203 }
1204 }
1205 }
1206
1207 /* HAL Root Bus is being initialized before loading the boot drivers so this may cause issues
1208 * when some devices are not being initialized with their drivers. This flag is used to delay
1209 * all actions with devices (except PnP root device) until boot drivers are loaded.
1210 * See PiQueueDeviceAction function
1211 */
1213
1214 DbgPrint("BOOT DRIVERS LOADED\n");
1215
1218 NULL,
1219 NULL);
1220}
1221
1222CODE_SEG("INIT")
1223VOID
1226{
1227 PUNICODE_STRING *DriverList, *SavedList;
1228
1230
1231 /* HACK: No system drivers on the BootCD */
1232 if (KeLoaderBlock->SetupLdrBlock) return;
1233
1234 /* Get the driver list */
1235 SavedList = DriverList = CmGetSystemDriverList();
1236 ASSERT(DriverList);
1237
1238 /* Loop it */
1239 while (*DriverList)
1240 {
1241 /* Load the driver */
1242 ZwLoadDriver(*DriverList);
1243
1244 /* Free the entry */
1245 RtlFreeUnicodeString(*DriverList);
1246 ExFreePool(*DriverList);
1247
1248 /* Next entry */
1250 DriverList++;
1251 }
1252
1253 /* Free the list */
1254 ExFreePool(SavedList);
1255
1258 NULL,
1259 NULL);
1260}
1261
1262/*
1263 * IopUnloadDriver
1264 *
1265 * Unloads a device driver.
1266 *
1267 * Parameters
1268 * DriverServiceName
1269 * Name of the service to unload (registry key).
1270 *
1271 * UnloadPnpDrivers
1272 * Whether to unload Plug & Plug or only legacy drivers. If this
1273 * parameter is set to FALSE, the routine will unload only legacy
1274 * drivers.
1275 *
1276 * Return Value
1277 * Status
1278 *
1279 * To do
1280 * Guard the whole function by SEH.
1281 */
1282
1284IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
1285{
1286 UNICODE_STRING Backslash = RTL_CONSTANT_STRING(L"\\");
1288 UNICODE_STRING ImagePath;
1293 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
1295 USHORT LastBackslash;
1296 BOOLEAN SafeToUnload = TRUE;
1298 UNICODE_STRING CapturedServiceName;
1299
1300 PAGED_CODE();
1301
1303
1304 /* Need the appropriate priviliege */
1306 {
1307 DPRINT1("No unload privilege!\n");
1309 }
1310
1311 /* Capture the service name */
1312 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
1314 DriverServiceName);
1315 if (!NT_SUCCESS(Status))
1316 {
1317 return Status;
1318 }
1319
1320 DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers);
1321
1322 /* We need a service name */
1323 if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL)
1324 {
1325 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1327 }
1328
1329 /*
1330 * Get the service name from the registry key name
1331 */
1333 &CapturedServiceName,
1334 &Backslash,
1335 &LastBackslash);
1336 if (NT_SUCCESS(Status))
1337 {
1338 NT_ASSERT(CapturedServiceName.Length >= LastBackslash + sizeof(WCHAR));
1339 ServiceName.Buffer = &CapturedServiceName.Buffer[LastBackslash / sizeof(WCHAR) + 1];
1340 ServiceName.Length = CapturedServiceName.Length - LastBackslash - sizeof(WCHAR);
1341 ServiceName.MaximumLength = CapturedServiceName.MaximumLength - LastBackslash - sizeof(WCHAR);
1342 }
1343 else
1344 {
1345 ServiceName = CapturedServiceName;
1346 }
1347
1348 /*
1349 * Construct the driver object name
1350 */
1351 Status = RtlUShortAdd(sizeof(DRIVER_ROOT_NAME),
1352 ServiceName.Length,
1353 &ObjectName.MaximumLength);
1354 if (!NT_SUCCESS(Status))
1355 {
1356 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1357 return Status;
1358 }
1359 ObjectName.Length = 0;
1361 ObjectName.MaximumLength,
1362 TAG_IO);
1363 if (!ObjectName.Buffer)
1364 {
1365 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1367 }
1370
1371 /*
1372 * Find the driver object
1373 */
1375 0,
1376 0,
1377 0,
1379 KernelMode,
1380 0,
1381 (PVOID*)&DriverObject);
1382
1383 if (!NT_SUCCESS(Status))
1384 {
1385 DPRINT1("Can't locate driver object for %wZ\n", &ObjectName);
1387 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1388 return Status;
1389 }
1390
1391 /* Free the buffer for driver object name */
1393
1394 /* Check that driver is not already unloading */
1395 if (DriverObject->Flags & DRVO_UNLOAD_INVOKED)
1396 {
1397 DPRINT1("Driver deletion pending\n");
1399 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1400 return STATUS_DELETE_PENDING;
1401 }
1402
1403 /*
1404 * Get path of service...
1405 */
1407
1408 RtlInitUnicodeString(&ImagePath, NULL);
1409
1410 QueryTable[0].Name = L"ImagePath";
1412 QueryTable[0].EntryContext = &ImagePath;
1413
1415 CapturedServiceName.Buffer,
1416 QueryTable,
1417 NULL,
1418 NULL);
1419
1420 /* We no longer need service name */
1421 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1422
1423 if (!NT_SUCCESS(Status))
1424 {
1425 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1427 return Status;
1428 }
1429
1430 /*
1431 * Normalize the image path for all later processing.
1432 */
1434
1435 if (!NT_SUCCESS(Status))
1436 {
1437 DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status);
1439 return Status;
1440 }
1441
1442 /* Free the service path */
1443 ExFreePool(ImagePath.Buffer);
1444
1445 /*
1446 * Unload the module and release the references to the device object
1447 */
1448
1449 /* Call the load/unload routine, depending on current process */
1450 if (DriverObject->DriverUnload && DriverObject->DriverSection &&
1451 (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER)))
1452 {
1453 /* Loop through each device object of the driver
1454 and set DOE_UNLOAD_PENDING flag */
1455 DeviceObject = DriverObject->DeviceObject;
1456 while (DeviceObject)
1457 {
1458 /* Set the unload pending flag for the device */
1459 DeviceExtension = IoGetDevObjExtension(DeviceObject);
1460 DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING;
1461
1462 /* Make sure there are no attached devices or no reference counts */
1463 if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice))
1464 {
1465 /* Not safe to unload */
1466 DPRINT1("Drivers device object is referenced or has attached devices\n");
1467
1468 SafeToUnload = FALSE;
1469 }
1470
1471 DeviceObject = DeviceObject->NextDevice;
1472 }
1473
1474 /* If not safe to unload, then return success */
1475 if (!SafeToUnload)
1476 {
1478 return STATUS_SUCCESS;
1479 }
1480
1481 DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName);
1482
1483 /* Set the unload invoked flag and call the unload routine */
1487
1488 /* Mark the driver object temporary, so it could be deleted later */
1490
1491 /* Dereference it 2 times */
1494
1495 return Status;
1496 }
1497 else
1498 {
1499 DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
1500
1501 /* Dereference one time (refd inside this function) */
1503
1504 /* Return unloading failure */
1506 }
1507}
1508
1509VOID
1510NTAPI
1512{
1513 PDRIVER_REINIT_ITEM ReinitItem;
1515
1516 /* Get the first entry and start looping */
1519 while (Entry)
1520 {
1521 /* Get the item */
1522 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1523
1524 /* Increment reinitialization counter */
1525 ReinitItem->DriverObject->DriverExtension->Count++;
1526
1527 /* Remove the device object flag */
1528 ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED;
1529
1530 /* Call the routine */
1531 ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1532 ReinitItem->Context,
1533 ReinitItem->DriverObject->
1534 DriverExtension->Count);
1535
1536 /* Free the entry */
1538
1539 /* Move to the next one */
1542 }
1543}
1544
1545VOID
1546NTAPI
1548{
1549 PDRIVER_REINIT_ITEM ReinitItem;
1551
1552 /* Get the first entry and start looping */
1555 while (Entry)
1556 {
1557 /* Get the item */
1558 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1559
1560 /* Increment reinitialization counter */
1561 ReinitItem->DriverObject->DriverExtension->Count++;
1562
1563 /* Remove the device object flag */
1564 ReinitItem->DriverObject->Flags &= ~DRVO_BOOTREINIT_REGISTERED;
1565
1566 /* Call the routine */
1567 ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1568 ReinitItem->Context,
1569 ReinitItem->DriverObject->
1570 DriverExtension->Count);
1571
1572 /* Free the entry */
1574
1575 /* Move to the next one */
1578 }
1579
1580 /* Wait for all device actions being finished*/
1582}
1583
1584/* PUBLIC FUNCTIONS ***********************************************************/
1585
1586/*
1587 * @implemented
1588 */
1590NTAPI
1592 _In_opt_ PUNICODE_STRING DriverName,
1593 _In_ PDRIVER_INITIALIZE InitializationFunction)
1594{
1595 WCHAR NameBuffer[100];
1596 USHORT NameLength;
1597 UNICODE_STRING LocalDriverName;
1600 ULONG ObjectSize;
1602 UNICODE_STRING ServiceKeyName;
1604 ULONG i, RetryCount = 0;
1605
1606try_again:
1607 /* First, create a unique name for the driver if we don't have one */
1608 if (!DriverName)
1609 {
1610 /* Create a random name and set up the string */
1611 NameLength = (USHORT)_swprintf(NameBuffer,
1612 DRIVER_ROOT_NAME L"%08u",
1614 LocalDriverName.Length = NameLength * sizeof(WCHAR);
1615 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1616 LocalDriverName.Buffer = NameBuffer;
1617 }
1618 else
1619 {
1620 /* So we can avoid another code path, use a local var */
1621 LocalDriverName = *DriverName;
1622 }
1623
1624 /* Initialize the Attributes */
1625 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
1627 &LocalDriverName,
1629 NULL,
1630 NULL);
1631
1632 /* Create the Object */
1636 KernelMode,
1637 NULL,
1638 ObjectSize,
1639 0,
1640 0,
1641 (PVOID*)&DriverObject);
1642 if (!NT_SUCCESS(Status)) return Status;
1643
1644 DPRINT("IopCreateDriver(): created DO %p\n", DriverObject);
1645
1646 /* Set up the Object */
1647 RtlZeroMemory(DriverObject, ObjectSize);
1649 DriverObject->Size = sizeof(DRIVER_OBJECT);
1651 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
1652 DriverObject->DriverExtension->DriverObject = DriverObject;
1653 DriverObject->DriverInit = InitializationFunction;
1654 /* Loop all Major Functions */
1655 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1656 {
1657 /* Invalidate each function */
1658 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1659 }
1660
1661 /* Set up the service key name buffer */
1662 ServiceKeyName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1663 ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool, LocalDriverName.MaximumLength, TAG_IO);
1664 if (!ServiceKeyName.Buffer)
1665 {
1666 /* Fail */
1670 }
1671
1672 /* For builtin drivers, the ServiceKeyName is equal to DriverName */
1673 RtlCopyUnicodeString(&ServiceKeyName, &LocalDriverName);
1674 ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1675 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
1676
1677 /* Make a copy of the driver name to store in the driver object */
1678 DriverObject->DriverName.MaximumLength = LocalDriverName.Length;
1679 DriverObject->DriverName.Buffer = ExAllocatePoolWithTag(PagedPool,
1680 DriverObject->DriverName.MaximumLength,
1681 TAG_IO);
1682 if (!DriverObject->DriverName.Buffer)
1683 {
1684 /* Fail */
1688 }
1689
1690 RtlCopyUnicodeString(&DriverObject->DriverName, &LocalDriverName);
1691
1692 /* Add the Object and get its handle */
1694 NULL,
1696 0,
1697 NULL,
1698 &hDriver);
1699
1700 /* Eliminate small possibility when this function is called more than
1701 once in a row, and KeTickCount doesn't get enough time to change */
1702 if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100))
1703 {
1704 RetryCount++;
1705 goto try_again;
1706 }
1707
1708 if (!NT_SUCCESS(Status)) return Status;
1709
1710 /* Now reference it */
1712 0,
1714 KernelMode,
1716 NULL);
1717
1718 /* Close the extra handle */
1720
1721 if (!NT_SUCCESS(Status))
1722 {
1723 /* Fail */
1726 return Status;
1727 }
1728
1729 /* Finally, call its init function */
1730 DPRINT("Calling driver entrypoint at %p\n", InitializationFunction);
1731 Status = InitializationFunction(DriverObject, NULL);
1732 if (!NT_SUCCESS(Status))
1733 {
1734 /* If it didn't work, then kill the object */
1735 DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", &LocalDriverName, Status);
1738 return Status;
1739 }
1740
1741 /* Windows does this fixup, keep it for compatibility */
1742 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1743 {
1744 /*
1745 * Make sure the driver didn't set any dispatch entry point to NULL!
1746 * Doing so is illegal; drivers shouldn't touch entry points they
1747 * do not implement.
1748 */
1749
1750 /* Check if it did so anyway */
1751 if (!DriverObject->MajorFunction[i])
1752 {
1753 /* Print a warning in the debug log */
1754 DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n",
1755 &DriverObject->DriverName, i);
1756
1757 /* Fix it up */
1758 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1759 }
1760 }
1761
1762 /* Return the Status */
1763 return Status;
1764}
1765
1766/*
1767 * @implemented
1768 */
1769VOID
1770NTAPI
1773{
1774 /* Simply dereference the Object */
1776}
1777
1778/*
1779 * @implemented
1780 */
1781VOID
1782NTAPI
1784 IN PDRIVER_REINITIALIZE ReinitRoutine,
1786{
1787 PDRIVER_REINIT_ITEM ReinitItem;
1788
1789 /* Allocate the entry */
1791 sizeof(DRIVER_REINIT_ITEM),
1792 TAG_REINIT);
1793 if (!ReinitItem) return;
1794
1795 /* Fill it out */
1796 ReinitItem->DriverObject = DriverObject;
1797 ReinitItem->ReinitRoutine = ReinitRoutine;
1798 ReinitItem->Context = Context;
1799
1800 /* Set the Driver Object flag and insert the entry into the list */
1803 &ReinitItem->ItemEntry,
1805}
1806
1807/*
1808 * @implemented
1809 */
1810VOID
1811NTAPI
1813 IN PDRIVER_REINITIALIZE ReinitRoutine,
1815{
1816 PDRIVER_REINIT_ITEM ReinitItem;
1817
1818 /* Allocate the entry */
1820 sizeof(DRIVER_REINIT_ITEM),
1821 TAG_REINIT);
1822 if (!ReinitItem) return;
1823
1824 /* Fill it out */
1825 ReinitItem->DriverObject = DriverObject;
1826 ReinitItem->ReinitRoutine = ReinitRoutine;
1827 ReinitItem->Context = Context;
1828
1829 /* Set the Driver Object flag and insert the entry into the list */
1832 &ReinitItem->ItemEntry,
1834}
1835
1836/*
1837 * @implemented
1838 */
1840NTAPI
1843 IN ULONG DriverObjectExtensionSize,
1844 OUT PVOID *DriverObjectExtension)
1845{
1846 KIRQL OldIrql;
1847 PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension;
1848 BOOLEAN Inserted = FALSE;
1849
1850 /* Assume failure */
1851 *DriverObjectExtension = NULL;
1852
1853 /* Allocate the extension */
1854 NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool,
1855 sizeof(IO_CLIENT_EXTENSION) +
1856 DriverObjectExtensionSize,
1858 if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES;
1859
1860 /* Clear the extension for teh caller */
1861 RtlZeroMemory(NewDriverExtension,
1862 sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize);
1863
1864 /* Acqure lock */
1866
1867 /* Fill out the extension */
1869
1870 /* Loop the current extensions */
1871 DriverExtensions = IoGetDrvObjExtension(DriverObject)->
1872 ClientDriverExtension;
1873 while (DriverExtensions)
1874 {
1875 /* Check if the identifier matches */
1876 if (DriverExtensions->ClientIdentificationAddress ==
1878 {
1879 /* We have a collision, break out */
1880 break;
1881 }
1882
1883 /* Go to the next one */
1884 DriverExtensions = DriverExtensions->NextExtension;
1885 }
1886
1887 /* Check if we didn't collide */
1888 if (!DriverExtensions)
1889 {
1890 /* Link this one in */
1891 NewDriverExtension->NextExtension =
1892 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
1893 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension =
1894 NewDriverExtension;
1895 Inserted = TRUE;
1896 }
1897
1898 /* Release the lock */
1900
1901 /* Check if insertion failed */
1902 if (!Inserted)
1903 {
1904 /* Free the entry and fail */
1905 ExFreePoolWithTag(NewDriverExtension, TAG_DRIVER_EXTENSION);
1907 }
1908
1909 /* Otherwise, return the pointer */
1910 *DriverObjectExtension = NewDriverExtension + 1;
1911 return STATUS_SUCCESS;
1912}
1913
1914/*
1915 * @implemented
1916 */
1917PVOID
1918NTAPI
1921{
1922 KIRQL OldIrql;
1923 PIO_CLIENT_EXTENSION DriverExtensions;
1924
1925 /* Acquire lock */
1927
1928 /* Loop the list until we find the right one */
1929 DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
1930 while (DriverExtensions)
1931 {
1932 /* Check for a match */
1933 if (DriverExtensions->ClientIdentificationAddress ==
1935 {
1936 /* Break out */
1937 break;
1938 }
1939
1940 /* Keep looping */
1941 DriverExtensions = DriverExtensions->NextExtension;
1942 }
1943
1944 /* Release lock */
1946
1947 /* Return nothing or the extension */
1948 if (!DriverExtensions) return NULL;
1949 return DriverExtensions + 1;
1950}
1951
1954 _In_ HANDLE ServiceHandle,
1956{
1957 UNICODE_STRING ImagePath;
1959 PLDR_DATA_TABLE_ENTRY ModuleObject;
1961
1963 Status = IopGetRegistryValue(ServiceHandle, L"ImagePath", &kvInfo);
1964 if (NT_SUCCESS(Status))
1965 {
1966 if ((kvInfo->Type != REG_EXPAND_SZ && kvInfo->Type != REG_SZ) ||
1967 (kvInfo->DataLength < sizeof(UNICODE_NULL)) ||
1969 ((kvInfo->DataLength % sizeof(WCHAR)) != 0))
1970 {
1971 DPRINT1("ObjectName invalid (Type = %lu, DataLength = %lu)\n",
1972 kvInfo->Type,
1973 kvInfo->DataLength);
1974 ExFreePool(kvInfo);
1976 }
1977
1978 ImagePath.Length = (USHORT)(kvInfo->DataLength - sizeof(UNICODE_NULL));
1979 ImagePath.MaximumLength = kvInfo->DataLength;
1981 if (!ImagePath.Buffer)
1982 {
1983 ExFreePool(kvInfo);
1985 }
1986
1987 RtlMoveMemory(ImagePath.Buffer,
1988 (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
1989 ImagePath.Length);
1990 ImagePath.Buffer[ImagePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
1991 ExFreePool(kvInfo);
1992 }
1993 else
1994 {
1995 return Status;
1996 }
1997
1998 /*
1999 * Normalize the image path for all later processing.
2000 */
2001 Status = IopNormalizeImagePath(&ImagePath, NULL);
2002 if (!NT_SUCCESS(Status))
2003 {
2004 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
2005 return Status;
2006 }
2007
2008 DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
2009
2012
2013 /*
2014 * Load the driver module
2015 */
2016 DPRINT("Loading module from %wZ\n", &ImagePath);
2017 Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress);
2018 RtlFreeUnicodeString(&ImagePath);
2019
2020 if (!NT_SUCCESS(Status))
2021 {
2022 DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
2025 return Status;
2026 }
2027
2028 // Display the loading message
2029 ULONG infoLength;
2030 Status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength);
2032 {
2034 if (servName)
2035 {
2036 Status = ZwQueryKey(ServiceHandle,
2038 servName,
2039 infoLength,
2040 &infoLength);
2041 if (NT_SUCCESS(Status))
2042 {
2044 .Length = servName->NameLength,
2045 .MaximumLength = servName->NameLength,
2046 .Buffer = servName->Name
2047 };
2048
2050 }
2051 ExFreePoolWithTag(servName, TAG_IO);
2052 }
2053 }
2054
2055 NTSTATUS driverEntryStatus;
2056 Status = IopInitializeDriverModule(ModuleObject,
2057 ServiceHandle,
2059 &driverEntryStatus);
2060 if (!NT_SUCCESS(Status))
2061 {
2062 DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status);
2063 }
2064
2067
2068 return Status;
2069}
2070
2071static
2072VOID
2073NTAPI
2076{
2077 PLOAD_UNLOAD_PARAMS LoadParams = Parameter;
2078
2080
2081 if (LoadParams->DriverObject)
2082 {
2083 // unload request
2084 LoadParams->DriverObject->DriverUnload(LoadParams->DriverObject);
2085 LoadParams->Status = STATUS_SUCCESS;
2086 }
2087 else
2088 {
2089 // load request
2090 HANDLE serviceHandle;
2092 status = IopOpenRegistryKeyEx(&serviceHandle, NULL, LoadParams->RegistryPath, KEY_READ);
2093 if (!NT_SUCCESS(status))
2094 {
2095 LoadParams->Status = status;
2096 }
2097 else
2098 {
2099 LoadParams->Status = IopLoadDriver(serviceHandle, &LoadParams->DriverObject);
2100 ZwClose(serviceHandle);
2101 }
2102 }
2103
2104 if (LoadParams->SetEvent)
2105 {
2106 KeSetEvent(&LoadParams->Event, 0, FALSE);
2107 }
2108}
2109
2123{
2124 LOAD_UNLOAD_PARAMS LoadParams;
2125
2126 /* Prepare parameters block */
2127 LoadParams.RegistryPath = RegistryPath;
2128 LoadParams.DriverObject = *DriverObject;
2129
2131 {
2132 LoadParams.SetEvent = TRUE;
2134
2135 /* Initialize and queue a work item */
2136 ExInitializeWorkItem(&LoadParams.WorkItem, IopLoadUnloadDriverWorker, &LoadParams);
2138
2139 /* And wait till it completes */
2141 }
2142 else
2143 {
2144 /* If we're already in a system process, call it right here */
2145 LoadParams.SetEvent = FALSE;
2146 IopLoadUnloadDriverWorker(&LoadParams);
2147 }
2148
2149 return LoadParams.Status;
2150}
2151
2152/*
2153 * NtLoadDriver
2154 *
2155 * Loads a device driver.
2156 *
2157 * Parameters
2158 * DriverServiceName
2159 * Name of the service to load (registry key).
2160 *
2161 * Return Value
2162 * Status
2163 *
2164 * Status
2165 * implemented
2166 */
2169{
2170 UNICODE_STRING CapturedServiceName = { 0, 0, NULL };
2174
2175 PAGED_CODE();
2176
2178
2179 /* Need the appropriate priviliege */
2181 {
2182 DPRINT1("No load privilege!\n");
2184 }
2185
2186 /* Capture the service name */
2187 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
2189 DriverServiceName);
2190 if (!NT_SUCCESS(Status))
2191 {
2192 return Status;
2193 }
2194
2195 DPRINT("NtLoadDriver('%wZ')\n", &CapturedServiceName);
2196
2197 /* We need a service name */
2198 if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL)
2199 {
2200 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
2202 }
2203
2204 /* Load driver and call its entry point */
2206 Status = IopDoLoadUnloadDriver(&CapturedServiceName, &DriverObject);
2207
2208 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
2209 return Status;
2210}
2211
2212/*
2213 * NtUnloadDriver
2214 *
2215 * Unloads a legacy device driver.
2216 *
2217 * Parameters
2218 * DriverServiceName
2219 * Name of the service to unload (registry key).
2220 *
2221 * Return Value
2222 * Status
2223 *
2224 * Status
2225 * implemented
2226 */
2227
2230{
2231 return IopUnloadDriver(DriverServiceName, FALSE);
2232}
2233
2234/* EOF */
#define PAGED_CODE()
#define CODE_SEG(...)
NTSTATUS NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
Definition: driver.c:2229
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1280
unsigned char BOOLEAN
Definition: actypes.h:127
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
static WCHAR ServiceName[]
Definition: browser.c:20
Definition: bufpool.h:45
PUNICODE_STRING *NTAPI CmGetSystemDriverList(VOID)
Definition: cmsysini.c:1864
char TextBuffer[BUFFERLEN]
Definition: combotst.c:45
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define wcsrchr
Definition: compat.h:16
DWORD RVA
Definition: compat.h:1262
#define RtlImageNtHeader
Definition: compat.h:806
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
static const unsigned char pc1[56]
Definition: des.c:54
static const unsigned char pc2[48]
Definition: des.c:68
static const WCHAR DeviceInstance[]
Definition: interface.c:28
static const WCHAR Cleanup[]
Definition: register.c:80
#define L(x)
Definition: resources.c:13
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
#define __drv_allocatesMem(kind)
Definition: driverspecs.h:257
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define MAXIMUM_FILENAME_LENGTH
Definition: env_spec_w32.h:41
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define NonPagedPool
Definition: env_spec_w32.h:307
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
@ Success
Definition: eventcreate.c:712
#define ExGetPreviousMode
Definition: ex.h:143
struct _FileName FileName
Definition: fatprocs.h:897
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment KeRaiseIrqlToDpcLevel
Definition: CrNtStubs.h:68
Status
Definition: gdiplustypes.h:24
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
static LPWSTR ClientIdentificationAddress
Definition: hidclass.c:16
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
VOID NTAPI InbvIndicateProgress(VOID)
Gives some progress feedback, without specifying any explicit number of progress steps or percentage....
Definition: inbv.c:632
PLIST_ENTRY NTAPI ExInterlockedInsertTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:140
PLIST_ENTRY NTAPI ExInterlockedRemoveHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:166
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define REG_SZ
Definition: layer.c:22
#define DRIVER_ROOT_NAME
Definition: ldr.h:5
#define FILESYSTEM_ROOT_NAME
Definition: ldr.h:6
#define LDRP_DRIVER_DEPENDENT_DLL
Definition: ldrtypes.h:60
#define MM_SYSLDR_NO_IMPORTS
Definition: miarm.h:214
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define _swprintf(buf, format,...)
Definition: sprintf.c:56
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
#define _Post_notnull_
Definition: ms_sal.h:701
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define KeGetPreviousMode()
Definition: ketypes.h:1115
#define KernelMode
Definition: asm.h:38
#define DOE_UNLOAD_PENDING
Definition: iotypes.h:153
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID * BaseAddress
Definition: mmfuncs.h:408
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ const STRING * String2
Definition: rtlfuncs.h:2404
_In_ const STRING _In_ BOOLEAN CaseInSensitive
Definition: rtlfuncs.h:2437
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4231
DRIVER_INFORMATION DriverInfo
Definition: main.c:60
WCHAR NTAPI RtlUpcaseUnicodeChar(_In_ WCHAR Source)
Definition: nlsboot.c:177
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _At_(t, a)
Definition: no_sal2.h:40
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _When_(c, a)
Definition: no_sal2.h:38
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
@ KeyBasicInformation
Definition: nt_native.h:1134
#define FILE_READ_DATA
Definition: nt_native.h:628
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define KEY_READ
Definition: nt_native.h:1026
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define FASTCALL
Definition: nt_native.h:50
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define REG_EXPAND_SZ
Definition: nt_native.h:1497
#define UNICODE_NULL
#define UNICODE_STRING_MAX_BYTES
@ NotificationEvent
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
Definition: ntimage.h:462
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:885
NTSTATUS NTAPI RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
Definition: rawfs.c:1193
ULONG IopCaseInsensitive
Definition: iomgr.c:38
@ PiActionAddBootDevices
Definition: io.h:528
@ PiActionEnumRootDevices
Definition: io.h:526
@ PiActionEnumDeviceTree
Definition: io.h:525
USHORT NTAPI PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle)
Definition: pnpinit.c:149
USHORT NTAPI PipGetDriverTagPriority(IN HANDLE ServiceHandle)
Definition: pnpinit.c:192
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1036
#define IoGetDrvObjExtension(DriverObject)
Definition: io.h:135
VOID PiQueueDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action, _In_opt_ PKEVENT CompletionEvent, _Out_opt_ NTSTATUS *CompletionStatus)
Queue a device operation to a worker thread.
Definition: devaction.c:2668
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
NTSTATUS PiPerformSyncDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action)
Perfom a device operation synchronously via PiQueueDeviceAction.
Definition: devaction.c:2727
VOID NTAPI IopReadyDeviceObjects(IN PDRIVER_OBJECT Driver)
Definition: device.c:34
#define IoGetDevObjExtension(DeviceObject)
Definition: io.h:128
NTSTATUS NTAPI MmLoadSystemImage(IN PUNICODE_STRING FileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedName OPTIONAL, IN ULONG Flags, OUT PVOID *ModuleObject, OUT PVOID *ImageBaseAddress)
Definition: sysldr.c:2991
VOID NTAPI MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:1715
NTSTATUS NTAPI MmCallDllInitialize(_In_ PLDR_DATA_TABLE_ENTRY LdrEntry, _In_ PLIST_ENTRY ModuleListHead)
Definition: sysldr.c:464
NTSTATUS NTAPI MmUnloadSystemImage(IN PVOID ImageHandle)
Definition: sysldr.c:976
#define RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END
Definition: rtl.h:25
NTSTATUS NTAPI RtlFindCharInUnicodeString(_In_ ULONG Flags, _In_ PCUNICODE_STRING SearchString, _In_ PCUNICODE_STRING MatchString, _Out_ PUSHORT Position)
const LUID SeLoadDriverPrivilege
Definition: priv.c:29
LIST_ENTRY DriverReinitListHead
Definition: driver.c:22
struct _LOAD_UNLOAD_PARAMS LOAD_UNLOAD_PARAMS
POBJECT_TYPE IoDriverObjectType
Definition: driver.c:34
VOID NTAPI IopReinitializeBootDrivers(VOID)
Definition: driver.c:1547
static VOID FASTCALL IopDisplayLoadingMessage(_In_ PCUNICODE_STRING ServiceName)
Displays a driver-loading message in SOS mode.
Definition: driver.c:334
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:206
NTSTATUS IopLoadDriver(_In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *DriverObject)
Definition: driver.c:1953
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1919
static BOOLEAN IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)
Definition: driver.c:816
KEVENT PiEnumerationFinished
Definition: devaction.c:50
VOID NTAPI IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1812
ERESOURCE IopDriverLoadResource
Definition: driver.c:20
struct _LOAD_UNLOAD_PARAMS * PLOAD_UNLOAD_PARAMS
NTSTATUS NTAPI IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress, IN ULONG DriverObjectExtensionSize, OUT PVOID *DriverObjectExtension)
Definition: driver.c:1841
static const WCHAR ServicesKeyName[]
Definition: driver.c:32
NTSTATUS NTAPI IoCreateDriver(_In_opt_ PUNICODE_STRING DriverName, _In_ PDRIVER_INITIALIZE InitializationFunction)
Definition: driver.c:1591
BOOLEAN PnpSystemInit
Definition: iomgr.c:33
VOID FASTCALL IopInitializeSystemDrivers(VOID)
Definition: driver.c:1225
PLIST_ENTRY IopGroupTable
Definition: driver.c:41
PLIST_ENTRY DriverBootReinitTailEntry
Definition: driver.c:26
KSPIN_LOCK DriverBootReinitListLock
Definition: driver.c:28
NTSTATUS NTAPI IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
Definition: driver.c:1284
NTSTATUS NTAPI MiResolveImageReferences(IN PVOID ImageBase, IN PUNICODE_STRING ImageFileDirectory, IN PUNICODE_STRING NamePrefix OPTIONAL, OUT PCHAR *MissingApi, OUT PWCHAR *MissingDriver, OUT PLOAD_IMPORTS *LoadImports)
Definition: sysldr.c:1076
VOID NTAPI IoDeleteDriver(_In_ PDRIVER_OBJECT DriverObject)
Definition: driver.c:1771
NTSTATUS NTAPI IopInvalidDeviceRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: driver.c:65
VOID NTAPI IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1783
NTSTATUS IopInitializeDriverModule(_In_ PLDR_DATA_TABLE_ENTRY ModuleObject, _In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *OutDriverObject, _Out_ NTSTATUS *DriverEntryStatus)
Initialize a loaded driver.
Definition: driver.c:449
LIST_ENTRY DriverBootReinitListHead
Definition: driver.c:27
KSPIN_LOCK DriverReinitListLock
Definition: driver.c:23
VOID NTAPI IopDeleteDriver(IN PVOID ObjectBody)
Definition: driver.c:77
NTSTATUS IopGetDriverNames(_In_ HANDLE ServiceHandle, _Out_ PUNICODE_STRING DriverName, _Out_opt_ PUNICODE_STRING ServiceName)
Definition: driver.c:123
VOID FASTCALL IopInitializeBootDrivers(VOID)
Definition: driver.c:1038
USHORT IopGroupIndex
Definition: driver.c:40
VOID NTAPI IopReinitializeDrivers(VOID)
Definition: driver.c:1511
NTSTATUS IopDoLoadUnloadDriver(_In_opt_ PUNICODE_STRING RegistryPath, _Inout_ PDRIVER_OBJECT *DriverObject)
Process load and unload driver operations. This is mostly for NtLoadDriver and NtUnloadDriver,...
Definition: driver.c:2120
NTSTATUS NTAPI NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
Definition: driver.c:2168
static VOID NTAPI IopLoadUnloadDriverWorker(_Inout_ PVOID Parameter)
Definition: driver.c:2074
NTSTATUS NTAPI LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, PUNICODE_STRING FileName, PLDR_DATA_TABLE_ENTRY *ModuleObject)
Definition: driver.c:731
NTSTATUS FASTCALL IopNormalizeImagePath(_Inout_ _When_(return >=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem))) PUNICODE_STRING ImagePath, _In_ PUNICODE_STRING ServiceName)
Definition: driver.c:375
PLIST_ENTRY DriverReinitTailEntry
Definition: driver.c:24
UNICODE_STRING IopHardwareDatabaseKey
Definition: driver.c:30
static BOOLEAN IopSuffixUnicodeString(_In_ PCUNICODE_STRING String1, _In_ PCUNICODE_STRING String2, _In_ BOOLEAN CaseInSensitive)
Determines whether String1 may be a suffix of String2.
Definition: driver.c:286
BOOLEAN PnPBootDriversLoaded
Definition: pnpinit.c:20
#define IoCompleteRequest
Definition: irp.c:1272
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:416
#define STATUS_FAILED_DRIVER_ENTRY
Definition: ntstatus.h:1039
#define STATUS_ILL_FORMED_SERVICE_ENTRY
Definition: ntstatus.h:682
NTSTRSAFEVAPI RtlStringCbPrintfA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1148
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2957
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1040
VOID NTAPI ObMakeTemporaryObject(IN PVOID ObjectBody)
Definition: oblife.c:1450
NTSTATUS NTAPI ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, IN ULONG Attributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext, OUT PVOID *ObjectPtr)
Definition: obref.c:408
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:493
NTSYSAPI PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:28
PPCI_DRIVER_EXTENSION DriverExtension
Definition: pci.c:31
short WCHAR
Definition: pedump.c:58
unsigned short USHORT
Definition: pedump.c:61
char CHAR
Definition: pedump.c:57
LIST_ENTRY PsLoadedModuleList
Definition: sysldr.c:21
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_PERMANENT
Definition: winternl.h:226
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define REG_DWORD
Definition: sdbapi.c:615
static __inline NTSTATUS ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest, IN KPROCESSOR_MODE CurrentMode, IN const UNICODE_STRING *UnsafeSrc)
Definition: probe.h:142
static __inline VOID ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, IN KPROCESSOR_MODE CurrentMode)
Definition: probe.h:239
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
_In_ PVOID Context
Definition: storport.h:2269
Definition: arc.h:334
UNICODE_STRING RegistryPath
Definition: arc.h:337
struct _LDR_DATA_TABLE_ENTRY * LdrEntry
Definition: arc.h:338
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:1015
struct _DRIVER_OBJECT * DriverObject
Definition: iotypes.h:2221
UNICODE_STRING ServiceKeyName
Definition: iotypes.h:2224
HANDLE ServiceHandle
Definition: io.h:405
PBOOT_DRIVER_LIST_ENTRY DataTableEntry
Definition: io.h:404
LIST_ENTRY Link
Definition: io.h:402
USHORT TagPosition
Definition: io.h:406
PUNICODE_STRING HardwareDatabase
Definition: iotypes.h:2286
PVOID DriverStart
Definition: iotypes.h:2281
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1]
Definition: iotypes.h:2291
PVOID DriverSection
Definition: iotypes.h:2283
CSHORT Size
Definition: iotypes.h:2278
ULONG DriverSize
Definition: iotypes.h:2282
PDRIVER_INITIALIZE DriverInit
Definition: iotypes.h:2288
PDRIVER_EXTENSION DriverExtension
Definition: iotypes.h:2284
CSHORT Type
Definition: iotypes.h:2277
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2279
PDRIVER_UNLOAD DriverUnload
Definition: iotypes.h:2290
UNICODE_STRING DriverName
Definition: iotypes.h:2285
PDRIVER_OBJECT DriverObject
Definition: io.h:448
PDRIVER_REINITIALIZE ReinitRoutine
Definition: io.h:449
LIST_ENTRY ItemEntry
Definition: io.h:447
PVOID Context
Definition: io.h:450
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
PVOID ClientIdentificationAddress
Definition: iotypes.h:989
struct _IO_CLIENT_EXTENSION * NextExtension
Definition: iotypes.h:988
ULONG LowPart
Definition: wdm.h:5
Definition: btrfs_drv.h:1876
ULONG Flags
Definition: ntddk_ex.h:207
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:149
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY BootDriverListHead
Definition: arc.h:822
LIST_ENTRY LoadOrderListHead
Definition: arc.h:820
PSTR ArcBootDeviceName
Definition: arc.h:841
WORK_QUEUE_ITEM WorkItem
Definition: driver.c:50
NTSTATUS Status
Definition: driver.c:48
BOOLEAN SetEvent
Definition: driver.c:53
PUNICODE_STRING RegistryPath
Definition: driver.c:49
PDRIVER_OBJECT DriverObject
Definition: driver.c:52
USHORT MaximumLength
Definition: env_spec_w32.h:370
ACPI_SIZE Length
Definition: actypes.h:1053
Definition: ps.c:97
#define TAG_REINIT
Definition: tag.h:83
#define TAG_LDR_WSTR
Definition: tag.h:102
#define TAG_RTLREGISTRY
Definition: tag.h:96
#define TAG_IO
Definition: tag.h:79
#define TAG_DRIVER_EXTENSION
Definition: tag.h:61
char serviceName[]
Definition: tftpd.cpp:34
uint16_t * PWSTR
Definition: typedefs.h:56
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static int Link(const char **args)
Definition: vfdcmd.c:2414
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_In_ LPWSTR _In_ ULONG _In_ ULONG _In_ ULONG _Out_ DEVINFO _In_ HDEV _In_ LPWSTR _In_ HANDLE hDriver
Definition: winddi.h:3557
@ KeyNameInformation
Definition: winternl.h:1852
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
BOOLEAN SosEnabled
Definition: winldr.c:34
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:727
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
#define SERVICE_RECOGNIZER_DRIVER
Definition: cmtypes.h:957
#define SERVICE_FILE_SYSTEM_DRIVER
Definition: cmtypes.h:955
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
#define DRVO_BUILTIN_DRIVER
Definition: iotypes.h:2229
#define IO_NO_INCREMENT
Definition: iotypes.h:598
struct _DRIVER_OBJECT DRIVER_OBJECT
VOID(NTAPI * PDRIVER_REINITIALIZE)(_In_ struct _DRIVER_OBJECT *DriverObject, _In_opt_ PVOID Context, _In_ ULONG Count)
Definition: iotypes.h:4458
struct _DRIVER_EXTENSION * PDRIVER_EXTENSION
#define DRVO_BOOTREINIT_REGISTERED
Definition: iotypes.h:4474
#define DRVO_UNLOAD_INVOKED
Definition: iotypes.h:2227
#define DRVO_REINIT_REGISTERED
Definition: iotypes.h:4472
#define IO_TYPE_DRIVER
#define DRVO_LEGACY_DRIVER
Definition: iotypes.h:2228
#define IRP_MJ_MAXIMUM_FUNCTION
DRIVER_INITIALIZE * PDRIVER_INITIALIZE
Definition: iotypes.h:2237
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ UserRequest
Definition: ketypes.h:473
@ Executive
Definition: ketypes.h:467
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ROUND_TO_PAGES(Size)
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define NT_ASSERT
Definition: rtlfuncs.h:3327
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336