/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/config/cmconfig.c * PURPOSE: Configuration Manager - System Configuration Routines * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ /* INCLUDES ******************************************************************/ #include "ntoskrnl.h" #define NDEBUG #include "debug.h" /* FUNCTIONS *****************************************************************/ CODE_SEG("INIT") NTSTATUS NTAPI CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, IN HANDLE NodeHandle, OUT PHANDLE NewHandle, IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber, IN PUSHORT DeviceIndexTable) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName, ValueName, ValueData; HANDLE KeyHandle, ParentHandle; ANSI_STRING TempString; CHAR TempBuffer[12]; WCHAR Buffer[12]; PCONFIGURATION_COMPONENT Component; ULONG Disposition, Length = 0; /* Get the component */ Component = &CurrentEntry->ComponentEntry; /* Set system class components to ARC system type */ if (Component->Class == SystemClass) Component->Type = ArcSystem; /* Create a key for the component */ InitializeObjectAttributes(&ObjectAttributes, &CmTypeName[Component->Type], OBJ_CASE_INSENSITIVE, NodeHandle, NULL); Status = NtCreateKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, 0, NULL, 0, &Disposition); if (!NT_SUCCESS(Status)) return Status; /* Check if this is anything but a system class component */ if (Component->Class != SystemClass) { /* Build the sub-component string */ RtlIntegerToChar(DeviceIndexTable[Component->Type]++, 10, 12, TempBuffer); RtlInitAnsiString(&TempString, TempBuffer); /* Convert it to Unicode */ RtlInitEmptyUnicodeString(&KeyName, Buffer, sizeof(Buffer)); Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE); if (!NT_SUCCESS(Status)) { NtClose(KeyHandle); return Status; } /* Create the key */ ParentHandle = KeyHandle; InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, ParentHandle, NULL); Status = NtCreateKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, 0, NULL, 0, &Disposition); NtClose(ParentHandle); /* Fail if the key couldn't be created, and make sure it's a new key */ if (!NT_SUCCESS(Status)) return Status; ASSERT(Disposition == REG_CREATED_NEW_KEY); } /* Setup the component information key */ RtlInitUnicodeString(&ValueName, L"Component Information"); Status = NtSetValueKey(KeyHandle, &ValueName, 0, REG_BINARY, &Component->Flags, FIELD_OFFSET(CONFIGURATION_COMPONENT, ConfigurationDataLength) - FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags)); if (!NT_SUCCESS(Status)) { /* Fail */ NtClose(KeyHandle); return Status; } /* Check if we have an identifier */ if (Component->IdentifierLength) { /* Build the string and convert it to Unicode */ RtlInitUnicodeString(&ValueName, L"Identifier"); RtlInitAnsiString(&TempString, Component->Identifier); Status = RtlAnsiStringToUnicodeString(&ValueData, &TempString, TRUE); if (NT_SUCCESS(Status)) { /* Save the identifier in the registry */ Status = NtSetValueKey(KeyHandle, &ValueName, 0, REG_SZ, ValueData.Buffer, ValueData.Length + sizeof(UNICODE_NULL)); RtlFreeUnicodeString(&ValueData); } /* Check for failure during conversion or registry write */ if (!NT_SUCCESS(Status)) { /* Fail */ NtClose(KeyHandle); return Status; } } /* Setup the configuration data string */ RtlInitUnicodeString(&ValueName, L"Configuration Data"); /* Check if we got configuration data */ if (CurrentEntry->ConfigurationData) { /* Calculate the total length and check if it fits into our buffer */ Length = Component->ConfigurationDataLength + FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList); if (Length > CmpConfigurationAreaSize) { ASSERTMSG("Component too large -- need reallocation!\n", FALSE); } else { /* Copy the data */ RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version, CurrentEntry->ConfigurationData, Component->ConfigurationDataLength); } } else { /* No configuration data, setup defaults */ CmpConfigurationData->PartialResourceList.Version = 0; CmpConfigurationData->PartialResourceList.Revision = 0; CmpConfigurationData->PartialResourceList.Count = 0; Length = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) + FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList); } /* Set the interface type and bus number */ CmpConfigurationData->InterfaceType = InterfaceType; CmpConfigurationData->BusNumber = BusNumber; /* Save the actual data */ Status = NtSetValueKey(KeyHandle, &ValueName, 0, REG_FULL_RESOURCE_DESCRIPTOR, CmpConfigurationData, Length); if (!NT_SUCCESS(Status)) { /* Fail */ NtClose(KeyHandle); } else { /* Return the new handle */ *NewHandle = KeyHandle; } /* Return status */ return Status; } CODE_SEG("INIT") NTSTATUS NTAPI CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, IN HANDLE ParentHandle, IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber) { PCONFIGURATION_COMPONENT Component; USHORT DeviceIndexTable[MaximumType + 1] = {0}; INTERFACE_TYPE Interface = InterfaceType; ULONG Bus = BusNumber, i; NTSTATUS Status; HANDLE NewHandle; /* Loop each entry */ while (CurrentEntry) { /* Check if this is an adapter */ Component = &CurrentEntry->ComponentEntry; if ((Component->Class == AdapterClass) && (CurrentEntry->Parent->ComponentEntry.Class == SystemClass)) { /* Check what kind of adapter it is */ switch (Component->Type) { /* EISA */ case EisaAdapter: { /* Fixup information */ Interface = Eisa; Bus = CmpTypeCount[EisaAdapter]++; break; } /* Turbo-channel */ case TcAdapter: { /* Fixup information */ Interface = TurboChannel; Bus = CmpTypeCount[TurboChannel]++; break; } /* ISA, PCI, etc busses */ case MultiFunctionAdapter: { /* Check if we have an identifier */ if (Component->Identifier) { /* Loop each multi-function adapter type */ for (i = 0; CmpMultifunctionTypes[i].Identifier; i++) { /* Check for a name match */ if (!_stricmp(CmpMultifunctionTypes[i].Identifier, Component->Identifier)) { /* Match found */ break; } } /* Fix up information */ Interface = CmpMultifunctionTypes[i].InterfaceType; Bus = CmpMultifunctionTypes[i].Count++; } break; } /* SCSI Bus */ case ScsiAdapter: { /* Fix up */ Interface = Internal; Bus = CmpTypeCount[ScsiAdapter]++; break; } /* Unknown */ default: { Interface = InterfaceTypeUndefined; Bus = CmpUnknownBusCount++; break; } } } /* Dump information on the component */ /* Setup the hardware node */ Status = CmpInitializeRegistryNode(CurrentEntry, ParentHandle, &NewHandle, Interface, Bus, DeviceIndexTable); if (!NT_SUCCESS(Status)) return Status; /* Check for children */ if (CurrentEntry->Child) { /* Recurse child */ Status = CmpSetupConfigurationTree(CurrentEntry->Child, NewHandle, Interface, Bus); if (!NT_SUCCESS(Status)) { /* Fail */ NtClose(NewHandle); return Status; } } /* Get to the next entry */ NtClose(NewHandle); CurrentEntry = CurrentEntry->Sibling; } /* We're done */ return STATUS_SUCCESS; } CODE_SEG("INIT") NTSTATUS NTAPI CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE KeyHandle; ULONG Disposition; UNICODE_STRING KeyName; /* Set the alternative system architecture information */ #if defined(SARCH_PC98) SharedUserData->AlternativeArchitecture = NEC98x86; #endif /* Setup the key name */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Hardware\\DeviceMap"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); /* Create the device map key */ Status = NtCreateKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, 0, NULL, 0, &Disposition); if (!NT_SUCCESS(Status)) return Status; NtClose(KeyHandle); /* Nobody should've created this key yet! */ ASSERT(Disposition == REG_CREATED_NEW_KEY); /* Setup the key name */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Hardware\\Description"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); /* Create the description key */ Status = NtCreateKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, 0, NULL, 0, &Disposition); if (!NT_SUCCESS(Status)) return Status; /* Nobody should've created this key yet! */ ASSERT(Disposition == REG_CREATED_NEW_KEY); /* Allocate the configuration data buffer */ CmpConfigurationData = ExAllocatePoolWithTag(PagedPool, CmpConfigurationAreaSize, TAG_CM); if (!CmpConfigurationData) { NtClose(KeyHandle); return STATUS_INSUFFICIENT_RESOURCES; } /* Check if we got anything from NTLDR */ if (LoaderBlock->ConfigurationRoot) { /* Setup the configuration tree */ Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot, KeyHandle, InterfaceTypeUndefined, -1); } else { /* Nothing else to do */ Status = STATUS_SUCCESS; } /* Free the buffer, close our handle and return status */ ExFreePoolWithTag(CmpConfigurationData, TAG_CM); NtClose(KeyHandle); return Status; }