1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/config/cmconfig.c 5 * PURPOSE: Configuration Manager - System Configuration Routines 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "ntoskrnl.h" 12 #define NDEBUG 13 #include "debug.h" 14 15 /* FUNCTIONS *****************************************************************/ 16 17 NTSTATUS 18 NTAPI 19 INIT_FUNCTION 20 CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, 21 IN HANDLE NodeHandle, 22 OUT PHANDLE NewHandle, 23 IN INTERFACE_TYPE InterfaceType, 24 IN ULONG BusNumber, 25 IN PUSHORT DeviceIndexTable) 26 { 27 NTSTATUS Status; 28 OBJECT_ATTRIBUTES ObjectAttributes; 29 UNICODE_STRING KeyName, ValueName, ValueData; 30 HANDLE KeyHandle, ParentHandle; 31 ANSI_STRING TempString; 32 CHAR TempBuffer[12]; 33 WCHAR Buffer[12]; 34 PCONFIGURATION_COMPONENT Component; 35 ULONG Disposition, Length = 0; 36 37 /* Get the component */ 38 Component = &CurrentEntry->ComponentEntry; 39 40 /* Set system class components to ARC system type */ 41 if (Component->Class == SystemClass) Component->Type = ArcSystem; 42 43 /* Create a key for the component */ 44 InitializeObjectAttributes(&ObjectAttributes, 45 &CmTypeName[Component->Type], 46 OBJ_CASE_INSENSITIVE, 47 NodeHandle, 48 NULL); 49 Status = NtCreateKey(&KeyHandle, 50 KEY_READ | KEY_WRITE, 51 &ObjectAttributes, 52 0, 53 NULL, 54 0, 55 &Disposition); 56 if (!NT_SUCCESS(Status)) return Status; 57 58 /* Check if this is anything but a system class component */ 59 if (Component->Class != SystemClass) 60 { 61 /* Build the sub-component string */ 62 RtlIntegerToChar(DeviceIndexTable[Component->Type]++, 63 10, 64 12, 65 TempBuffer); 66 RtlInitAnsiString(&TempString, TempBuffer); 67 68 /* Convert it to Unicode */ 69 RtlInitEmptyUnicodeString(&KeyName, Buffer, sizeof(Buffer)); 70 RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE); 71 72 /* Create the key */ 73 ParentHandle = KeyHandle; 74 InitializeObjectAttributes(&ObjectAttributes, 75 &KeyName, 76 OBJ_CASE_INSENSITIVE, 77 ParentHandle, 78 NULL); 79 Status = NtCreateKey(&KeyHandle, 80 KEY_READ | KEY_WRITE, 81 &ObjectAttributes, 82 0, 83 NULL, 84 0, 85 &Disposition); 86 NtClose(ParentHandle); 87 88 /* Fail if the key couldn't be created, and make sure it's a new key */ 89 if (!NT_SUCCESS(Status)) return Status; 90 ASSERT(Disposition == REG_CREATED_NEW_KEY); 91 } 92 93 /* Setup the component information key */ 94 RtlInitUnicodeString(&ValueName, L"Component Information"); 95 Status = NtSetValueKey(KeyHandle, 96 &ValueName, 97 0, 98 REG_BINARY, 99 &Component->Flags, 100 FIELD_OFFSET(CONFIGURATION_COMPONENT, 101 ConfigurationDataLength) - 102 FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags)); 103 if (!NT_SUCCESS(Status)) 104 { 105 /* Fail */ 106 NtClose(KeyHandle); 107 return Status; 108 } 109 110 /* Check if we have an identifier */ 111 if (Component->IdentifierLength) 112 { 113 /* Build the string and convert it to Unicode */ 114 RtlInitUnicodeString(&ValueName, L"Identifier"); 115 RtlInitAnsiString(&TempString, Component->Identifier); 116 Status = RtlAnsiStringToUnicodeString(&ValueData, 117 &TempString, 118 TRUE); 119 if (NT_SUCCESS(Status)) 120 { 121 /* Save the identifier in the registry */ 122 Status = NtSetValueKey(KeyHandle, 123 &ValueName, 124 0, 125 REG_SZ, 126 ValueData.Buffer, 127 ValueData.Length + sizeof(UNICODE_NULL)); 128 RtlFreeUnicodeString(&ValueData); 129 } 130 131 /* Check for failure during conversion or registry write */ 132 if (!NT_SUCCESS(Status)) 133 { 134 /* Fail */ 135 NtClose(KeyHandle); 136 return Status; 137 } 138 } 139 140 /* Setup the configuration data string */ 141 RtlInitUnicodeString(&ValueName, L"Configuration Data"); 142 143 /* Check if we got configuration data */ 144 if (CurrentEntry->ConfigurationData) 145 { 146 /* Calculate the total length and check if it fits into our buffer */ 147 Length = Component->ConfigurationDataLength + 148 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList); 149 if (Length > CmpConfigurationAreaSize) 150 { 151 ASSERTMSG("Component too large -- need reallocation!", FALSE); 152 } 153 else 154 { 155 /* Copy the data */ 156 RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version, 157 CurrentEntry->ConfigurationData, 158 Component->ConfigurationDataLength); 159 } 160 } 161 else 162 { 163 /* No configuration data, setup defaults */ 164 CmpConfigurationData->PartialResourceList.Version = 0; 165 CmpConfigurationData->PartialResourceList.Revision = 0; 166 CmpConfigurationData->PartialResourceList.Count = 0; 167 Length = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) + 168 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList); 169 } 170 171 /* Set the interface type and bus number */ 172 CmpConfigurationData->InterfaceType = InterfaceType; 173 CmpConfigurationData->BusNumber = BusNumber; 174 175 /* Save the actual data */ 176 Status = NtSetValueKey(KeyHandle, 177 &ValueName, 178 0, 179 REG_FULL_RESOURCE_DESCRIPTOR, 180 CmpConfigurationData, 181 Length); 182 if (!NT_SUCCESS(Status)) 183 { 184 /* Fail */ 185 NtClose(KeyHandle); 186 } 187 else 188 { 189 /* Return the new handle */ 190 *NewHandle = KeyHandle; 191 } 192 193 /* Return status */ 194 return Status; 195 } 196 197 NTSTATUS 198 NTAPI 199 INIT_FUNCTION 200 CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, 201 IN HANDLE ParentHandle, 202 IN INTERFACE_TYPE InterfaceType, 203 IN ULONG BusNumber) 204 { 205 PCONFIGURATION_COMPONENT Component; 206 USHORT DeviceIndexTable[MaximumType + 1] = {0}; 207 ULONG Interface = InterfaceType, Bus = BusNumber, i; 208 NTSTATUS Status; 209 HANDLE NewHandle; 210 211 /* Loop each entry */ 212 while (CurrentEntry) 213 { 214 /* Check if this is an adapter */ 215 Component = &CurrentEntry->ComponentEntry; 216 if ((Component->Class == AdapterClass) && 217 (CurrentEntry->Parent->ComponentEntry.Class == SystemClass)) 218 { 219 /* Check what kind of adapter it is */ 220 switch (Component->Type) 221 { 222 /* EISA */ 223 case EisaAdapter: 224 225 /* Fixup information */ 226 Interface = Eisa; 227 Bus = CmpTypeCount[EisaAdapter]++; 228 break; 229 230 /* Turbo-channel */ 231 case TcAdapter: 232 233 /* Fixup information */ 234 Interface = TurboChannel; 235 Bus = CmpTypeCount[TurboChannel]++; 236 break; 237 238 /* ISA, PCI, etc busses */ 239 case MultiFunctionAdapter: 240 241 /* Check if we have an identifier */ 242 if (Component->Identifier) 243 { 244 /* Loop each multi-function adapter type */ 245 for (i = 0; CmpMultifunctionTypes[i].Identifier; i++) 246 { 247 /* Check for a name match */ 248 if (!_stricmp(CmpMultifunctionTypes[i].Identifier, 249 Component->Identifier)) 250 { 251 /* Match found */ 252 break; 253 } 254 } 255 256 /* Fix up information */ 257 Interface = CmpMultifunctionTypes[i].InterfaceType; 258 Bus = CmpMultifunctionTypes[i].Count++; 259 } 260 break; 261 262 /* SCSI Bus */ 263 case ScsiAdapter: 264 265 /* Fix up */ 266 Interface = Internal; 267 Bus = CmpTypeCount[ScsiAdapter]++; 268 break; 269 270 /* Unknown */ 271 default: 272 Interface = -1; 273 Bus = CmpUnknownBusCount++; 274 break; 275 } 276 } 277 278 /* Dump information on the component */ 279 280 /* Setup the hardware node */ 281 Status = CmpInitializeRegistryNode(CurrentEntry, 282 ParentHandle, 283 &NewHandle, 284 Interface, 285 Bus, 286 DeviceIndexTable); 287 if (!NT_SUCCESS(Status)) return Status; 288 289 /* Check for children */ 290 if (CurrentEntry->Child) 291 { 292 /* Recurse child */ 293 Status = CmpSetupConfigurationTree(CurrentEntry->Child, 294 NewHandle, 295 Interface, 296 Bus); 297 if (!NT_SUCCESS(Status)) 298 { 299 /* Fail */ 300 NtClose(NewHandle); 301 return Status; 302 } 303 } 304 305 /* Get to the next entry */ 306 NtClose(NewHandle); 307 CurrentEntry = CurrentEntry->Sibling; 308 } 309 310 /* We're done */ 311 return STATUS_SUCCESS; 312 } 313 314 NTSTATUS 315 NTAPI 316 INIT_FUNCTION 317 CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 318 { 319 NTSTATUS Status; 320 OBJECT_ATTRIBUTES ObjectAttributes; 321 HANDLE KeyHandle; 322 ULONG Disposition; 323 UNICODE_STRING KeyName; 324 325 /* Setup the key name */ 326 RtlInitUnicodeString(&KeyName, 327 L"\\Registry\\Machine\\Hardware\\DeviceMap"); 328 InitializeObjectAttributes(&ObjectAttributes, 329 &KeyName, 330 OBJ_CASE_INSENSITIVE, 331 NULL, 332 NULL); 333 334 /* Create the device map key */ 335 Status = NtCreateKey(&KeyHandle, 336 KEY_READ | KEY_WRITE, 337 &ObjectAttributes, 338 0, 339 NULL, 340 0, 341 &Disposition); 342 if (!NT_SUCCESS(Status)) return Status; 343 NtClose(KeyHandle); 344 345 /* Nobody should've created this key yet! */ 346 ASSERT(Disposition == REG_CREATED_NEW_KEY); 347 348 /* Setup the key name */ 349 RtlInitUnicodeString(&KeyName, 350 L"\\Registry\\Machine\\Hardware\\Description"); 351 InitializeObjectAttributes(&ObjectAttributes, 352 &KeyName, 353 OBJ_CASE_INSENSITIVE, 354 NULL, 355 NULL); 356 357 /* Create the description key */ 358 Status = NtCreateKey(&KeyHandle, 359 KEY_READ | KEY_WRITE, 360 &ObjectAttributes, 361 0, 362 NULL, 363 0, 364 &Disposition); 365 if (!NT_SUCCESS(Status)) return Status; 366 367 /* Nobody should've created this key yet! */ 368 ASSERT(Disposition == REG_CREATED_NEW_KEY); 369 370 /* Allocate the configuration data buffer */ 371 CmpConfigurationData = ExAllocatePoolWithTag(PagedPool, 372 CmpConfigurationAreaSize, 373 TAG_CM); 374 if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES; 375 376 /* Check if we got anything from NTLDR */ 377 if (LoaderBlock->ConfigurationRoot) 378 { 379 /* Setup the configuration tree */ 380 Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot, 381 KeyHandle, 382 -1, 383 -1); 384 } 385 else 386 { 387 /* Nothing else to do */ 388 Status = STATUS_SUCCESS; 389 } 390 391 /* Close our handle, free the buffer and return status */ 392 ExFreePoolWithTag(CmpConfigurationData, TAG_CM); 393 NtClose(KeyHandle); 394 return Status; 395 } 396