static NTSTATUS IopUpdateControlKeyWithResources(IN PDEVICE_NODE DeviceNode) { UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control"); UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"AllocConfig"); HANDLE EnumKey, InstanceKey, ControlKey; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; /* Open the Enum key */ Status = IopOpenRegistryKeyEx(&EnumKey, NULL, &EnumRoot, KEY_ENUMERATE_SUB_KEYS); if (!NT_SUCCESS(Status)) return Status; /* Open the instance key (eg. Root\PNP0A03) */ Status = IopOpenRegistryKeyEx(&InstanceKey, EnumKey, &DeviceNode->InstancePath, KEY_ENUMERATE_SUB_KEYS); ZwClose(EnumKey); if (!NT_SUCCESS(Status)) return Status; /* Create/Open the Control key */ InitializeObjectAttributes(&ObjectAttributes, &Control, OBJ_CASE_INSENSITIVE, InstanceKey, NULL); Status = ZwCreateKey(&ControlKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); ZwClose(InstanceKey); if (!NT_SUCCESS(Status)) return Status; /* Write the resource list */ Status = ZwSetValueKey(ControlKey, &ValueName, 0, REG_RESOURCE_LIST, DeviceNode->ResourceList, PnpDetermineResourceListSize(DeviceNode->ResourceList)); ZwClose(ControlKey); if (!NT_SUCCESS(Status)) return Status; return STATUS_SUCCESS; }
INIT_FUNCTION NTSTATUS NTAPI PiInitCacheGroupInformation(VOID) { HANDLE KeyHandle; NTSTATUS Status; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; PUNICODE_STRING GroupTable; ULONG Count; UNICODE_STRING GroupString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" L"\\Control\\ServiceGroupOrder"); /* Open the registry key */ Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ); if (NT_SUCCESS(Status)) { /* Get the list */ Status = IopGetRegistryValue(KeyHandle, L"List", &KeyValueInformation); ZwClose(KeyHandle); /* Make sure we got it */ if (NT_SUCCESS(Status)) { /* Make sure it's valid */ if ((KeyValueInformation->Type == REG_MULTI_SZ) && (KeyValueInformation->DataLength)) { /* Convert it to unicode strings */ Status = PnpRegMultiSzToUnicodeStrings(KeyValueInformation, &GroupTable, &Count); /* Cache it for later */ PiInitGroupOrderTable = GroupTable; PiInitGroupOrderTableCount = (USHORT)Count; } else { /* Fail */ Status = STATUS_UNSUCCESSFUL; } /* Free the information */ ExFreePool(KeyValueInformation); } } /* Return status */ return Status; }
/* * @implemented */ NTSTATUS NTAPI IoSetSystemPartition(IN PUNICODE_STRING VolumeNameString) { NTSTATUS Status; HANDLE RootHandle, KeyHandle; UNICODE_STRING HKLMSystem, KeyString; WCHAR Buffer[sizeof(L"SystemPartition") / sizeof(WCHAR)]; RtlInitUnicodeString(&HKLMSystem, L"\\REGISTRY\\MACHINE\\SYSTEM"); /* Open registry to save data (HKLM\SYSTEM) */ Status = IopOpenRegistryKeyEx(&RootHandle, 0, &HKLMSystem, KEY_ALL_ACCESS); if (!NT_SUCCESS(Status)) { return Status; } /* Create or open Setup subkey */ KeyString.Buffer = Buffer; KeyString.Length = sizeof(L"Setup") - sizeof(UNICODE_NULL); KeyString.MaximumLength = sizeof(L"Setup"); RtlCopyMemory(Buffer, L"Setup", sizeof(L"Setup")); Status = IopCreateRegistryKeyEx(&KeyHandle, RootHandle, &KeyString, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL); ZwClose(RootHandle); if (!NT_SUCCESS(Status)) { return Status; } /* Store caller value */ KeyString.Length = sizeof(L"SystemPartition") - sizeof(UNICODE_NULL); KeyString.MaximumLength = sizeof(L"SystemPartition"); RtlCopyMemory(Buffer, L"SystemPartition", sizeof(L"SystemPartition")); Status = ZwSetValueKey(KeyHandle, &KeyString, 0, REG_SZ, VolumeNameString->Buffer, VolumeNameString->Length + sizeof(UNICODE_NULL)); ZwClose(KeyHandle); return Status; }
NTSTATUS NTAPI INIT_FUNCTION IopInitializePlugPlayServices(VOID) { NTSTATUS Status; ULONG Disposition; HANDLE KeyHandle, EnumHandle, ParentHandle, TreeHandle, ControlHandle; UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); UNICODE_STRING PnpManagerDriverName = RTL_CONSTANT_STRING(DRIVER_ROOT_NAME L"PnpManager"); PDEVICE_OBJECT Pdo; /* Initialize locks and such */ KeInitializeSpinLock(&IopDeviceTreeLock); KeInitializeSpinLock(&IopDeviceRelationsSpinLock); InitializeListHead(&IopDeviceRelationsRequestList); /* Get the default interface */ PnpDefaultInterfaceType = IopDetermineDefaultInterfaceType(); /* Initialize arbiters */ Status = IopInitializeArbiters(); if (!NT_SUCCESS(Status)) return Status; /* Setup the group cache */ Status = PiInitCacheGroupInformation(); if (!NT_SUCCESS(Status)) return Status; /* Open the current control set */ Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &KeyName, KEY_ALL_ACCESS); if (!NT_SUCCESS(Status)) return Status; /* Create the control key */ RtlInitUnicodeString(&KeyName, L"Control"); Status = IopCreateRegistryKeyEx(&ControlHandle, KeyHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) return Status; /* Check if it's a new key */ if (Disposition == REG_CREATED_NEW_KEY) { HANDLE DeviceClassesHandle; /* Create the device classes key */ RtlInitUnicodeString(&KeyName, L"DeviceClasses"); Status = IopCreateRegistryKeyEx(&DeviceClassesHandle, ControlHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) return Status; ZwClose(DeviceClassesHandle); } ZwClose(ControlHandle); /* Create the enum key */ RtlInitUnicodeString(&KeyName, REGSTR_KEY_ENUM); Status = IopCreateRegistryKeyEx(&EnumHandle, KeyHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) return Status; /* Check if it's a new key */ if (Disposition == REG_CREATED_NEW_KEY) { /* FIXME: DACLs */ DPRINT1("Need to build DACL\n"); } /* Create the root key */ ParentHandle = EnumHandle; RtlInitUnicodeString(&KeyName, REGSTR_KEY_ROOTENUM); Status = IopCreateRegistryKeyEx(&EnumHandle, ParentHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); NtClose(ParentHandle); if (!NT_SUCCESS(Status)) return Status; NtClose(EnumHandle); /* Open the root key now */ RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM"); Status = IopOpenRegistryKeyEx(&EnumHandle, NULL, &KeyName, KEY_ALL_ACCESS); if (NT_SUCCESS(Status)) { /* Create the root dev node */ RtlInitUnicodeString(&KeyName, REGSTR_VAL_ROOT_DEVNODE); Status = IopCreateRegistryKeyEx(&TreeHandle, EnumHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL); NtClose(EnumHandle); if (NT_SUCCESS(Status)) NtClose(TreeHandle); } /* Create the root driver */ Status = IoCreateDriver(&PnpManagerDriverName, PnpRootDriverEntry); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateDriverObject() failed\n"); KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); } /* Create the root PDO */ Status = IoCreateDevice(IopRootDriverObject, sizeof(IOPNP_DEVICE_EXTENSION), NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &Pdo); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateDevice() failed\n"); KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); } /* This is a bus enumerated device */ Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; /* Create the root device node */ IopRootDeviceNode = PipAllocateDeviceNode(Pdo); /* Set flags */ IopRootDeviceNode->Flags |= DNF_STARTED + DNF_PROCESSED + DNF_ENUMERATED + DNF_MADEUP + DNF_NO_RESOURCE_REQUIRED + DNF_ADDED; /* Create instance path */ RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath, REGSTR_VAL_ROOT_DEVNODE); /* Call the add device routine */ IopRootDriverObject->DriverExtension->AddDevice(IopRootDriverObject, IopRootDeviceNode->PhysicalDeviceObject); /* Initialize PnP-Event notification support */ Status = IopInitPlugPlayEvents(); if (!NT_SUCCESS(Status)) return Status; /* Report the device to the user-mode pnp manager */ IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &IopRootDeviceNode->InstancePath); /* Initialize the Bus Type GUID List */ PnpBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST)); RtlZeroMemory(PnpBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST)); ExInitializeFastMutex(&PnpBusTypeGuidList->Lock); /* Launch the firmware mapper */ Status = IopUpdateRootKey(); if (!NT_SUCCESS(Status)) return Status; /* Close the handle to the control set */ NtClose(KeyHandle); /* We made it */ return STATUS_SUCCESS; }
NTSTATUS NTAPI PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode, IN BOOLEAN LoadDriver, IN PDRIVER_OBJECT DriverObject) { NTSTATUS Status; HANDLE EnumRootKey, SubKey, ControlKey, ClassKey, PropertiesKey; UNICODE_STRING ClassGuid, Properties; UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); UNICODE_STRING ControlClass = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class"); PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; PWCHAR Buffer; /* Open enumeration root key */ Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, &EnumRoot, KEY_READ); if (!NT_SUCCESS(Status)) { DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); return Status; } /* Open instance subkey */ Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, &DeviceNode->InstancePath, KEY_READ); ZwClose(EnumRootKey); if (!NT_SUCCESS(Status)) { DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); return Status; } /* Get class GUID */ Status = IopGetRegistryValue(SubKey, REGSTR_VAL_CLASSGUID, &KeyValueInformation); if (NT_SUCCESS(Status)) { /* Convert to unicode string */ Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &ClassGuid.Length); ClassGuid.MaximumLength = (USHORT)KeyValueInformation->DataLength; ClassGuid.Buffer = Buffer; /* Open the key */ Status = IopOpenRegistryKeyEx(&ControlKey, NULL, &ControlClass, KEY_READ); if (!NT_SUCCESS(Status)) { /* No class key */ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); ClassKey = NULL; } else { /* Open the class key */ Status = IopOpenRegistryKeyEx(&ClassKey, ControlKey, &ClassGuid, KEY_READ); ZwClose(ControlKey); if (!NT_SUCCESS(Status)) { /* No class key */ DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); ClassKey = NULL; } } /* Check if we made it till here */ if (ClassKey) { /* Get the device properties */ RtlInitUnicodeString(&Properties, REGSTR_KEY_DEVICE_PROPERTIES); Status = IopOpenRegistryKeyEx(&PropertiesKey, ClassKey, &Properties, KEY_READ); ZwClose(ClassKey); if (!NT_SUCCESS(Status)) { /* No properties */ DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); PropertiesKey = NULL; } else { ZwClose(PropertiesKey); } } /* Free the registry data */ ExFreePool(KeyValueInformation); } /* Do ReactOS-style setup */ Status = IopAttachFilterDrivers(DeviceNode, TRUE); if (!NT_SUCCESS(Status)) { IopRemoveDevice(DeviceNode); return Status; } Status = IopInitializeDevice(DeviceNode, DriverObject); if (NT_SUCCESS(Status)) { Status = IopAttachFilterDrivers(DeviceNode, FALSE); if (!NT_SUCCESS(Status)) { IopRemoveDevice(DeviceNode); return Status; } Status = IopStartDevice(DeviceNode); } /* Return status */ return Status; }
USHORT NTAPI PipGetDriverTagPriority(IN HANDLE ServiceHandle) { NTSTATUS Status; HANDLE KeyHandle = NULL; PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag; PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList; PVOID Buffer; UNICODE_STRING Group; PULONG GroupOrder; ULONG Count, Tag = 0; USHORT i = -1; UNICODE_STRING GroupString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" L"\\Control\\ServiceGroupOrder"); /* Open the key */ Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ); if (!NT_SUCCESS(Status)) goto Quickie; /* Read the group */ Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); if (!NT_SUCCESS(Status)) goto Quickie; /* Make sure we have a group */ if ((KeyValueInformation->Type == REG_SZ) && (KeyValueInformation->DataLength)) { /* Convert to unicode string */ Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); Group.MaximumLength = (USHORT)KeyValueInformation->DataLength; Group.Buffer = Buffer; } /* Now read the tag */ Status = IopGetRegistryValue(ServiceHandle, L"Tag", &KeyValueInformationTag); if (!NT_SUCCESS(Status)) goto Quickie; /* Make sure we have a tag */ if ((KeyValueInformationTag->Type == REG_DWORD) && (KeyValueInformationTag->DataLength)) { /* Read it */ Tag = *(PULONG)((ULONG_PTR)KeyValueInformationTag + KeyValueInformationTag->DataOffset); } /* We can get rid of this now */ ExFreePool(KeyValueInformationTag); /* Now let's read the group's tag order */ Status = IopGetRegistryValue(KeyHandle, Group.Buffer, &KeyValueInformationGroupOrderList); /* We can get rid of this now */ Quickie: if (KeyValueInformation) ExFreePool(KeyValueInformation); if (KeyHandle) NtClose(KeyHandle); if (!NT_SUCCESS(Status)) return -1; /* We're on the success path -- validate the tag order*/ if ((KeyValueInformationGroupOrderList->Type == REG_BINARY) && (KeyValueInformationGroupOrderList->DataLength)) { /* Get the order array */ GroupOrder = (PULONG)((ULONG_PTR)KeyValueInformationGroupOrderList + KeyValueInformationGroupOrderList->DataOffset); /* Get the count */ Count = *GroupOrder; ASSERT(((Count + 1) * sizeof(ULONG)) <= KeyValueInformationGroupOrderList->DataLength); /* Now loop each tag */ GroupOrder++; for (i = 1; i <= Count; i++) { /* If we found it, we're out */ if (Tag == *GroupOrder) break; /* Try the next one */ GroupOrder++; } } /* Last buffer to free */ ExFreePool(KeyValueInformationGroupOrderList); return i; }
VOID NTAPI IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName, IN PUNICODE_STRING OsLoaderPathName) { NTSTATUS Status; UNICODE_STRING LinkTarget, KeyName; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE LinkHandle, RegistryHandle, KeyHandle; WCHAR LinkTargetBuffer[256]; UNICODE_STRING CmRegistryMachineSystemName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM"); ASSERT(NtSystemPartitionDeviceName->MaximumLength >= NtSystemPartitionDeviceName->Length + sizeof(WCHAR)); ASSERT(NtSystemPartitionDeviceName->Buffer[NtSystemPartitionDeviceName->Length / sizeof(WCHAR)] == UNICODE_NULL); ASSERT(OsLoaderPathName->MaximumLength >= OsLoaderPathName->Length + sizeof(WCHAR)); ASSERT(OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] == UNICODE_NULL); /* First define needed stuff to open NtSystemPartitionDeviceName symbolic link */ InitializeObjectAttributes(&ObjectAttributes, NtSystemPartitionDeviceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Open NtSystemPartitionDeviceName symbolic link */ Status = ZwOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT("Failed to open symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status); return; } /* Prepare the string that will receive where symbolic link points to */ LinkTarget.Length = 0; /* We will zero the end of the string after having received it */ LinkTarget.MaximumLength = sizeof(LinkTargetBuffer) - sizeof(UNICODE_NULL); LinkTarget.Buffer = LinkTargetBuffer; /* Query target */ Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL); /* We are done with symbolic link */ ObCloseHandle(LinkHandle, KernelMode); if (!NT_SUCCESS(Status)) { DPRINT("Failed querying symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status); return; } /* As promised, we zero the end */ LinkTarget.Buffer[LinkTarget.Length / sizeof(WCHAR)] = UNICODE_NULL; /* Open registry to save data (HKLM\SYSTEM) */ Status = IopOpenRegistryKeyEx(&RegistryHandle, NULL, &CmRegistryMachineSystemName, KEY_ALL_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT("Failed to open HKLM\\SYSTEM, Status=%lx\n", Status); return; } /* Open or create the Setup subkey where we'll store in */ RtlInitUnicodeString(&KeyName, L"Setup"); Status = IopCreateRegistryKeyEx(&KeyHandle, RegistryHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL); /* We're done with HKLM\SYSTEM */ ObCloseHandle(RegistryHandle, KernelMode); if (!NT_SUCCESS(Status)) { DPRINT("Failed opening/creating Setup key, Status=%lx\n", Status); return; } /* Prepare first data writing... */ RtlInitUnicodeString(&KeyName, L"SystemPartition"); /* Write SystemPartition value which is the target of the symbolic link */ Status = ZwSetValueKey(KeyHandle, &KeyName, 0, REG_SZ, LinkTarget.Buffer, LinkTarget.Length + sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { DPRINT("Failed writing SystemPartition value, Status=%lx\n", Status); } /* Prepare for second data writing... */ RtlInitUnicodeString(&KeyName, L"OsLoaderPath"); /* Remove trailing slash if any (one slash only excepted) */ if (OsLoaderPathName->Length > sizeof(WCHAR) && OsLoaderPathName->Buffer[(OsLoaderPathName->Length / sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR) { OsLoaderPathName->Length -= sizeof(WCHAR); OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] = UNICODE_NULL; } /* Then, write down data */ Status = ZwSetValueKey(KeyHandle, &KeyName, 0, REG_SZ, OsLoaderPathName->Buffer, OsLoaderPathName->Length + sizeof(UNICODE_NULL)); if (!NT_SUCCESS(Status)) { DPRINT("Failed writing OsLoaderPath value, Status=%lx\n", Status); } /* We're finally done! */ ObCloseHandle(KeyHandle, KernelMode); }