ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

iorsrce.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.