/* * @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; }
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); }