Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeniorsrce.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/io/iorsrce.c 00005 * PURPOSE: Hardware resource managment 00006 * 00007 * PROGRAMMERS: David Welch (welch@mcmail.com) 00008 * Alex Ionescu (alex@relsoft.net) 00009 * Pierre Schweitzer (pierre.schweitzer@reactos.org) 00010 */ 00011 00012 /* INCLUDES *****************************************************************/ 00013 00014 #include <ntoskrnl.h> 00015 #include <debug.h> 00016 00017 /* GLOBALS *******************************************************************/ 00018 00019 static CONFIGURATION_INFORMATION 00020 _SystemConfigurationInformation = { 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE, 0, 0 }; 00021 00022 /* API Parameters to Pass in IopQueryBusDescription */ 00023 typedef struct IO_QUERY { 00024 PINTERFACE_TYPE BusType; 00025 PULONG BusNumber; 00026 PCONFIGURATION_TYPE ControllerType; 00027 PULONG ControllerNumber; 00028 PCONFIGURATION_TYPE PeripheralType; 00029 PULONG PeripheralNumber; 00030 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine; 00031 PVOID Context; 00032 } IO_QUERY, *PIO_QUERY; 00033 00034 PWSTR ArcTypes[42] = { 00035 L"System", 00036 L"CentralProcessor", 00037 L"FloatingPointProcessor", 00038 L"PrimaryICache", 00039 L"PrimaryDCache", 00040 L"SecondaryICache", 00041 L"SecondaryDCache", 00042 L"SecondaryCache", 00043 L"EisaAdapter", 00044 L"TcAdapter", 00045 L"ScsiAdapter", 00046 L"DtiAdapter", 00047 L"MultifunctionAdapter", 00048 L"DiskController", 00049 L"TapeController", 00050 L"CdRomController", 00051 L"WormController", 00052 L"SerialController", 00053 L"NetworkController", 00054 L"DisplayController", 00055 L"ParallelController", 00056 L"PointerController", 00057 L"KeyboardController", 00058 L"AudioController", 00059 L"OtherController", 00060 L"DiskPeripheral", 00061 L"FloppyDiskPeripheral", 00062 L"TapePeripheral", 00063 L"ModemPeripheral", 00064 L"MonitorPeripheral", 00065 L"PrinterPeripheral", 00066 L"PointerPeripheral", 00067 L"KeyboardPeripheral", 00068 L"TerminalPeripheral", 00069 L"OtherPeripheral", 00070 L"LinePeripheral", 00071 L"NetworkPeripheral", 00072 L"SystemMemory", 00073 L"DockingInformation", 00074 L"RealModeIrqRoutingTable", 00075 L"RealModePCIEnumeration", 00076 L"Undefined" 00077 }; 00078 00079 /* PRIVATE FUNCTIONS **********************************************************/ 00080 00081 /* 00082 * IopQueryDeviceDescription 00083 * 00084 * FUNCTION: 00085 * Reads and returns Hardware information from the appropriate hardware 00086 * registry key. Helper sub of IopQueryBusDescription. 00087 * 00088 * ARGUMENTS: 00089 * Query - What the parent function wants. 00090 * RootKey - Which key to look in 00091 * RootKeyHandle - Handle to the key 00092 * Bus - Bus Number. 00093 * BusInformation - The Configuration Information Sent 00094 * 00095 * RETURNS: 00096 * Status 00097 */ 00098 00099 NTSTATUS NTAPI 00100 IopQueryDeviceDescription( 00101 PIO_QUERY Query, 00102 UNICODE_STRING RootKey, 00103 HANDLE RootKeyHandle, 00104 ULONG Bus, 00105 PKEY_VALUE_FULL_INFORMATION *BusInformation) 00106 { 00107 NTSTATUS Status = STATUS_SUCCESS; 00108 00109 /* Controller Stuff */ 00110 UNICODE_STRING ControllerString; 00111 UNICODE_STRING ControllerRootRegName = RootKey; 00112 UNICODE_STRING ControllerRegName; 00113 HANDLE ControllerKeyHandle; 00114 PKEY_FULL_INFORMATION ControllerFullInformation = NULL; 00115 PKEY_VALUE_FULL_INFORMATION ControllerInformation[3] = {NULL, NULL, NULL}; 00116 ULONG ControllerNumber; 00117 ULONG ControllerLoop; 00118 ULONG MaximumControllerNumber; 00119 00120 /* Peripheral Stuff */ 00121 UNICODE_STRING PeripheralString; 00122 HANDLE PeripheralKeyHandle; 00123 PKEY_FULL_INFORMATION PeripheralFullInformation; 00124 PKEY_VALUE_FULL_INFORMATION PeripheralInformation[3] = {NULL, NULL, NULL}; 00125 ULONG PeripheralNumber; 00126 ULONG PeripheralLoop; 00127 ULONG MaximumPeripheralNumber; 00128 00129 /* Global Registry Stuff */ 00130 OBJECT_ATTRIBUTES ObjectAttributes; 00131 ULONG LenFullInformation; 00132 ULONG LenKeyFullInformation; 00133 UNICODE_STRING TempString; 00134 WCHAR TempBuffer[14]; 00135 PWSTR Strings[3] = { 00136 L"Identifier", 00137 L"Configuration Data", 00138 L"Component Information" 00139 }; 00140 00141 /* Temporary String */ 00142 TempString.MaximumLength = sizeof(TempBuffer); 00143 TempString.Length = 0; 00144 TempString.Buffer = TempBuffer; 00145 00146 /* Add Controller Name to String */ 00147 RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 00148 RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]); 00149 00150 /* Set the Controller Number if specified */ 00151 if (Query->ControllerNumber && *(Query->ControllerNumber)) 00152 { 00153 ControllerNumber = *Query->ControllerNumber; 00154 MaximumControllerNumber = ControllerNumber + 1; 00155 } else { 00156 /* Find out how many Controller Numbers there are */ 00157 InitializeObjectAttributes( 00158 &ObjectAttributes, 00159 &ControllerRootRegName, 00160 OBJ_CASE_INSENSITIVE, 00161 NULL, 00162 NULL); 00163 00164 Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); 00165 if (NT_SUCCESS(Status)) 00166 { 00167 /* How much buffer space */ 00168 ZwQueryKey(ControllerKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); 00169 00170 /* Allocate it */ 00171 ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); 00172 00173 /* Get the Information */ 00174 Status = ZwQueryKey(ControllerKeyHandle, KeyFullInformation, ControllerFullInformation, LenFullInformation, &LenFullInformation); 00175 ZwClose(ControllerKeyHandle); 00176 ControllerKeyHandle = NULL; 00177 } 00178 00179 /* No controller was found, go back to function. */ 00180 if (!NT_SUCCESS(Status)) 00181 { 00182 if (ControllerFullInformation != NULL) 00183 ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE); 00184 return Status; 00185 } 00186 00187 /* Find out Controller Numbers */ 00188 ControllerNumber = 0; 00189 MaximumControllerNumber = ControllerFullInformation->SubKeys; 00190 00191 /* Free Memory */ 00192 ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE); 00193 ControllerFullInformation = NULL; 00194 } 00195 00196 /* Save String */ 00197 ControllerRegName = ControllerRootRegName; 00198 00199 /* Loop through controllers */ 00200 for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++) 00201 { 00202 /* Load String */ 00203 ControllerRootRegName = ControllerRegName; 00204 00205 /* Controller Number to Registry String */ 00206 Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString); 00207 00208 /* Create String */ 00209 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 00210 Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); 00211 00212 /* Something messed up */ 00213 if (!NT_SUCCESS(Status)) break; 00214 00215 /* Open the Registry Key */ 00216 InitializeObjectAttributes( 00217 &ObjectAttributes, 00218 &ControllerRootRegName, 00219 OBJ_CASE_INSENSITIVE, 00220 NULL, 00221 NULL); 00222 00223 Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); 00224 00225 /* Read the Configuration Data... */ 00226 if (NT_SUCCESS(Status)) 00227 { 00228 for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++) 00229 { 00230 /* Identifier String First */ 00231 RtlInitUnicodeString(&ControllerString, Strings[ControllerLoop]); 00232 00233 /* How much buffer space */ 00234 Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); 00235 00236 if(!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW) 00237 continue; 00238 00239 /* Allocate it */ 00240 ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); 00241 00242 /* Get the Information */ 00243 Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, ControllerInformation[ControllerLoop], LenKeyFullInformation, &LenKeyFullInformation); 00244 } 00245 00246 /* Clean Up */ 00247 ZwClose(ControllerKeyHandle); 00248 ControllerKeyHandle = NULL; 00249 } 00250 00251 /* Something messed up */ 00252 if (!NT_SUCCESS(Status)) 00253 goto EndLoop; 00254 00255 /* We now have Bus *AND* Controller Information.. is it enough? */ 00256 if (!Query->PeripheralType || !(*Query->PeripheralType)) 00257 { 00258 Status = Query->CalloutRoutine( 00259 Query->Context, 00260 &ControllerRootRegName, 00261 *Query->BusType, 00262 Bus, 00263 BusInformation, 00264 *Query->ControllerType, 00265 ControllerNumber, 00266 ControllerInformation, 00267 0, 00268 0, 00269 NULL); 00270 goto EndLoop; 00271 } 00272 00273 /* Not enough...caller also wants peripheral name */ 00274 Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 00275 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]); 00276 00277 /* Something messed up */ 00278 if (!NT_SUCCESS(Status)) goto EndLoop; 00279 00280 /* Set the Peripheral Number if specified */ 00281 if (Query->PeripheralNumber && *Query->PeripheralNumber) 00282 { 00283 PeripheralNumber = *Query->PeripheralNumber; 00284 MaximumPeripheralNumber = PeripheralNumber + 1; 00285 } else { 00286 /* Find out how many Peripheral Numbers there are */ 00287 InitializeObjectAttributes( 00288 &ObjectAttributes, 00289 &ControllerRootRegName, 00290 OBJ_CASE_INSENSITIVE, 00291 NULL, 00292 NULL); 00293 00294 Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); 00295 00296 if (NT_SUCCESS(Status)) 00297 { 00298 /* How much buffer space */ 00299 ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); 00300 00301 /* Allocate it */ 00302 PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); 00303 00304 /* Get the Information */ 00305 Status = ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, PeripheralFullInformation, LenFullInformation, &LenFullInformation); 00306 ZwClose(PeripheralKeyHandle); 00307 PeripheralKeyHandle = NULL; 00308 } 00309 00310 /* No controller was found, go back to function but clean up first */ 00311 if (!NT_SUCCESS(Status)) 00312 { 00313 Status = STATUS_SUCCESS; 00314 goto EndLoop; 00315 } 00316 00317 /* Find out Peripheral Number */ 00318 PeripheralNumber = 0; 00319 MaximumPeripheralNumber = PeripheralFullInformation->SubKeys; 00320 00321 /* Free Memory */ 00322 ExFreePoolWithTag(PeripheralFullInformation, TAG_IO_RESOURCE); 00323 PeripheralFullInformation = NULL; 00324 } 00325 00326 /* Save Name */ 00327 ControllerRegName = ControllerRootRegName; 00328 00329 /* Loop through Peripherals */ 00330 for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++) 00331 { 00332 /* Restore Name */ 00333 ControllerRootRegName = ControllerRegName; 00334 00335 /* Peripheral Number to Registry String */ 00336 Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString); 00337 00338 /* Create String */ 00339 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 00340 Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); 00341 00342 /* Something messed up */ 00343 if (!NT_SUCCESS(Status)) break; 00344 00345 /* Open the Registry Key */ 00346 InitializeObjectAttributes( 00347 &ObjectAttributes, 00348 &ControllerRootRegName, 00349 OBJ_CASE_INSENSITIVE, 00350 NULL, 00351 NULL); 00352 00353 Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); 00354 00355 if (NT_SUCCESS(Status)) 00356 { 00357 for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++) 00358 { 00359 /* Identifier String First */ 00360 RtlInitUnicodeString(&PeripheralString, Strings[PeripheralLoop]); 00361 00362 /* How much buffer space */ 00363 Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); 00364 00365 if(!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW) 00366 { 00367 PeripheralInformation[PeripheralLoop] = NULL; 00368 continue; 00369 } 00370 00371 /* Allocate it */ 00372 PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); 00373 00374 /* Get the Information */ 00375 Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, PeripheralInformation[PeripheralLoop], LenKeyFullInformation, &LenKeyFullInformation); 00376 } 00377 00378 /* Clean Up */ 00379 ZwClose(PeripheralKeyHandle); 00380 PeripheralKeyHandle = NULL; 00381 00382 /* We now have everything the caller could possibly want */ 00383 if (NT_SUCCESS(Status)) 00384 { 00385 Status = Query->CalloutRoutine( 00386 Query->Context, 00387 &ControllerRootRegName, 00388 *Query->BusType, 00389 Bus, 00390 BusInformation, 00391 *Query->ControllerType, 00392 ControllerNumber, 00393 ControllerInformation, 00394 *Query->PeripheralType, 00395 PeripheralNumber, 00396 PeripheralInformation); 00397 } 00398 00399 /* Free the allocated memory */ 00400 for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++) 00401 { 00402 if (PeripheralInformation[PeripheralLoop]) 00403 { 00404 ExFreePoolWithTag(PeripheralInformation[PeripheralLoop], TAG_IO_RESOURCE); 00405 PeripheralInformation[PeripheralLoop] = NULL; 00406 } 00407 } 00408 00409 /* Something Messed up */ 00410 if (!NT_SUCCESS(Status)) break; 00411 } 00412 } 00413 00414 EndLoop: 00415 /* Free the allocated memory */ 00416 for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++) 00417 { 00418 if (ControllerInformation[ControllerLoop]) 00419 { 00420 ExFreePoolWithTag(ControllerInformation[ControllerLoop], TAG_IO_RESOURCE); 00421 ControllerInformation[ControllerLoop] = NULL; 00422 } 00423 } 00424 00425 /* Something Messed up */ 00426 if (!NT_SUCCESS(Status)) break; 00427 } 00428 00429 return Status; 00430 } 00431 00432 /* 00433 * IopQueryBusDescription 00434 * 00435 * FUNCTION: 00436 * Reads and returns Hardware information from the appropriate hardware 00437 * registry key. Helper sub of IoQueryDeviceDescription. Has two modes 00438 * of operation, either looking for Root Bus Types or for sub-Bus 00439 * information. 00440 * 00441 * ARGUMENTS: 00442 * Query - What the parent function wants. 00443 * RootKey - Which key to look in 00444 * RootKeyHandle - Handle to the key 00445 * Bus - Bus Number. 00446 * KeyIsRoot - Whether we are looking for Root Bus Types or 00447 * information under them. 00448 * 00449 * RETURNS: 00450 * Status 00451 */ 00452 00453 NTSTATUS NTAPI 00454 IopQueryBusDescription( 00455 PIO_QUERY Query, 00456 UNICODE_STRING RootKey, 00457 HANDLE RootKeyHandle, 00458 PULONG Bus, 00459 BOOLEAN KeyIsRoot) 00460 { 00461 NTSTATUS Status; 00462 ULONG BusLoop; 00463 UNICODE_STRING SubRootRegName; 00464 UNICODE_STRING BusString; 00465 UNICODE_STRING SubBusString; 00466 ULONG LenBasicInformation = 0; 00467 ULONG LenFullInformation; 00468 ULONG LenKeyFullInformation; 00469 ULONG LenKey; 00470 HANDLE SubRootKeyHandle; 00471 PKEY_FULL_INFORMATION FullInformation; 00472 PKEY_BASIC_INFORMATION BasicInformation = NULL; 00473 OBJECT_ATTRIBUTES ObjectAttributes; 00474 PKEY_VALUE_FULL_INFORMATION BusInformation[3] = {NULL, NULL, NULL}; 00475 00476 /* How much buffer space */ 00477 Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); 00478 00479 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW) 00480 return Status; 00481 00482 /* Allocate it */ 00483 FullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); 00484 00485 if(!FullInformation) 00486 return STATUS_NO_MEMORY; 00487 00488 /* Get the Information */ 00489 Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, FullInformation, LenFullInformation, &LenFullInformation); 00490 00491 /* Everything was fine */ 00492 if (NT_SUCCESS(Status)) 00493 { 00494 /* Buffer needed for all the keys under this one */ 00495 LenBasicInformation = FullInformation->MaxNameLen + sizeof(KEY_BASIC_INFORMATION); 00496 00497 /* Allocate it */ 00498 BasicInformation = ExAllocatePoolWithTag(PagedPool, LenBasicInformation, TAG_IO_RESOURCE); 00499 } 00500 00501 /* Deallocate the old Buffer */ 00502 ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE); 00503 00504 /* Try to find a Bus */ 00505 for (BusLoop = 0; NT_SUCCESS(Status); BusLoop++) 00506 { 00507 /* Bus parameter was passed and number was matched */ 00508 if ((Query->BusNumber) && (*(Query->BusNumber)) == *Bus) break; 00509 00510 /* Enumerate the Key */ 00511 Status = ZwEnumerateKey( 00512 RootKeyHandle, 00513 BusLoop, 00514 KeyBasicInformation, 00515 BasicInformation, 00516 LenBasicInformation, 00517 &LenKey); 00518 00519 /* Everything enumerated */ 00520 if (!NT_SUCCESS(Status)) break; 00521 00522 /* What Bus are we going to go down? (only check if this is a Root Key) */ 00523 if (KeyIsRoot) 00524 { 00525 if (wcsncmp(BasicInformation->Name, L"MultifunctionAdapter", BasicInformation->NameLength / 2) && 00526 wcsncmp(BasicInformation->Name, L"EisaAdapter", BasicInformation->NameLength / 2) && 00527 wcsncmp(BasicInformation->Name, L"TcAdapter", BasicInformation->NameLength / 2)) 00528 { 00529 /* Nothing found, check next */ 00530 continue; 00531 } 00532 } 00533 00534 /* Enumerate the Bus. */ 00535 BusString.Buffer = BasicInformation->Name; 00536 BusString.Length = (USHORT)BasicInformation->NameLength; 00537 BusString.MaximumLength = (USHORT)BasicInformation->NameLength; 00538 00539 /* Open a handle to the Root Registry Key */ 00540 InitializeObjectAttributes( 00541 &ObjectAttributes, 00542 &BusString, 00543 OBJ_CASE_INSENSITIVE, 00544 RootKeyHandle, 00545 NULL); 00546 00547 Status = ZwOpenKey(&SubRootKeyHandle, KEY_READ, &ObjectAttributes); 00548 00549 /* Go on if we can't */ 00550 if (!NT_SUCCESS(Status)) continue; 00551 00552 /* Key opened. Create the path */ 00553 SubRootRegName = RootKey; 00554 RtlAppendUnicodeToString(&SubRootRegName, L"\\"); 00555 RtlAppendUnicodeStringToString(&SubRootRegName, &BusString); 00556 00557 if (!KeyIsRoot) 00558 { 00559 /* Parsing a SubBus-key */ 00560 int SubBusLoop; 00561 PWSTR Strings[3] = { 00562 L"Identifier", 00563 L"Configuration Data", 00564 L"Component Information"}; 00565 00566 for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++) 00567 { 00568 /* Identifier String First */ 00569 RtlInitUnicodeString(&SubBusString, Strings[SubBusLoop]); 00570 00571 /* How much buffer space */ 00572 ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); 00573 00574 /* Allocate it */ 00575 BusInformation[SubBusLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); 00576 00577 /* Get the Information */ 00578 Status = ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, BusInformation[SubBusLoop], LenKeyFullInformation, &LenKeyFullInformation); 00579 } 00580 00581 if (NT_SUCCESS(Status)) 00582 { 00583 /* Do we have something */ 00584 if (BusInformation[1] != NULL && 00585 BusInformation[1]->DataLength != 0 && 00586 /* Does it match what we want? */ 00587 (((PCM_FULL_RESOURCE_DESCRIPTOR)((ULONG_PTR)BusInformation[1] + BusInformation[1]->DataOffset))->InterfaceType == *(Query->BusType))) 00588 { 00589 /* Found a bus */ 00590 (*Bus)++; 00591 00592 /* Is it the bus we wanted */ 00593 if (Query->BusNumber == NULL || *(Query->BusNumber) == *Bus) 00594 { 00595 /* If we don't want Controller Information, we're done... call the callback */ 00596 if (Query->ControllerType == NULL) 00597 { 00598 Status = Query->CalloutRoutine( 00599 Query->Context, 00600 &SubRootRegName, 00601 *(Query->BusType), 00602 *Bus, 00603 BusInformation, 00604 0, 00605 0, 00606 NULL, 00607 0, 00608 0, 00609 NULL); 00610 } else { 00611 /* We want Controller Info...get it */ 00612 Status = IopQueryDeviceDescription(Query, SubRootRegName, RootKeyHandle, *Bus, (PKEY_VALUE_FULL_INFORMATION*)BusInformation); 00613 } 00614 } 00615 } 00616 } 00617 00618 /* Free the allocated memory */ 00619 for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++) 00620 { 00621 if (BusInformation[SubBusLoop]) 00622 { 00623 ExFreePoolWithTag(BusInformation[SubBusLoop], TAG_IO_RESOURCE); 00624 BusInformation[SubBusLoop] = NULL; 00625 } 00626 } 00627 00628 /* Exit the Loop if we found the bus */ 00629 if (Query->BusNumber != NULL && *(Query->BusNumber) == *Bus) 00630 { 00631 ZwClose(SubRootKeyHandle); 00632 SubRootKeyHandle = NULL; 00633 continue; 00634 } 00635 } 00636 00637 /* Enumerate the buses below us recursively if we haven't found the bus yet */ 00638 Status = IopQueryBusDescription(Query, SubRootRegName, SubRootKeyHandle, Bus, !KeyIsRoot); 00639 00640 /* Everything enumerated */ 00641 if (Status == STATUS_NO_MORE_ENTRIES) Status = STATUS_SUCCESS; 00642 00643 ZwClose(SubRootKeyHandle); 00644 SubRootKeyHandle = NULL; 00645 } 00646 00647 /* Free the last remaining Allocated Memory */ 00648 if (BasicInformation) 00649 ExFreePoolWithTag(BasicInformation, TAG_IO_RESOURCE); 00650 00651 return Status; 00652 } 00653 00654 NTSTATUS 00655 NTAPI 00656 IopFetchConfigurationInformation(OUT PWSTR * SymbolicLinkList, 00657 IN GUID Guid, 00658 IN ULONG ExpectedInterfaces, 00659 IN PULONG Interfaces) 00660 { 00661 NTSTATUS Status; 00662 ULONG IntInterfaces = 0; 00663 PWSTR IntSymbolicLinkList; 00664 00665 /* Get the associated enabled interfaces with the given GUID */ 00666 Status = IoGetDeviceInterfaces(&Guid, NULL, 0, SymbolicLinkList); 00667 if (!NT_SUCCESS(Status)) 00668 { 00669 /* Zero output and leave */ 00670 if (SymbolicLinkList != 0) 00671 { 00672 *SymbolicLinkList = 0; 00673 } 00674 00675 return STATUS_UNSUCCESSFUL; 00676 } 00677 00678 IntSymbolicLinkList = *SymbolicLinkList; 00679 00680 /* Count the number of enabled interfaces by counting the number of symbolic links */ 00681 while (*IntSymbolicLinkList != UNICODE_NULL) 00682 { 00683 IntInterfaces++; 00684 IntSymbolicLinkList += wcslen(IntSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); 00685 } 00686 00687 /* Matching result will define the result */ 00688 Status = (IntInterfaces >= ExpectedInterfaces) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 00689 /* Finally, give back to the caller the number of found interfaces */ 00690 *Interfaces = IntInterfaces; 00691 00692 return Status; 00693 } 00694 00695 VOID 00696 NTAPI 00697 IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName, 00698 IN PUNICODE_STRING OsLoaderPathName) 00699 { 00700 NTSTATUS Status; 00701 UNICODE_STRING LinkTarget, KeyName; 00702 OBJECT_ATTRIBUTES ObjectAttributes; 00703 HANDLE LinkHandle, RegistryHandle, KeyHandle; 00704 WCHAR LinkTargetBuffer[256], KeyNameBuffer[sizeof(L"SystemPartition") / sizeof(WCHAR)]; 00705 UNICODE_STRING CmRegistryMachineSystemName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM"); 00706 00707 ASSERT(NtSystemPartitionDeviceName->MaximumLength >= NtSystemPartitionDeviceName->Length + sizeof(WCHAR)); 00708 ASSERT(NtSystemPartitionDeviceName->Buffer[NtSystemPartitionDeviceName->Length / sizeof(WCHAR)] == UNICODE_NULL); 00709 ASSERT(OsLoaderPathName->MaximumLength >= OsLoaderPathName->Length + sizeof(WCHAR)); 00710 ASSERT(OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] == UNICODE_NULL); 00711 00712 /* First define needed stuff to open NtSystemPartitionDeviceName symbolic link */ 00713 InitializeObjectAttributes(&ObjectAttributes, 00714 NtSystemPartitionDeviceName, 00715 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 00716 NULL, 00717 NULL); 00718 00719 /* Open NtSystemPartitionDeviceName symbolic link */ 00720 Status = ZwOpenSymbolicLinkObject(&LinkHandle, 00721 SYMBOLIC_LINK_QUERY, 00722 &ObjectAttributes); 00723 if (!NT_SUCCESS(Status)) 00724 { 00725 DPRINT("Failed opening given symbolic link!\n"); 00726 return; 00727 } 00728 00729 /* Prepare the string that will receive where symbolic link points to */ 00730 LinkTarget.Length = 0; 00731 /* We will zero the end of the string after having received it */ 00732 LinkTarget.MaximumLength = sizeof(LinkTargetBuffer) - sizeof(UNICODE_NULL); 00733 LinkTarget.Buffer = LinkTargetBuffer; 00734 00735 /* Query target */ 00736 Status = ZwQuerySymbolicLinkObject(LinkHandle, 00737 &LinkTarget, 00738 NULL); 00739 00740 /* We are done with symbolic link */ 00741 ObCloseHandle(LinkHandle, KernelMode); 00742 00743 if (!NT_SUCCESS(Status)) 00744 { 00745 DPRINT("Failed querying given symbolic link!\n"); 00746 return; 00747 } 00748 00749 /* As promised, we zero the end */ 00750 LinkTarget.Buffer[LinkTarget.Length / sizeof(WCHAR)] = UNICODE_NULL; 00751 00752 /* Open registry to save data (HKLM\SYSTEM) */ 00753 Status = IopOpenRegistryKeyEx(&RegistryHandle, 00754 NULL, 00755 &CmRegistryMachineSystemName, 00756 KEY_ALL_ACCESS); 00757 if (!NT_SUCCESS(Status)) 00758 { 00759 DPRINT("Failed opening registry!\n"); 00760 return; 00761 } 00762 00763 /* We'll store in Setup subkey, and as we love fun, we use only one buffer for three writings... */ 00764 wcscpy(KeyNameBuffer, L"Setup"); 00765 KeyName.Length = sizeof(L"Setup") - sizeof(UNICODE_NULL); 00766 KeyName.MaximumLength = sizeof(L"Setup"); 00767 KeyName.Buffer = KeyNameBuffer; 00768 00769 /* So, open or create the subkey */ 00770 Status = IopCreateRegistryKeyEx(&KeyHandle, 00771 RegistryHandle, 00772 &KeyName, 00773 KEY_ALL_ACCESS, 00774 REG_OPTION_NON_VOLATILE, 00775 NULL); 00776 00777 /* We're done with HKLM\SYSTEM */ 00778 ObCloseHandle(RegistryHandle, KernelMode); 00779 00780 if (!NT_SUCCESS(Status)) 00781 { 00782 DPRINT("Failed opening/creating Setup key!\n"); 00783 return; 00784 } 00785 00786 /* Prepare first data writing... */ 00787 wcscpy(KeyNameBuffer, L"SystemPartition"); 00788 KeyName.Length = sizeof(L"SystemPartition") - sizeof(UNICODE_NULL); 00789 KeyName.MaximumLength = sizeof(L"SystemPartition"); 00790 00791 /* Write SystemPartition value which is the target of the symbolic link */ 00792 Status = ZwSetValueKey(KeyHandle, 00793 &KeyName, 00794 0, 00795 REG_SZ, 00796 LinkTarget.Buffer, 00797 LinkTarget.Length + sizeof(WCHAR)); 00798 if (!NT_SUCCESS(Status)) 00799 { 00800 DPRINT("Failed writing SystemPartition value!\n"); 00801 } 00802 00803 /* Prepare for second data writing... */ 00804 wcscpy(KeyName.Buffer, L"OsLoaderPath"); 00805 KeyName.Length = sizeof(L"OsLoaderPath") - sizeof(UNICODE_NULL); 00806 KeyName.MaximumLength = sizeof(L"OsLoaderPath"); 00807 00808 /* Remove trailing slash if any (one slash only excepted) */ 00809 if (OsLoaderPathName->Length > sizeof(WCHAR) && 00810 OsLoaderPathName->Buffer[(OsLoaderPathName->Length / sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR) 00811 { 00812 OsLoaderPathName->Length -= sizeof(WCHAR); 00813 OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] = UNICODE_NULL; 00814 } 00815 00816 /* Then, write down data */ 00817 Status = ZwSetValueKey(KeyHandle, 00818 &KeyName, 00819 0, 00820 REG_SZ, 00821 OsLoaderPathName->Buffer, 00822 OsLoaderPathName->Length + sizeof(WCHAR)); 00823 if (!NT_SUCCESS(Status)) 00824 { 00825 DPRINT("Failed writing OsLoaderPath value!\n"); 00826 } 00827 00828 /* We're finally done! */ 00829 ObCloseHandle(KeyHandle, KernelMode); 00830 } 00831 00832 /* PUBLIC FUNCTIONS ***********************************************************/ 00833 00834 /* 00835 * @implemented 00836 */ 00837 PCONFIGURATION_INFORMATION NTAPI 00838 IoGetConfigurationInformation(VOID) 00839 { 00840 return(&_SystemConfigurationInformation); 00841 } 00842 00843 /* 00844 * @halfplemented 00845 */ 00846 NTSTATUS NTAPI 00847 IoReportResourceUsage(PUNICODE_STRING DriverClassName, 00848 PDRIVER_OBJECT DriverObject, 00849 PCM_RESOURCE_LIST DriverList, 00850 ULONG DriverListSize, 00851 PDEVICE_OBJECT DeviceObject, 00852 PCM_RESOURCE_LIST DeviceList, 00853 ULONG DeviceListSize, 00854 BOOLEAN OverrideConflict, 00855 PBOOLEAN ConflictDetected) 00856 /* 00857 * FUNCTION: Reports hardware resources in the 00858 * \Registry\Machine\Hardware\ResourceMap tree, so that a subsequently 00859 * loaded driver cannot attempt to use the same resources. 00860 * ARGUMENTS: 00861 * DriverClassName - The class of driver under which the resource 00862 * information should be stored. 00863 * DriverObject - The driver object that was input to the 00864 * DriverEntry. 00865 * DriverList - Resources that claimed for the driver rather than 00866 * per-device. 00867 * DriverListSize - Size in bytes of the DriverList. 00868 * DeviceObject - The device object for which resources should be 00869 * claimed. 00870 * DeviceList - List of resources which should be claimed for the 00871 * device. 00872 * DeviceListSize - Size of the per-device resource list in bytes. 00873 * OverrideConflict - True if the resources should be cliamed 00874 * even if a conflict is found. 00875 * ConflictDetected - Points to a variable that receives TRUE if 00876 * a conflict is detected with another driver. 00877 */ 00878 { 00879 NTSTATUS Status; 00880 PCM_RESOURCE_LIST ResourceList; 00881 00882 DPRINT1("IoReportResourceUsage is halfplemented!\n"); 00883 00884 if (!DriverList && !DeviceList) 00885 return STATUS_INVALID_PARAMETER; 00886 00887 if (DeviceList) 00888 ResourceList = DeviceList; 00889 else 00890 ResourceList = DriverList; 00891 00892 Status = IopDetectResourceConflict(ResourceList, FALSE, NULL); 00893 if (Status == STATUS_CONFLICTING_ADDRESSES) 00894 { 00895 *ConflictDetected = TRUE; 00896 00897 if (!OverrideConflict) 00898 { 00899 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n"); 00900 return STATUS_CONFLICTING_ADDRESSES; 00901 } 00902 else 00903 { 00904 DPRINT1("Proceeding with conflicting resources\n"); 00905 } 00906 } 00907 else if (!NT_SUCCESS(Status)) 00908 { 00909 return Status; 00910 } 00911 00912 /* TODO: Claim resources in registry */ 00913 00914 *ConflictDetected = FALSE; 00915 00916 return STATUS_SUCCESS; 00917 } 00918 00919 /* 00920 * @halfplemented 00921 */ 00922 NTSTATUS NTAPI 00923 IoAssignResources(PUNICODE_STRING RegistryPath, 00924 PUNICODE_STRING DriverClassName, 00925 PDRIVER_OBJECT DriverObject, 00926 PDEVICE_OBJECT DeviceObject, 00927 PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources, 00928 PCM_RESOURCE_LIST* AllocatedResources) 00929 { 00930 NTSTATUS Status; 00931 00932 DPRINT1("IoAssignResources is halfplemented!\n"); 00933 00934 *AllocatedResources = NULL; 00935 Status = IopFixupResourceListWithRequirements(RequestedResources, 00936 AllocatedResources); 00937 if (!NT_SUCCESS(Status)) 00938 { 00939 if (Status == STATUS_CONFLICTING_ADDRESSES) 00940 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n"); 00941 00942 return Status; 00943 } 00944 00945 /* TODO: Claim resources in registry */ 00946 00947 return STATUS_SUCCESS; 00948 } 00949 00950 /* 00951 * FUNCTION: 00952 * Reads and returns Hardware information from the appropriate hardware registry key. 00953 * 00954 * ARGUMENTS: 00955 * BusType - MCA, ISA, EISA...specifies the Bus Type 00956 * BusNumber - Which bus of above should be queried 00957 * ControllerType - Specifices the Controller Type 00958 * ControllerNumber - Which of the controllers to query. 00959 * CalloutRoutine - Which function to call for each valid query. 00960 * Context - Value to pass to the callback. 00961 * 00962 * RETURNS: 00963 * Status 00964 * 00965 * STATUS: 00966 * @implemented 00967 */ 00968 00969 NTSTATUS NTAPI 00970 IoQueryDeviceDescription(PINTERFACE_TYPE BusType OPTIONAL, 00971 PULONG BusNumber OPTIONAL, 00972 PCONFIGURATION_TYPE ControllerType OPTIONAL, 00973 PULONG ControllerNumber OPTIONAL, 00974 PCONFIGURATION_TYPE PeripheralType OPTIONAL, 00975 PULONG PeripheralNumber OPTIONAL, 00976 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, 00977 PVOID Context) 00978 { 00979 NTSTATUS Status; 00980 ULONG BusLoopNumber = -1; /* Root Bus */ 00981 OBJECT_ATTRIBUTES ObjectAttributes; 00982 UNICODE_STRING RootRegKey; 00983 HANDLE RootRegHandle; 00984 IO_QUERY Query; 00985 00986 /* Set up the String */ 00987 RootRegKey.Length = 0; 00988 RootRegKey.MaximumLength = 2048; 00989 RootRegKey.Buffer = ExAllocatePoolWithTag(PagedPool, RootRegKey.MaximumLength, TAG_IO_RESOURCE); 00990 RtlAppendUnicodeToString(&RootRegKey, L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"); 00991 00992 /* Open a handle to the Root Registry Key */ 00993 InitializeObjectAttributes( 00994 &ObjectAttributes, 00995 &RootRegKey, 00996 OBJ_CASE_INSENSITIVE, 00997 NULL, 00998 NULL); 00999 01000 Status = ZwOpenKey(&RootRegHandle, KEY_READ, &ObjectAttributes); 01001 01002 if (NT_SUCCESS(Status)) 01003 { 01004 /* Use a helper function to loop though this key and get the info */ 01005 Query.BusType = BusType; 01006 Query.BusNumber = BusNumber; 01007 Query.ControllerType = ControllerType; 01008 Query.ControllerNumber = ControllerNumber; 01009 Query.PeripheralType = PeripheralType; 01010 Query.PeripheralNumber = PeripheralNumber; 01011 Query.CalloutRoutine = CalloutRoutine; 01012 Query.Context = Context; 01013 Status = IopQueryBusDescription(&Query, RootRegKey, RootRegHandle, &BusLoopNumber, TRUE); 01014 01015 /* Close registry */ 01016 ZwClose(RootRegHandle); 01017 } 01018 01019 /* Free Memory */ 01020 ExFreePoolWithTag(RootRegKey.Buffer, TAG_IO_RESOURCE); 01021 01022 return Status; 01023 } 01024 01025 /* 01026 * @implemented 01027 */ 01028 NTSTATUS NTAPI 01029 IoReportHalResourceUsage(PUNICODE_STRING HalDescription, 01030 PCM_RESOURCE_LIST RawList, 01031 PCM_RESOURCE_LIST TranslatedList, 01032 ULONG ListSize) 01033 /* 01034 * FUNCTION: 01035 * Reports hardware resources of the HAL in the 01036 * \Registry\Machine\Hardware\ResourceMap tree. 01037 * ARGUMENTS: 01038 * HalDescription: Descriptive name of the HAL. 01039 * RawList: List of raw (bus specific) resources which should be 01040 * claimed for the HAL. 01041 * TranslatedList: List of translated (system wide) resources which 01042 * should be claimed for the HAL. 01043 * ListSize: Size in bytes of the raw and translated resource lists. 01044 * Both lists have the same size. 01045 * RETURNS: 01046 * Status. 01047 */ 01048 { 01049 OBJECT_ATTRIBUTES ObjectAttributes; 01050 UNICODE_STRING Name; 01051 ULONG Disposition; 01052 NTSTATUS Status; 01053 HANDLE ResourcemapKey; 01054 HANDLE HalKey; 01055 HANDLE DescriptionKey; 01056 01057 /* Open/Create 'RESOURCEMAP' key. */ 01058 RtlInitUnicodeString(&Name, 01059 L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); 01060 InitializeObjectAttributes(&ObjectAttributes, 01061 &Name, 01062 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 01063 0, 01064 NULL); 01065 Status = ZwCreateKey(&ResourcemapKey, 01066 KEY_ALL_ACCESS, 01067 &ObjectAttributes, 01068 0, 01069 NULL, 01070 REG_OPTION_VOLATILE, 01071 &Disposition); 01072 if (!NT_SUCCESS(Status)) 01073 return(Status); 01074 01075 /* Open/Create 'Hardware Abstraction Layer' key */ 01076 RtlInitUnicodeString(&Name, 01077 L"Hardware Abstraction Layer"); 01078 InitializeObjectAttributes(&ObjectAttributes, 01079 &Name, 01080 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 01081 ResourcemapKey, 01082 NULL); 01083 Status = ZwCreateKey(&HalKey, 01084 KEY_ALL_ACCESS, 01085 &ObjectAttributes, 01086 0, 01087 NULL, 01088 REG_OPTION_VOLATILE, 01089 &Disposition); 01090 ZwClose(ResourcemapKey); 01091 if (!NT_SUCCESS(Status)) 01092 return(Status); 01093 01094 /* Create 'HalDescription' key */ 01095 InitializeObjectAttributes(&ObjectAttributes, 01096 HalDescription, 01097 OBJ_CASE_INSENSITIVE, 01098 HalKey, 01099 NULL); 01100 Status = ZwCreateKey(&DescriptionKey, 01101 KEY_ALL_ACCESS, 01102 &ObjectAttributes, 01103 0, 01104 NULL, 01105 REG_OPTION_VOLATILE, 01106 &Disposition); 01107 ZwClose(HalKey); 01108 if (!NT_SUCCESS(Status)) 01109 return(Status); 01110 01111 /* Add '.Raw' value. */ 01112 RtlInitUnicodeString(&Name, 01113 L".Raw"); 01114 Status = ZwSetValueKey(DescriptionKey, 01115 &Name, 01116 0, 01117 REG_RESOURCE_LIST, 01118 RawList, 01119 ListSize); 01120 if (!NT_SUCCESS(Status)) 01121 { 01122 ZwClose(DescriptionKey); 01123 return(Status); 01124 } 01125 01126 /* Add '.Translated' value. */ 01127 RtlInitUnicodeString(&Name, 01128 L".Translated"); 01129 Status = ZwSetValueKey(DescriptionKey, 01130 &Name, 01131 0, 01132 REG_RESOURCE_LIST, 01133 TranslatedList, 01134 ListSize); 01135 ZwClose(DescriptionKey); 01136 01137 return(Status); 01138 } 01139 01140 /* EOF */ Generated on Sat May 26 2012 04:36:09 for ReactOS by
1.7.6.1
|