1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/io/pnpmgr/pnpinit.c 5 * PURPOSE: PnP Initialization Code 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* GLOBALS ********************************************************************/ 16 17 PUNICODE_STRING PiInitGroupOrderTable; 18 USHORT PiInitGroupOrderTableCount; 19 INTERFACE_TYPE PnpDefaultInterfaceType; 20 BOOLEAN PnPBootDriversLoaded = FALSE; 21 BOOLEAN PnPBootDriversInitialized = FALSE; 22 23 ARBITER_INSTANCE IopRootBusNumberArbiter; 24 ARBITER_INSTANCE IopRootIrqArbiter; 25 ARBITER_INSTANCE IopRootDmaArbiter; 26 ARBITER_INSTANCE IopRootMemArbiter; 27 ARBITER_INSTANCE IopRootPortArbiter; 28 29 extern KEVENT PiEnumerationFinished; 30 31 NTSTATUS NTAPI IopPortInitialize(VOID); 32 NTSTATUS NTAPI IopMemInitialize(VOID); 33 NTSTATUS NTAPI IopDmaInitialize(VOID); 34 NTSTATUS NTAPI IopIrqInitialize(VOID); 35 NTSTATUS NTAPI IopBusNumberInitialize(VOID); 36 37 /* FUNCTIONS ******************************************************************/ 38 39 INTERFACE_TYPE 40 NTAPI 41 IopDetermineDefaultInterfaceType(VOID) 42 { 43 /* FIXME: ReactOS doesn't support MicroChannel yet */ 44 return Isa; 45 } 46 47 NTSTATUS 48 NTAPI 49 IopInitializeArbiters(VOID) 50 { 51 NTSTATUS Status; 52 53 Status = IopPortInitialize(); 54 if (!NT_SUCCESS(Status)) 55 { 56 DPRINT1("IopPortInitialize() return %X\n", Status); 57 return Status; 58 } 59 60 Status = IopMemInitialize(); 61 if (!NT_SUCCESS(Status)) 62 { 63 DPRINT1("IopMemInitialize() return %X\n", Status); 64 return Status; 65 } 66 67 Status = IopDmaInitialize(); 68 if (!NT_SUCCESS(Status)) 69 { 70 DPRINT1("IopDmaInitialize() return %X\n", Status); 71 return Status; 72 } 73 74 Status = IopIrqInitialize(); 75 if (!NT_SUCCESS(Status)) 76 { 77 DPRINT1("IopIrqInitialize() return %X\n", Status); 78 return Status; 79 } 80 81 Status = IopBusNumberInitialize(); 82 if (!NT_SUCCESS(Status)) 83 { 84 DPRINT1("IopBusNumberInitialize() return %X\n", Status); 85 } 86 87 return Status; 88 } 89 90 91 CODE_SEG("INIT") 92 NTSTATUS 93 NTAPI 94 PiInitCacheGroupInformation(VOID) 95 { 96 HANDLE KeyHandle; 97 NTSTATUS Status; 98 PKEY_VALUE_FULL_INFORMATION KeyValueInformation; 99 PUNICODE_STRING GroupTable; 100 ULONG Count; 101 UNICODE_STRING GroupString = 102 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" 103 L"\\Control\\ServiceGroupOrder"); 104 105 /* Open the registry key */ 106 Status = IopOpenRegistryKeyEx(&KeyHandle, 107 NULL, 108 &GroupString, 109 KEY_READ); 110 if (NT_SUCCESS(Status)) 111 { 112 /* Get the list */ 113 Status = IopGetRegistryValue(KeyHandle, L"List", &KeyValueInformation); 114 ZwClose(KeyHandle); 115 116 /* Make sure we got it */ 117 if (NT_SUCCESS(Status)) 118 { 119 /* Make sure it's valid */ 120 if ((KeyValueInformation->Type == REG_MULTI_SZ) && 121 (KeyValueInformation->DataLength)) 122 { 123 /* Convert it to unicode strings */ 124 Status = PnpRegMultiSzToUnicodeStrings(KeyValueInformation, 125 &GroupTable, 126 &Count); 127 128 /* Cache it for later */ 129 PiInitGroupOrderTable = GroupTable; 130 PiInitGroupOrderTableCount = (USHORT)Count; 131 } 132 else 133 { 134 /* Fail */ 135 Status = STATUS_UNSUCCESSFUL; 136 } 137 138 /* Free the information */ 139 ExFreePool(KeyValueInformation); 140 } 141 } 142 143 /* Return status */ 144 return Status; 145 } 146 147 USHORT 148 NTAPI 149 PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle) 150 { 151 NTSTATUS Status; 152 PKEY_VALUE_FULL_INFORMATION KeyValueInformation; 153 USHORT i; 154 PVOID Buffer; 155 UNICODE_STRING Group; 156 PAGED_CODE(); 157 158 /* Make sure we have a cache */ 159 if (!PiInitGroupOrderTable) return -1; 160 161 /* If we don't have a handle, the rest is easy -- return the count */ 162 if (!ServiceHandle) return PiInitGroupOrderTableCount + 1; 163 164 /* Otherwise, get the group value */ 165 Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); 166 if (!NT_SUCCESS(Status)) return PiInitGroupOrderTableCount; 167 168 /* Make sure we have a valid string */ 169 ASSERT(KeyValueInformation->Type == REG_SZ); 170 ASSERT(KeyValueInformation->DataLength); 171 172 /* Convert to unicode string */ 173 Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); 174 PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); 175 Group.MaximumLength = (USHORT)KeyValueInformation->DataLength; 176 Group.Buffer = Buffer; 177 178 /* Loop the groups */ 179 for (i = 0; i < PiInitGroupOrderTableCount; i++) 180 { 181 /* Try to find a match */ 182 if (RtlEqualUnicodeString(&Group, &PiInitGroupOrderTable[i], TRUE)) break; 183 } 184 185 /* We're done */ 186 ExFreePool(KeyValueInformation); 187 return i; 188 } 189 190 USHORT 191 NTAPI 192 PipGetDriverTagPriority(IN HANDLE ServiceHandle) 193 { 194 NTSTATUS Status; 195 HANDLE KeyHandle = NULL; 196 PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; 197 PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag; 198 PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList; 199 PVOID Buffer; 200 UNICODE_STRING Group; 201 PULONG GroupOrder; 202 ULONG Count, Tag = 0; 203 USHORT i = -1; 204 UNICODE_STRING GroupString = 205 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" 206 L"\\Control\\ServiceGroupOrder"); 207 208 /* Open the key */ 209 Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ); 210 if (!NT_SUCCESS(Status)) goto Quickie; 211 212 /* Read the group */ 213 Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); 214 if (!NT_SUCCESS(Status)) goto Quickie; 215 216 /* Make sure we have a group */ 217 if ((KeyValueInformation->Type == REG_SZ) && 218 (KeyValueInformation->DataLength)) 219 { 220 /* Convert to unicode string */ 221 Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); 222 PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); 223 Group.MaximumLength = (USHORT)KeyValueInformation->DataLength; 224 Group.Buffer = Buffer; 225 } 226 227 /* Now read the tag */ 228 Status = IopGetRegistryValue(ServiceHandle, L"Tag", &KeyValueInformationTag); 229 if (!NT_SUCCESS(Status)) goto Quickie; 230 231 /* Make sure we have a tag */ 232 if ((KeyValueInformationTag->Type == REG_DWORD) && 233 (KeyValueInformationTag->DataLength)) 234 { 235 /* Read it */ 236 Tag = *(PULONG)((ULONG_PTR)KeyValueInformationTag + 237 KeyValueInformationTag->DataOffset); 238 } 239 240 /* We can get rid of this now */ 241 ExFreePool(KeyValueInformationTag); 242 243 /* Now let's read the group's tag order */ 244 Status = IopGetRegistryValue(KeyHandle, 245 Group.Buffer, 246 &KeyValueInformationGroupOrderList); 247 248 /* We can get rid of this now */ 249 Quickie: 250 if (KeyValueInformation) ExFreePool(KeyValueInformation); 251 if (KeyHandle) NtClose(KeyHandle); 252 if (!NT_SUCCESS(Status)) return -1; 253 254 /* We're on the success path -- validate the tag order*/ 255 if ((KeyValueInformationGroupOrderList->Type == REG_BINARY) && 256 (KeyValueInformationGroupOrderList->DataLength)) 257 { 258 /* Get the order array */ 259 GroupOrder = (PULONG)((ULONG_PTR)KeyValueInformationGroupOrderList + 260 KeyValueInformationGroupOrderList->DataOffset); 261 262 /* Get the count */ 263 Count = *GroupOrder; 264 ASSERT(((Count + 1) * sizeof(ULONG)) <= 265 KeyValueInformationGroupOrderList->DataLength); 266 267 /* Now loop each tag */ 268 GroupOrder++; 269 for (i = 1; i <= Count; i++) 270 { 271 /* If we found it, we're out */ 272 if (Tag == *GroupOrder) break; 273 274 /* Try the next one */ 275 GroupOrder++; 276 } 277 } 278 279 /* Last buffer to free */ 280 ExFreePool(KeyValueInformationGroupOrderList); 281 return i; 282 } 283 284 CODE_SEG("INIT") 285 NTSTATUS 286 NTAPI 287 IopInitializePlugPlayServices(VOID) 288 { 289 NTSTATUS Status; 290 ULONG Disposition; 291 HANDLE KeyHandle, EnumHandle, ParentHandle, TreeHandle, ControlHandle; 292 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); 293 UNICODE_STRING PnpManagerDriverName = RTL_CONSTANT_STRING(DRIVER_ROOT_NAME L"PnpManager"); 294 PDEVICE_OBJECT Pdo; 295 296 /* Initialize locks and such */ 297 KeInitializeSpinLock(&IopDeviceTreeLock); 298 KeInitializeSpinLock(&IopDeviceActionLock); 299 InitializeListHead(&IopDeviceActionRequestList); 300 KeInitializeEvent(&PiEnumerationFinished, NotificationEvent, TRUE); 301 302 /* Get the default interface */ 303 PnpDefaultInterfaceType = IopDetermineDefaultInterfaceType(); 304 305 /* Initialize arbiters */ 306 Status = IopInitializeArbiters(); 307 if (!NT_SUCCESS(Status)) return Status; 308 309 /* Setup the group cache */ 310 Status = PiInitCacheGroupInformation(); 311 if (!NT_SUCCESS(Status)) return Status; 312 313 /* Open the current control set */ 314 Status = IopOpenRegistryKeyEx(&KeyHandle, 315 NULL, 316 &KeyName, 317 KEY_ALL_ACCESS); 318 if (!NT_SUCCESS(Status)) return Status; 319 320 /* Create the control key */ 321 RtlInitUnicodeString(&KeyName, L"Control"); 322 Status = IopCreateRegistryKeyEx(&ControlHandle, 323 KeyHandle, 324 &KeyName, 325 KEY_ALL_ACCESS, 326 REG_OPTION_NON_VOLATILE, 327 &Disposition); 328 if (!NT_SUCCESS(Status)) return Status; 329 330 /* Check if it's a new key */ 331 if (Disposition == REG_CREATED_NEW_KEY) 332 { 333 HANDLE DeviceClassesHandle; 334 335 /* Create the device classes key */ 336 RtlInitUnicodeString(&KeyName, L"DeviceClasses"); 337 Status = IopCreateRegistryKeyEx(&DeviceClassesHandle, 338 ControlHandle, 339 &KeyName, 340 KEY_ALL_ACCESS, 341 REG_OPTION_NON_VOLATILE, 342 &Disposition); 343 if (!NT_SUCCESS(Status)) return Status; 344 345 ZwClose(DeviceClassesHandle); 346 } 347 348 ZwClose(ControlHandle); 349 350 /* Create the enum key */ 351 RtlInitUnicodeString(&KeyName, REGSTR_KEY_ENUM); 352 Status = IopCreateRegistryKeyEx(&EnumHandle, 353 KeyHandle, 354 &KeyName, 355 KEY_ALL_ACCESS, 356 REG_OPTION_NON_VOLATILE, 357 &Disposition); 358 if (!NT_SUCCESS(Status)) return Status; 359 360 /* Check if it's a new key */ 361 if (Disposition == REG_CREATED_NEW_KEY) 362 { 363 /* FIXME: DACLs */ 364 } 365 366 /* Create the root key */ 367 ParentHandle = EnumHandle; 368 RtlInitUnicodeString(&KeyName, REGSTR_KEY_ROOTENUM); 369 Status = IopCreateRegistryKeyEx(&EnumHandle, 370 ParentHandle, 371 &KeyName, 372 KEY_ALL_ACCESS, 373 REG_OPTION_NON_VOLATILE, 374 &Disposition); 375 NtClose(ParentHandle); 376 if (!NT_SUCCESS(Status)) return Status; 377 NtClose(EnumHandle); 378 379 /* Open the root key now */ 380 RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM"); 381 Status = IopOpenRegistryKeyEx(&EnumHandle, 382 NULL, 383 &KeyName, 384 KEY_ALL_ACCESS); 385 if (NT_SUCCESS(Status)) 386 { 387 /* Create the root dev node */ 388 RtlInitUnicodeString(&KeyName, REGSTR_VAL_ROOT_DEVNODE); 389 Status = IopCreateRegistryKeyEx(&TreeHandle, 390 EnumHandle, 391 &KeyName, 392 KEY_ALL_ACCESS, 393 REG_OPTION_NON_VOLATILE, 394 NULL); 395 NtClose(EnumHandle); 396 if (NT_SUCCESS(Status)) NtClose(TreeHandle); 397 } 398 399 /* Create the root driver */ 400 Status = IoCreateDriver(&PnpManagerDriverName, PnpRootDriverEntry); 401 if (!NT_SUCCESS(Status)) 402 { 403 DPRINT1("IoCreateDriverObject() failed\n"); 404 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); 405 } 406 407 /* Create the root PDO */ 408 Status = IoCreateDevice(IopRootDriverObject, 409 0, 410 NULL, 411 FILE_DEVICE_CONTROLLER, 412 0, 413 FALSE, 414 &Pdo); 415 if (!NT_SUCCESS(Status)) 416 { 417 DPRINT1("IoCreateDevice() failed\n"); 418 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); 419 } 420 421 /* This is a bus enumerated device */ 422 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; 423 424 /* Create the root device node */ 425 IopRootDeviceNode = PipAllocateDeviceNode(Pdo); 426 427 /* Set flags */ 428 IopRootDeviceNode->Flags |= DNF_MADEUP | DNF_ENUMERATED | 429 DNF_IDS_QUERIED | DNF_NO_RESOURCE_REQUIRED; 430 431 /* Create instance path */ 432 if (!RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath, REGSTR_VAL_ROOT_DEVNODE)) 433 { 434 DPRINT1("RtlCreateUnicodeString() failed\n"); 435 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); 436 } 437 438 PnpRootInitializeDevExtension(); 439 440 PiSetDevNodeState(IopRootDeviceNode, DeviceNodeStarted); 441 442 /* Initialize PnP-Event notification support */ 443 Status = IopInitPlugPlayEvents(); 444 if (!NT_SUCCESS(Status)) return Status; 445 446 /* Initialize the Bus Type GUID List */ 447 PnpBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST)); 448 RtlZeroMemory(PnpBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST)); 449 ExInitializeFastMutex(&PnpBusTypeGuidList->Lock); 450 451 /* Initialize PnP root relations (this is a syncronous operation) */ 452 PiQueueDeviceAction(Pdo, PiActionEnumRootDevices, NULL, NULL); 453 454 /* Launch the firmware mapper */ 455 Status = IopUpdateRootKey(); 456 if (!NT_SUCCESS(Status)) return Status; 457 458 /* Close the handle to the control set */ 459 NtClose(KeyHandle); 460 461 /* Initialize PnP root relations (this is a syncronous operation) */ 462 PiQueueDeviceAction(Pdo, PiActionEnumRootDevices, NULL, NULL); 463 464 /* We made it */ 465 return STATUS_SUCCESS; 466 } 467 468 /* EOF */ 469