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 CODE_SEG("INIT") 18 NTSTATUS 19 NTAPI 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 Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE); 71 if (!NT_SUCCESS(Status)) 72 { 73 NtClose(KeyHandle); 74 return Status; 75 } 76 77 /* Create the key */ 78 ParentHandle = KeyHandle; 79 InitializeObjectAttributes(&ObjectAttributes, 80 &KeyName, 81 OBJ_CASE_INSENSITIVE, 82 ParentHandle, 83 NULL); 84 Status = NtCreateKey(&KeyHandle, 85 KEY_READ | KEY_WRITE, 86 &ObjectAttributes, 87 0, 88 NULL, 89 0, 90 &Disposition); 91 NtClose(ParentHandle); 92 93 /* Fail if the key couldn't be created, and make sure it's a new key */ 94 if (!NT_SUCCESS(Status)) return Status; 95 ASSERT(Disposition == REG_CREATED_NEW_KEY); 96 } 97 98 /* Setup the component information key */ 99 RtlInitUnicodeString(&ValueName, L"Component Information"); 100 Status = NtSetValueKey(KeyHandle, 101 &ValueName, 102 0, 103 REG_BINARY, 104 &Component->Flags, 105 FIELD_OFFSET(CONFIGURATION_COMPONENT, 106 ConfigurationDataLength) - 107 FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags)); 108 if (!NT_SUCCESS(Status)) 109 { 110 /* Fail */ 111 NtClose(KeyHandle); 112 return Status; 113 } 114 115 /* Check if we have an identifier */ 116 if (Component->IdentifierLength) 117 { 118 /* Build the string and convert it to Unicode */ 119 RtlInitUnicodeString(&ValueName, L"Identifier"); 120 RtlInitAnsiString(&TempString, Component->Identifier); 121 Status = RtlAnsiStringToUnicodeString(&ValueData, 122 &TempString, 123 TRUE); 124 if (NT_SUCCESS(Status)) 125 { 126 /* Save the identifier in the registry */ 127 Status = NtSetValueKey(KeyHandle, 128 &ValueName, 129 0, 130 REG_SZ, 131 ValueData.Buffer, 132 ValueData.Length + sizeof(UNICODE_NULL)); 133 RtlFreeUnicodeString(&ValueData); 134 } 135 136 /* Check for failure during conversion or registry write */ 137 if (!NT_SUCCESS(Status)) 138 { 139 /* Fail */ 140 NtClose(KeyHandle); 141 return Status; 142 } 143 } 144 145 /* Setup the configuration data string */ 146 RtlInitUnicodeString(&ValueName, L"Configuration Data"); 147 148 /* Check if we got configuration data */ 149 if (CurrentEntry->ConfigurationData) 150 { 151 /* Calculate the total length and check if it fits into our buffer */ 152 Length = Component->ConfigurationDataLength + 153 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList); 154 if (Length > CmpConfigurationAreaSize) 155 { 156 ASSERTMSG("Component too large -- need reallocation!\n", FALSE); 157 } 158 else 159 { 160 /* Copy the data */ 161 RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version, 162 CurrentEntry->ConfigurationData, 163 Component->ConfigurationDataLength); 164 } 165 } 166 else 167 { 168 /* No configuration data, setup defaults */ 169 CmpConfigurationData->PartialResourceList.Version = 0; 170 CmpConfigurationData->PartialResourceList.Revision = 0; 171 CmpConfigurationData->PartialResourceList.Count = 0; 172 Length = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) + 173 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList); 174 } 175 176 /* Set the interface type and bus number */ 177 CmpConfigurationData->InterfaceType = InterfaceType; 178 CmpConfigurationData->BusNumber = BusNumber; 179 180 /* Save the actual data */ 181 Status = NtSetValueKey(KeyHandle, 182 &ValueName, 183 0, 184 REG_FULL_RESOURCE_DESCRIPTOR, 185 CmpConfigurationData, 186 Length); 187 if (!NT_SUCCESS(Status)) 188 { 189 /* Fail */ 190 NtClose(KeyHandle); 191 } 192 else 193 { 194 /* Return the new handle */ 195 *NewHandle = KeyHandle; 196 } 197 198 /* Return status */ 199 return Status; 200 } 201 202 CODE_SEG("INIT") 203 NTSTATUS 204 NTAPI 205 CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry, 206 IN HANDLE ParentHandle, 207 IN INTERFACE_TYPE InterfaceType, 208 IN ULONG BusNumber) 209 { 210 PCONFIGURATION_COMPONENT Component; 211 USHORT DeviceIndexTable[MaximumType + 1] = {0}; 212 INTERFACE_TYPE Interface = InterfaceType; 213 ULONG Bus = BusNumber, i; 214 NTSTATUS Status; 215 HANDLE NewHandle; 216 217 /* Loop each entry */ 218 while (CurrentEntry) 219 { 220 /* Check if this is an adapter */ 221 Component = &CurrentEntry->ComponentEntry; 222 if ((Component->Class == AdapterClass) && 223 (CurrentEntry->Parent->ComponentEntry.Class == SystemClass)) 224 { 225 /* Check what kind of adapter it is */ 226 switch (Component->Type) 227 { 228 /* EISA */ 229 case EisaAdapter: 230 { 231 /* Fixup information */ 232 Interface = Eisa; 233 Bus = CmpTypeCount[EisaAdapter]++; 234 break; 235 } 236 237 /* Turbo-channel */ 238 case TcAdapter: 239 { 240 /* Fixup information */ 241 Interface = TurboChannel; 242 Bus = CmpTypeCount[TurboChannel]++; 243 break; 244 } 245 246 /* ISA, PCI, etc busses */ 247 case MultiFunctionAdapter: 248 { 249 /* Check if we have an identifier */ 250 if (Component->Identifier) 251 { 252 /* Loop each multi-function adapter type */ 253 for (i = 0; CmpMultifunctionTypes[i].Identifier; i++) 254 { 255 /* Check for a name match */ 256 if (!_stricmp(CmpMultifunctionTypes[i].Identifier, 257 Component->Identifier)) 258 { 259 /* Match found */ 260 break; 261 } 262 } 263 264 /* Fix up information */ 265 Interface = CmpMultifunctionTypes[i].InterfaceType; 266 Bus = CmpMultifunctionTypes[i].Count++; 267 } 268 break; 269 } 270 271 /* SCSI Bus */ 272 case ScsiAdapter: 273 { 274 /* Fix up */ 275 Interface = Internal; 276 Bus = CmpTypeCount[ScsiAdapter]++; 277 break; 278 } 279 280 /* Unknown */ 281 default: 282 { 283 Interface = InterfaceTypeUndefined; 284 Bus = CmpUnknownBusCount++; 285 break; 286 } 287 } 288 } 289 290 /* Dump information on the component */ 291 292 /* Setup the hardware node */ 293 Status = CmpInitializeRegistryNode(CurrentEntry, 294 ParentHandle, 295 &NewHandle, 296 Interface, 297 Bus, 298 DeviceIndexTable); 299 if (!NT_SUCCESS(Status)) return Status; 300 301 /* Check for children */ 302 if (CurrentEntry->Child) 303 { 304 /* Recurse child */ 305 Status = CmpSetupConfigurationTree(CurrentEntry->Child, 306 NewHandle, 307 Interface, 308 Bus); 309 if (!NT_SUCCESS(Status)) 310 { 311 /* Fail */ 312 NtClose(NewHandle); 313 return Status; 314 } 315 } 316 317 /* Get to the next entry */ 318 NtClose(NewHandle); 319 CurrentEntry = CurrentEntry->Sibling; 320 } 321 322 /* We're done */ 323 return STATUS_SUCCESS; 324 } 325 326 CODE_SEG("INIT") 327 NTSTATUS 328 NTAPI 329 CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 330 { 331 NTSTATUS Status; 332 OBJECT_ATTRIBUTES ObjectAttributes; 333 HANDLE KeyHandle; 334 ULONG Disposition; 335 UNICODE_STRING KeyName; 336 337 /* Set the alternative system architecture information */ 338 #if defined(SARCH_PC98) 339 SharedUserData->AlternativeArchitecture = NEC98x86; 340 #endif 341 342 /* Setup the key name */ 343 RtlInitUnicodeString(&KeyName, 344 L"\\Registry\\Machine\\Hardware\\DeviceMap"); 345 InitializeObjectAttributes(&ObjectAttributes, 346 &KeyName, 347 OBJ_CASE_INSENSITIVE, 348 NULL, 349 NULL); 350 351 /* Create the device map key */ 352 Status = NtCreateKey(&KeyHandle, 353 KEY_READ | KEY_WRITE, 354 &ObjectAttributes, 355 0, 356 NULL, 357 0, 358 &Disposition); 359 if (!NT_SUCCESS(Status)) 360 return Status; 361 NtClose(KeyHandle); 362 363 /* Nobody should've created this key yet! */ 364 ASSERT(Disposition == REG_CREATED_NEW_KEY); 365 366 /* Setup the key name */ 367 RtlInitUnicodeString(&KeyName, 368 L"\\Registry\\Machine\\Hardware\\Description"); 369 InitializeObjectAttributes(&ObjectAttributes, 370 &KeyName, 371 OBJ_CASE_INSENSITIVE, 372 NULL, 373 NULL); 374 375 /* Create the description key */ 376 Status = NtCreateKey(&KeyHandle, 377 KEY_READ | KEY_WRITE, 378 &ObjectAttributes, 379 0, 380 NULL, 381 0, 382 &Disposition); 383 if (!NT_SUCCESS(Status)) 384 return Status; 385 386 /* Nobody should've created this key yet! */ 387 ASSERT(Disposition == REG_CREATED_NEW_KEY); 388 389 /* Allocate the configuration data buffer */ 390 CmpConfigurationData = ExAllocatePoolWithTag(PagedPool, 391 CmpConfigurationAreaSize, 392 TAG_CM); 393 if (!CmpConfigurationData) 394 { 395 NtClose(KeyHandle); 396 return STATUS_INSUFFICIENT_RESOURCES; 397 } 398 399 /* Check if we got anything from NTLDR */ 400 if (LoaderBlock->ConfigurationRoot) 401 { 402 /* Setup the configuration tree */ 403 Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot, 404 KeyHandle, 405 InterfaceTypeUndefined, 406 -1); 407 } 408 else 409 { 410 /* Nothing else to do */ 411 Status = STATUS_SUCCESS; 412 } 413 414 /* Free the buffer, close our handle and return status */ 415 ExFreePoolWithTag(CmpConfigurationData, TAG_CM); 416 NtClose(KeyHandle); 417 return Status; 418 } 419