test: query.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# query.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989-1994  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     query.c
    00008
    00009 Abstract:
    00010
    00011     This module contains the subroutines to Query Device Descriptions from
    00012     the Hardware tree in the registry
    00013
    00014 Author:
    00015
    00016     Andre Vachon (andreva) 20-Jun-1994
    00017
    00018 Environment:
    00019
    00020     Kernel mode
    00021
    00022 Revision History:
    00023
    00024
    00025 --*/
    00026
    00027 #include "iop.h"
    00028
    00029 typedef struct _IO_QUERY_DESC {
    00030     PINTERFACE_TYPE BusType;
    00031     PULONG BusNumber;
    00032     PCONFIGURATION_TYPE ControllerType;
    00033     PULONG ControllerNumber;
    00034     PCONFIGURATION_TYPE PeripheralType;
    00035     PULONG PeripheralNumber;
    00036     PIO_QUERY_DEVICE_ROUTINE CalloutRoutine;
    00037     PVOID Context;
    00038 } IO_QUERY_DESC, *PIO_QUERY_DESC;
    00039
    00040
    00041 NTSTATUS
    00042 pIoQueryBusDescription(
    00043     PIO_QUERY_DESC QueryDescription,
    00044     UNICODE_STRING PathName,
    00045     HANDLE RootHandle,
    00046     PULONG BusNum,
    00047     BOOLEAN HighKey
    00048     );
    00049
    00050 NTSTATUS
    00051 pIoQueryDeviceDescription(
    00052     PIO_QUERY_DESC QueryDescription,
    00053     UNICODE_STRING PathName,
    00054     HANDLE RootHandle,
    00055     ULONG BusNum,
    00056     PKEY_VALUE_FULL_INFORMATION *BusValueInfo
    00057     );
    00058
    00059
    00060 #ifdef ALLOC_PRAGMA
    00061 #pragma alloc_text(PAGE, IoQueryDeviceDescription)
    00062 #pragma alloc_text(PAGE, pIoQueryBusDescription)
    00063 #pragma alloc_text(PAGE, pIoQueryDeviceDescription)
    00064 #endif
    00065
    00066
    00067
    00068
    00069 NTSTATUS
    00070 IoQueryDeviceDescription(
    00071     IN PINTERFACE_TYPE BusType OPTIONAL,
    00072     IN PULONG BusNumber OPTIONAL,
    00073     IN PCONFIGURATION_TYPE ControllerType OPTIONAL,
    00074     IN PULONG ControllerNumber OPTIONAL,
    00075     IN PCONFIGURATION_TYPE PeripheralType OPTIONAL,
    00076     IN PULONG PeripheralNumber OPTIONAL,
    00077     IN PIO_QUERY_DEVICE_ROUTINE CalloutRoutine,
    00078     IN PVOID Context
    00079     )
    00080
    00081 /*++
    00082
    00083 Routine Description:
    00084
    00085
    00086 Arguments:
    00087
    00088     BusType - Supplies an optional bus type being searched for in the
    00089         description tree. Valid types are Mca, Isa, Eisa ... If no bus type
    00090         is specified, the system information (i.e. machine BIOS) is returned.
    00091
    00092     BusNumber - Supplies an optional value determining which bus should be
    00093         queried.
    00094
    00095     ControllerType - Supplies an optional controller type being searched for.
    00096         If no Controller type is specified, only the Bus information is
    00097         returned.
    00098
    00099     ControllerNumber - Supplies an optional value determining which
    00100         controller should be queried.
    00101
    00102     PeripheralType - Supplies an optional peripheral type being searched for.
    00103         If no Controller type is specified, only the Bus information and the
    00104         controller information are returned.
    00105
    00106     PeripheralNumber - Supplies an optional value determining which
    00107         peripheral should be queried.
    00108
    00109     CalloutRoutine - Supplies a pointer to a routine that gets called
    00110        for each successful match of PeripheralType.
    00111
    00112     Context - Supplies a context value that is passed back to the callback
    00113         routine.
    00114
    00115 Return Value:
    00116
    00117     The status returned is the final completion status of the operation.
    00118
    00119 Notes:
    00120
    00121 --*/
    00122
    00123 {
    00124
    00125 #define UNICODE_NUM_LENGTH 14
    00126 #define UNICODE_REGISTRY_PATH_LENGTH 1024
    00127
    00128     IO_QUERY_DESC queryDesc;
    00129
    00130     NTSTATUS status;
    00131     UNICODE_STRING registryPathName;
    00132     HANDLE rootHandle;
    00133     ULONG busNumber = (ULONG) -1;
    00134
    00135
    00136     PAGED_CODE();
    00137
    00138     ASSERT( CalloutRoutine != NULL );
    00139
    00140     //
    00141     // Check if we need to return the machine information
    00142     //
    00143
    00144     if (!ARGUMENT_PRESENT( BusType )) {
    00145         return STATUS_NOT_IMPLEMENTED;
    00146     }
    00147
    00148     queryDesc.BusType = BusType;
    00149     queryDesc.BusNumber = BusNumber;
    00150     queryDesc.ControllerType = ControllerType;
    00151     queryDesc.ControllerNumber = ControllerNumber;
    00152     queryDesc.PeripheralType = PeripheralType;
    00153     queryDesc.PeripheralNumber = PeripheralNumber;
    00154     queryDesc.CalloutRoutine = CalloutRoutine;
    00155     queryDesc.Context = Context;
    00156
    00157
    00158     //
    00159     // Set up a string with the pathname to the hardware description
    00160     // portion of the registry.
    00161     //
    00162
    00163     registryPathName.Length = 0;
    00164     registryPathName.MaximumLength = UNICODE_REGISTRY_PATH_LENGTH *
    00165                                      sizeof(WCHAR);
    00166
    00167     registryPathName.Buffer = ExAllocatePoolWithTag( PagedPool,
    00168                                                      UNICODE_REGISTRY_PATH_LENGTH,
    00169                                                      'mNoI' );
    00170
    00171     if (!registryPathName.Buffer) {
    00172
    00173         return STATUS_INSUFFICIENT_RESOURCES;
    00174
    00175     }
    00176
    00177     RtlAppendUnicodeStringToString( &registryPathName,
    00178                                     &CmRegistryMachineHardwareDescriptionSystemName );
    00179
    00180
    00181     //
    00182     // Open a handle to the root path we have.
    00183     //
    00184
    00185     status = IopOpenRegistryKey( &rootHandle,
    00186                                  (HANDLE) NULL,
    00187                                  &registryPathName,
    00188                                  KEY_READ,
    00189                                  FALSE );
    00190
    00191     if (NT_SUCCESS( status )) {
    00192
    00193         status = pIoQueryBusDescription(&queryDesc,
    00194                                         registryPathName,
    00195                                         rootHandle,
    00196                                         &busNumber,
    00197                                         TRUE );
    00198
    00199         ZwClose( rootHandle );
    00200
    00201     }
    00202
    00203     ExFreePool( registryPathName.Buffer );
    00204
    00205     //
    00206     // For compatibility with old version of the function.
    00207     //
    00208
    00209     if (status == STATUS_NO_MORE_ENTRIES) {
    00210
    00211         return STATUS_OBJECT_NAME_NOT_FOUND;
    00212
    00213
    00214     } else {
    00215
    00216         return status;
    00217
    00218     }
    00219 }
    00220
    00221
    00222 NTSTATUS
    00223 pIoQueryBusDescription(
    00224     PIO_QUERY_DESC QueryDescription,
    00225     UNICODE_STRING PathName,
    00226     HANDLE RootHandle,
    00227     PULONG BusNum,
    00228     BOOLEAN HighKey
    00229     )
    00230
    00231 /*++
    00232
    00233 Routine Description:
    00234
    00235
    00236 Arguments:
    00237
    00238     QueryDescription - Buffer containing all the query information requested
    00239         by the driver.
    00240
    00241     PathName - Registry path name of the key we are dealing with.  This is
    00242         a unicode strig so that we don't have to bother with resetting NULLs
    00243         at the end of the string - the length determines how much of the
    00244         string is valid.
    00245
    00246     RootHandle - Handle equivalent to the registry path.
    00247
    00248     BusNum - Pointer to a variable that keeps track of the bus number we are
    00249         searching for (buses have to be accumulated.
    00250
    00251     HighKey - Determines is this is a high key (a root key with a list of
    00252         bus types) or a low level key (under which the number of the various
    00253         buses will be little).
    00254
    00255 Return Value:
    00256
    00257     The status returned is the final completion status of the operation.
    00258
    00259 Notes:
    00260
    00261 --*/
    00262
    00263 {
    00264     NTSTATUS status;
    00265     ULONG i;
    00266     UNICODE_STRING unicodeString;
    00267
    00268     UNICODE_STRING registryPathName;
    00269
    00270     ULONG keyBasicInformationSize;
    00271     PKEY_BASIC_INFORMATION keyBasicInformation = NULL;
    00272     HANDLE handle;
    00273
    00274     PKEY_FULL_INFORMATION keyInformation;
    00275     ULONG size;
    00276
    00277     PKEY_VALUE_FULL_INFORMATION busValueInfo[IoQueryDeviceMaxData];
    00278
    00279
    00280     PAGED_CODE();
    00281
    00282     status = IopGetRegistryKeyInformation( RootHandle,
    00283                                            &keyInformation );
    00284
    00285     if (NT_SUCCESS( status )) {
    00286
    00287         //
    00288         // With the keyInformation, allocate a buffer that will be large
    00289         // enough for all the subkeys
    00290         //
    00291
    00292         keyBasicInformationSize = keyInformation->MaxNameLen +
    00293                                   sizeof(KEY_NODE_INFORMATION);
    00294
    00295         keyBasicInformation = ExAllocatePoolWithTag( PagedPool,
    00296                                                      keyBasicInformationSize,
    00297                                                      'mNoI' );
    00298
    00299         ExFreePool(keyInformation);
    00300
    00301         if (keyBasicInformation == NULL) {
    00302
    00303             return STATUS_INSUFFICIENT_RESOURCES;
    00304
    00305         }
    00306     }
    00307
    00308     //
    00309     // Now we need to enumerate the keys and see if one of them is a bus
    00310     //
    00311
    00312     for (i = 0; NT_SUCCESS( status ); i++) {
    00313
    00314
    00315         //
    00316         // If we have found the Bus we are looking for, break
    00317         //
    00318
    00319         if ((ARGUMENT_PRESENT( QueryDescription->BusNumber )) &&
    00320             (*(QueryDescription->BusNumber) == *BusNum)) {
    00321
    00322             break;
    00323
    00324         }
    00325
    00326         status = ZwEnumerateKey( RootHandle,
    00327                                  i,
    00328                                  KeyBasicInformation,
    00329                                  keyBasicInformation,
    00330                                  keyBasicInformationSize,
    00331                                  &size );
    00332
    00333         //
    00334         // If the sub function enumerated all the buses till the end, then
    00335         // treat that as success.
    00336         //
    00337
    00338         if (!NT_SUCCESS( status )) {
    00339
    00340             break;
    00341
    00342         }
    00343
    00344         //
    00345         // Only if this is a high key (otherwise we are in the callback
    00346         // pass which we will process later on).
    00347         //
    00348         // If the string is any valid bus string, then we have to go down
    00349         // the tree recursively.
    00350         // Otherwise, go on to the next key.
    00351         //
    00352
    00353         if (HighKey) {
    00354
    00355             if (wcsncmp( keyBasicInformation->Name,
    00356                          CmTypeString[MultiFunctionAdapter],
    00357                          keyBasicInformation->NameLength / sizeof(WCHAR) )  &&
    00358                 wcsncmp( keyBasicInformation->Name,
    00359                          CmTypeString[EisaAdapter],
    00360                          keyBasicInformation->NameLength / sizeof(WCHAR) )  &&
    00361                 wcsncmp( keyBasicInformation->Name,
    00362                          CmTypeString[TcAdapter],
    00363                          keyBasicInformation->NameLength / sizeof(WCHAR) )) {
    00364
    00365                 //
    00366                 // All the comparisons returned 1 (which means they all were
    00367                 // unsuccessful) so we do not have a bus.
    00368                 //
    00369                 // Go on to the next key.
    00370                 //
    00371
    00372                 continue;
    00373             }
    00374         }
    00375
    00376         //
    00377         // We have a bus. Open that key and enumerate it's clidren
    00378         // (which should be numbers)
    00379         //
    00380
    00381         unicodeString.Buffer = keyBasicInformation->Name;
    00382         unicodeString.Length = (USHORT) keyBasicInformation->NameLength;
    00383         unicodeString.MaximumLength = (USHORT) keyBasicInformation->NameLength;
    00384
    00385         if (!NT_SUCCESS( IopOpenRegistryKey( &handle,
    00386                                              RootHandle,
    00387                                              &unicodeString,
    00388                                              KEY_READ,
    00389                                              FALSE ) )) {
    00390
    00391             //
    00392             // The key could not be opened. Go to the next key
    00393             //
    00394
    00395             continue;
    00396
    00397         }
    00398
    00399         //
    00400         // We have the key. now build the name for this path.
    00401         //
    00402         // Reset the string to its original value
    00403         //
    00404
    00405         registryPathName = PathName;
    00406
    00407         RtlAppendUnicodeToString( &registryPathName,
    00408                                   L"\\" );
    00409
    00410         RtlAppendUnicodeStringToString( &registryPathName,
    00411                                         &unicodeString );
    00412
    00413
    00414         if (!HighKey) {
    00415
    00416             //
    00417             // We have a Key. Get the information for that key
    00418             //
    00419
    00420             status = IopGetRegistryValues( handle,
    00421                                            &busValueInfo[0] );
    00422
    00423             if (NT_SUCCESS( status )) {
    00424
    00425                 //
    00426                 // Verify that the identifier value for this bus
    00427                 // sub-key matches the user-specified bus type.
    00428                 // If not, do not increment the number of *found*
    00429                 // buses.
    00430                 //
    00431
    00432                 if (( busValueInfo[IoQueryDeviceConfigurationData] != NULL ) &&
    00433                     ( busValueInfo[IoQueryDeviceConfigurationData]->DataLength != 0 ) &&
    00434                     ( ((PCM_FULL_RESOURCE_DESCRIPTOR)
    00435                         ((PCCHAR) busValueInfo[IoQueryDeviceConfigurationData] +
    00436                         busValueInfo[IoQueryDeviceConfigurationData]->DataOffset))
    00437                         ->InterfaceType == *(QueryDescription->BusType) )) {
    00438
    00439                     //
    00440                     // Increment the number of buses of desired type we
    00441                     // have found.
    00442                     //
    00443
    00444                     (*BusNum)++;
    00445
    00446                     //
    00447                     // If we are looking for a specific bus number,
    00448                     // check to see if we are at the right number.
    00449                     // If we are not goto the next bus.  Otherwise
    00450                     // (i.e we have the right bus number, or we
    00451                     // specified all buses), then go on so the
    00452                     // information can be reported.
    00453                     //
    00454
    00455                     if ( (QueryDescription->BusNumber == NULL) ||
    00456                          (*(QueryDescription->BusNumber) == *BusNum) ) {
    00457
    00458
    00459                         //
    00460                         // If we want controller information, call
    00461                         // the controller function.
    00462                         // Otherwise just return the bus information.
    00463                         //
    00464
    00465                         if (QueryDescription->ControllerType != NULL) {
    00466
    00467                             status = pIoQueryDeviceDescription(
    00468                                          QueryDescription,
    00469                                          registryPathName,
    00470                                          handle,
    00471                                          *BusNum,
    00472                                          (PKEY_VALUE_FULL_INFORMATION *) busValueInfo );
    00473
    00474                         } else {
    00475
    00476                             status = QueryDescription->CalloutRoutine(
    00477                                          QueryDescription->Context,
    00478                                          &registryPathName,
    00479                                          *(QueryDescription->BusType),
    00480                                          *BusNum,
    00481                                          (PKEY_VALUE_FULL_INFORMATION *) busValueInfo,
    00482                                          0,
    00483                                          0,
    00484                                          NULL,
    00485                                          0,
    00486                                          0,
    00487                                          NULL );
    00488
    00489                         }
    00490                     }
    00491                 }
    00492
    00493                 //
    00494                 // Free the pool allocated for the controller value data.
    00495                 //
    00496
    00497                 if (busValueInfo[0]) {
    00498                     ExFreePool( busValueInfo[0] );
    00499                     busValueInfo[0] = NULL;
    00500                 }
    00501                 if (busValueInfo[1]) {
    00502                     ExFreePool( busValueInfo[1] );
    00503                     busValueInfo[1] = NULL;
    00504                 }
    00505                 if (busValueInfo[2]) {
    00506                     ExFreePool( busValueInfo[2] );
    00507                     busValueInfo[2] = NULL;
    00508                 }
    00509
    00510             }
    00511
    00512
    00513             //
    00514             // Shortcurt exit to avoid the recursive call.
    00515             //
    00516
    00517             if ((QueryDescription->BusNumber !=NULL ) &&
    00518                 (*(QueryDescription->BusNumber) == *BusNum)) {
    00519                 ZwClose( handle );
    00520                 handle = NULL;
    00521                 continue;
    00522
    00523             }
    00524         }
    00525
    00526         //
    00527         // If we have the key handle, do recursive enumeration.
    00528         // enumaration (for both high and low keys)
    00529         //
    00530
    00531         status = pIoQueryBusDescription(
    00532                      QueryDescription,
    00533                      registryPathName,
    00534                      handle,
    00535                      BusNum,
    00536                      (BOOLEAN)!HighKey );
    00537
    00538         //
    00539         // If the sub function enumerated all the buses till the end, then
    00540         // treat that as success.
    00541         //
    00542
    00543         if (status == STATUS_NO_MORE_ENTRIES) {
    00544
    00545             status = STATUS_SUCCESS;
    00546
    00547         }
    00548
    00549         ZwClose( handle );
    00550         handle = NULL;
    00551
    00552     }
    00553
    00554     if (keyBasicInformation) {
    00555         ExFreePool( keyBasicInformation );
    00556     }
    00557
    00558     return status;
    00559 }
    00560
    00561
    00562
    00563
    00564 NTSTATUS
    00565 pIoQueryDeviceDescription(
    00566     PIO_QUERY_DESC QueryDescription,
    00567     UNICODE_STRING PathName,
    00568     HANDLE RootHandle,
    00569     ULONG BusNum,
    00570     PKEY_VALUE_FULL_INFORMATION *BusValueInfo
    00571     )
    00572
    00573 {
    00574
    00575     NTSTATUS status;
    00576     UNICODE_STRING registryPathName = PathName;
    00577     UNICODE_STRING controllerBackupRegistryPathName;
    00578     UNICODE_STRING peripheralBackupRegistryPathName;
    00579     HANDLE controllerHandle = NULL;
    00580     HANDLE peripheralHandle = NULL;
    00581     PKEY_FULL_INFORMATION controllerTypeInfo = NULL;
    00582     PKEY_FULL_INFORMATION peripheralTypeInfo = NULL;
    00583     ULONG maxControllerNum;
    00584     ULONG maxPeripheralNum;
    00585     ULONG controllerNum;
    00586     ULONG peripheralNum;
    00587     WCHAR numBuffer[UNICODE_NUM_LENGTH];
    00588     UNICODE_STRING bufferUnicodeString;
    00589     PKEY_VALUE_FULL_INFORMATION controllerValueInfo[IoQueryDeviceMaxData];
    00590     PKEY_VALUE_FULL_INFORMATION peripheralValueInfo[IoQueryDeviceMaxData];
    00591
    00592
    00593     //
    00594     // Set up a string for the number translation.
    00595     //
    00596
    00597     bufferUnicodeString.MaximumLength = UNICODE_NUM_LENGTH * sizeof(WCHAR);
    00598     bufferUnicodeString.Buffer = &numBuffer[0];
    00599
    00600
    00601     //         For each controller of the specified type (subkeys 0..M)
    00602     //             if we are looking for controller information
    00603     //                 call the specified callout routine
    00604     //             else
    00605     //                 For each peripheral of the specified type (subkeys 0..N)
    00606     //                     call the specified callout routine
    00607
    00608     //
    00609     // Add the controller name to the registry path name.
    00610     //
    00611
    00612     status = RtlAppendUnicodeToString( &registryPathName,
    00613                                        L"\\" );
    00614
    00615     if (NT_SUCCESS( status )) {
    00616
    00617         status = RtlAppendUnicodeToString( &registryPathName,
    00618                                            CmTypeString[*(QueryDescription->ControllerType)] );
    00619
    00620     }
    00621
    00622     if (!NT_SUCCESS( status )) {
    00623         return status;
    00624     }
    00625
    00626     //
    00627     // If a Contoller number was specified by the caller, use that
    00628     // controller number. Otherwise, find out how many buses are present
    00629     // by querying the key.
    00630     //
    00631
    00632     if (ARGUMENT_PRESENT( QueryDescription->ControllerNumber )) {
    00633
    00634         controllerNum = *(QueryDescription->ControllerNumber);
    00635         maxControllerNum = controllerNum + 1;
    00636
    00637     } else {
    00638
    00639         //
    00640         // Open the registry key for the controller and
    00641         // Get the full key information for the controller key to
    00642         // determine the number of sub-keys (controller numbers).
    00643         // And we fail, then go on to the next bus.
    00644         // Note the memory allocated by the query must be freed.
    00645         //
    00646
    00647         status = IopOpenRegistryKey( &controllerHandle,
    00648                                      (HANDLE) NULL,
    00649                                      &registryPathName,
    00650                                      KEY_READ,
    00651                                      FALSE );
    00652
    00653         if (NT_SUCCESS( status )) {
    00654
    00655             status = IopGetRegistryKeyInformation( controllerHandle,
    00656                                                    &controllerTypeInfo );
    00657
    00658             ZwClose( controllerHandle );
    00659             controllerHandle = NULL;
    00660         }
    00661
    00662         //
    00663         // If no controller of this type was found on the bus, go on to
    00664         // the next bus; goto the end of the loop with a successful status
    00665         // so that the memory gets freed, but we continue looping.
    00666         //
    00667
    00668         if (!NT_SUCCESS( status )) {
    00669
    00670             return status;
    00671
    00672         }
    00673
    00674         //
    00675         // Get the number of controller sub-keys for this controller
    00676         // type and free the pool.
    00677         //
    00678
    00679         maxControllerNum = controllerTypeInfo->SubKeys;
    00680         controllerNum = 0;
    00681
    00682         ExFreePool( controllerTypeInfo );
    00683         controllerTypeInfo = NULL;
    00684     }
    00685
    00686     //
    00687     // Make a backup of the string since we want to start where we were
    00688     // on the next loop iteration.
    00689     //
    00690
    00691     controllerBackupRegistryPathName = registryPathName;
    00692
    00693     //
    00694     // For each controller of the specified type (subkeys 0..M).
    00695     // We use BusNumber as the initial value since it is zero if we want
    00696     // all buses, and we only want the bus specified if the value  is not
    00697     // zero.
    00698     //
    00699
    00700     for ( ; controllerNum < maxControllerNum; controllerNum++) {
    00701
    00702         //
    00703         // Reset the string to its original value
    00704         //
    00705
    00706         registryPathName = controllerBackupRegistryPathName;
    00707
    00708         //
    00709         // Convert the controller number to a unicode string and append
    00710         // it to the registry path name.
    00711         //
    00712
    00713         bufferUnicodeString.Length = (UNICODE_NUM_LENGTH-1) * sizeof(WCHAR);
    00714         status = RtlIntegerToUnicodeString( controllerNum,
    00715                                             10,
    00716                                             &bufferUnicodeString );
    00717
    00718         if (NT_SUCCESS( status )) {
    00719
    00720             status = RtlAppendUnicodeToString( &registryPathName,
    00721                                                L"\\" );
    00722
    00723             if (NT_SUCCESS( status )) {
    00724
    00725                 status = RtlAppendUnicodeStringToString(
    00726                                                      &registryPathName,
    00727                                                      &bufferUnicodeString );
    00728
    00729             }
    00730         }
    00731
    00732         if (!NT_SUCCESS( status )) {
    00733             break;
    00734         }
    00735
    00736         //
    00737         // Open the registry key for the controller number and
    00738         // Get the value data for this controller and save it for later.
    00739         //
    00740
    00741
    00742         status = IopOpenRegistryKey( &controllerHandle,
    00743                                      (HANDLE) NULL,
    00744                                      &registryPathName,
    00745                                      KEY_READ,
    00746                                      FALSE );
    00747
    00748         if (NT_SUCCESS( status )) {
    00749
    00750             status = IopGetRegistryValues( controllerHandle,
    00751                                            &controllerValueInfo[0] );
    00752
    00753             ZwClose( controllerHandle );
    00754             controllerHandle = NULL;
    00755         }
    00756
    00757         //
    00758         // If we could not open the key and get the info, just continue
    00759         // since there is no memory to free and we are using the for
    00760         // loop to determine when we get to the last controller.
    00761         //
    00762
    00763         if (!NT_SUCCESS( status )) {
    00764             continue;
    00765         }
    00766
    00767         //
    00768         // Check if we want the controller and bus information only. If
    00769         // it is the case, invoque the callout routine and go on to the
    00770         // next loop (unless an error occurs in the callout).
    00771         //
    00772
    00773         if (!ARGUMENT_PRESENT( (QueryDescription->PeripheralType) )) {
    00774
    00775             status = QueryDescription->CalloutRoutine(
    00776                          QueryDescription->Context,
    00777                          &registryPathName,
    00778                          *(QueryDescription->BusType),
    00779                          BusNum,
    00780                          BusValueInfo,
    00781                          *(QueryDescription->ControllerType),
    00782                          controllerNum,
    00783                          (PKEY_VALUE_FULL_INFORMATION *) controllerValueInfo,
    00784                          0,
    00785                          0,
    00786                          NULL );
    00787
    00788             goto IoQueryDeviceControllerLoop;
    00789         }
    00790
    00791         //
    00792         // Add the peripheral name to the registry path name.
    00793         //
    00794
    00795         status = RtlAppendUnicodeToString( &registryPathName,
    00796                                            L"\\" );
    00797
    00798         if (NT_SUCCESS( status )) {
    00799
    00800             status = RtlAppendUnicodeToString(
    00801                                              &registryPathName,
    00802                                              CmTypeString[*(QueryDescription->PeripheralType)] );
    00803
    00804         }
    00805
    00806         if (!NT_SUCCESS( status )) {
    00807             goto IoQueryDeviceControllerLoop;
    00808         }
    00809
    00810         //
    00811         // If a Peripheralnumber was specified by the caller, use that
    00812         // peripheral number. Otherwise, find out how many buses are
    00813         // present by querying the key.
    00814         //
    00815
    00816         if (ARGUMENT_PRESENT( (QueryDescription->PeripheralNumber) )) {
    00817
    00818             peripheralNum = *(QueryDescription->PeripheralNumber);
    00819             maxPeripheralNum = peripheralNum + 1;
    00820
    00821         } else {
    00822
    00823             //
    00824             // Open the registry key for the peripheral and
    00825             // Get the full key information for the peripheral key to
    00826             // determine the number of sub-keys (peripheral numbers).
    00827             // And we fail, then go on to the next controller.
    00828             // Note the memory allocated by the query must be freed.
    00829             //
    00830
    00831             status = IopOpenRegistryKey( &peripheralHandle,
    00832                                          (HANDLE) NULL,
    00833                                          &registryPathName,
    00834                      KEY_READ,
    00835                      FALSE );
    00836
    00837             if (NT_SUCCESS( status )) {
    00838
    00839                 status = IopGetRegistryKeyInformation( peripheralHandle,
    00840                            &peripheralTypeInfo );
    00841
    00842                 ZwClose( peripheralHandle );
    00843                 peripheralHandle = NULL;
    00844             }
    00845
    00846             //
    00847             // If no controller of this type was found on the bus, go on to
    00848             // the next bus; goto the end of the loop with a successful
    00849             // status so that the memory gets freed, but we continue looping.
    00850             //
    00851
    00852             if (!NT_SUCCESS( status )) {
    00853                 status = STATUS_SUCCESS;
    00854                 goto IoQueryDeviceControllerLoop;
    00855             }
    00856
    00857             //
    00858             // Get the number of peripheral sub-keys for this peripheral
    00859             // type and free the pool.
    00860             //
    00861
    00862             maxPeripheralNum = peripheralTypeInfo->SubKeys;
    00863             peripheralNum = 0;
    00864
    00865             ExFreePool( peripheralTypeInfo );
    00866             peripheralTypeInfo = NULL;
    00867         }
    00868
    00869         //
    00870         // Make a backup of the string since we want to start where we
    00871         // were on the next loop iteration.
    00872         //
    00873
    00874         peripheralBackupRegistryPathName = registryPathName;
    00875
    00876         //
    00877         // For each peripheral of the specified type (subkeys 0..N).
    00878         // We use BusNumber as the initial value since it is zero if we
    00879         // want all buses, and we only want the bus specified if the
    00880         // value is not zero.
    00881         //
    00882
    00883         for ( ; peripheralNum < maxPeripheralNum; peripheralNum++) {
    00884
    00885             //
    00886             // Reset the string to its original value.
    00887             //
    00888
    00889             registryPathName = peripheralBackupRegistryPathName;
    00890
    00891             //
    00892             // Convert the peripheral number to a unicode string and append
    00893             // it to the registry path name.
    00894             //
    00895
    00896             bufferUnicodeString.Length =
    00897                 (UNICODE_NUM_LENGTH-1) * sizeof(WCHAR);
    00898             status = RtlIntegerToUnicodeString( peripheralNum,
    00899                                                 10,
    00900                                                 &bufferUnicodeString );
    00901
    00902             if (NT_SUCCESS( status )) {
    00903
    00904                 status = RtlAppendUnicodeToString( &registryPathName,
    00905                                                    L"\\" );
    00906
    00907                 if (NT_SUCCESS( status )) {
    00908
    00909                     status = RtlAppendUnicodeStringToString(
    00910                                                      &registryPathName,
    00911                                                      &bufferUnicodeString );
    00912
    00913                 }
    00914             }
    00915
    00916             if (!NT_SUCCESS( status )) {
    00917                 break;
    00918             }
    00919
    00920             //
    00921             // Open the registry key for the peripheral number and
    00922             // Get the value data for this peripheral and save it for
    00923             // later.
    00924             //
    00925
    00926             status = IopOpenRegistryKey( &peripheralHandle,
    00927                                          (HANDLE) NULL,
    00928                                          &registryPathName,
    00929                                          KEY_READ,
    00930                                          FALSE );
    00931
    00932             if (NT_SUCCESS( status )) {
    00933
    00934                 status = IopGetRegistryValues( peripheralHandle,
    00935                                                &peripheralValueInfo[0] );
    00936
    00937                 ZwClose( peripheralHandle );
    00938                 peripheralHandle = NULL;
    00939             }
    00940
    00941             //
    00942             // If getting the peripheral information worked properly,
    00943             // call the user-specified callout routine.
    00944             //
    00945
    00946             if (NT_SUCCESS( status )) {
    00947
    00948                 status = QueryDescription->CalloutRoutine(
    00949                              QueryDescription->Context,
    00950                              &registryPathName,
    00951                              *(QueryDescription->BusType),
    00952                              BusNum,
    00953                              BusValueInfo,
    00954                              *(QueryDescription->ControllerType),
    00955                              controllerNum,
    00956                              (PKEY_VALUE_FULL_INFORMATION *) controllerValueInfo,
    00957                              *(QueryDescription->PeripheralType),
    00958                              peripheralNum,
    00959                              (PKEY_VALUE_FULL_INFORMATION *) peripheralValueInfo );
    00960
    00961                 //
    00962                 // Free the pool allocated for the peripheral value data.
    00963                 //
    00964
    00965                 if (peripheralValueInfo[0]) {
    00966                     ExFreePool( peripheralValueInfo[0] );
    00967                     peripheralValueInfo[0] = NULL;
    00968                 }
    00969                 if (peripheralValueInfo[1]) {
    00970                     ExFreePool( peripheralValueInfo[1] );
    00971                     peripheralValueInfo[1] = NULL;
    00972                 }
    00973                 if (peripheralValueInfo[2]) {
    00974                     ExFreePool( peripheralValueInfo[2] );
    00975                     peripheralValueInfo[2] = NULL;
    00976                 }
    00977
    00978                 //
    00979                 // If the user-specified callout routine returned with
    00980                 // an unsuccessful status, quit.
    00981                 //
    00982
    00983                 if (!NT_SUCCESS( status )) {
    00984                     break;
    00985                }
    00986             }
    00987
    00988         } // for ( ; peripheralNum < maxPeripheralNum ...
    00989
    00990 IoQueryDeviceControllerLoop:
    00991
    00992         //
    00993         // Free the pool allocated for the controller value data.
    00994         //
    00995
    00996         if (controllerValueInfo[0]) {
    00997             ExFreePool( controllerValueInfo[0] );
    00998             controllerValueInfo[0] = NULL;
    00999         }
    01000         if (controllerValueInfo[1]) {
    01001             ExFreePool( controllerValueInfo[1] );
    01002             controllerValueInfo[1] = NULL;
    01003         }
    01004         if (controllerValueInfo[2]) {
    01005             ExFreePool( controllerValueInfo[2] );
    01006             controllerValueInfo[2] = NULL;
    01007         }
    01008
    01009         if (!NT_SUCCESS( status )) {
    01010             break;
    01011         }
    01012
    01013     } // for ( ; controllerNum < maxControllerNum...
    01014
    01015
    01016     return( status );
    01017 }
    01018