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