Annotation of ntddk/src/mmedia/synth/dll/registry.c, revision 1.1.1.1

1.1       root        1: /****************************************************************************
                      2:  *
                      3:  *   registry.c
                      4:  *
                      5:  *   Copyright (c) 1992 Microsoft Corporation.  All Rights Reserved.
                      6:  *
                      7:  *   This file contains functions to maintain registry entries for
                      8:  *   kernel drivers installed via the drivers control panel applet.
                      9:  *
                     10:  *   Note that the ONLY state maintained between calls here is whatever
                     11:  *   state the registry and its handles maintain.
                     12:  *
                     13:  *   The registry entries are structured as follows :
                     14:  *   (see also winreg.h, winnt.h)
                     15:  *
                     16:  *   HKEY_LOCAL_MACHINE
                     17:  *       SYSTEM
                     18:  *           CurrentControlSet
                     19:  *               Services
                     20:  *                   DriverNode      (eg sndblst)
                     21:  *                           Type         = SERVICE_KERNEL_DRIVER (eg)
                     22:  *                           Group        = "Base"
                     23:  *                           ErrorControl = SERVICE_ERROR_NORMAL
                     24:  *                           Start        = SERVICE_SYSTEM_START |
                     25:  *                                          SERVICE_DEMAND_START |
                     26:  *                                          SERVICE_DISABLED
                     27:  *                                          ...
                     28:  *                           Tag          = A unique number ???
                     29:  *
                     30:  *                        Device
                     31:  *                                Interrupt  =
                     32:  *                                Port       =
                     33:  *                                DMAChannel =
                     34:  *
                     35:  *   The Driver node is set up by the services manager when we call
                     36:  *   CreateService but we have to insert the device data ourselves.
                     37:  *
                     38:  *
                     39:  *
                     40:  *   The registry entries are shared between :
                     41:  *
                     42:  *        The system loader (which uses the Services entry)
                     43:  *        The kernel driver (which reads from the Device entry)
                     44:  *        This component called from the drivers control panel applet
                     45:  *        The service control manager
                     46:  *        The Setup utility
                     47:  *
                     48:  *   Security access
                     49:  *   ---------------
                     50:  *
                     51:  *   The driver determines whether it can perform configuration and
                     52:  *   installation by whether it can get read and write access to the
                     53:  *   service control manager.  This is required to manipulate the kernel
                     54:  *   driver database.
                     55:  *
                     56:  *   Services controller
                     57:  *   -------------------
                     58:  *
                     59:  *   The services controller is used because this is the only way we
                     60:  *   are allowed to load and unload kernel drivers.  Only the services
                     61:  *   controller can call LoadDriver and UnloadDriver and not get 'access
                     62:  *   denied'.
                     63:  *
                     64:  *   Note also that we can't keep the services controller handle open
                     65:  *   at the same time as the registry handle because then we can't get
                     66:  *   write access (actually we only need KEY_CREATE_SUB_KEY access) to
                     67:  *   our device parameters subkey.
                     68:  *
                     69:  ***************************************************************************/
                     70: 
                     71:  #include <stdio.h>
                     72: #ifdef UNICODE
                     73:  #include <wchar.h>
                     74: #else
                     75:  #include <string.h>
                     76:  #define wcscat strcat
                     77:  #define wcscpy strcpy
                     78:  #define wcsicmp stricmp
                     79: #endif
                     80:  #include <windows.h>
                     81:  #include <mmsystem.h>
                     82:  #include <winsvc.h>
                     83:  #include <soundcfg.h>
                     84:  #include "registry.h"
                     85: 
                     86: /***************************************************************************
                     87:  *
                     88:  * Constants for accessing the registry
                     89:  *
                     90:  ***************************************************************************/
                     91: 
                     92:     /*
                     93:      *  Path to service node key
                     94:      */
                     95: 
                     96:      #define STR_SERVICES_NODE TEXT("SYSTEM\\CurrentControlSet\\Services\\")
                     97: 
                     98:     /*
                     99:      *  Node sub-key for device parameters
                    100:      */
                    101: 
                    102:      #define STR_DEVICE_DATA PARMS_SUBKEY
                    103: 
                    104:     /*
                    105:      *  Name of Base group where sound drivers normally go
                    106:      */
                    107: 
                    108:      #define STR_BASE_GROUP TEXT("Base")
                    109: 
                    110:     /*
                    111:      *  Name of driver group for synthesizers
                    112:      *     - we use our own name here to make sure
                    113:      *       we are loaded after things like the PAS driver.  (Base is a
                    114:      *       known group and drivers in it are always loaded before unknown
                    115:      *       groups like this one).
                    116:      */
                    117: 
                    118:      #define STR_SYNTH_GROUP TEXT("Synthesizer Drivers")
                    119: 
                    120:     /*
                    121:      *  Name of service
                    122:      */
                    123: 
                    124:      #define STR_DRIVER TEXT("\\Driver\\")
                    125: 
                    126:     /*
                    127:      *  Path to kernel drivers directory from system directory
                    128:      */
                    129: 
                    130:      #define STR_DRIVERS_DIR TEXT("\\SystemRoot\\SYSTEM32\\DRIVERS\\")
                    131: 
                    132:     /*
                    133:      *  Extension for drivers
                    134:      */
                    135: 
                    136:      #define STR_SYS_EXT TEXT(".SYS")
                    137: 
                    138: 
                    139:  HKEY DrvOpenRegKey(LPTSTR DriverName)
                    140:  {
                    141:      TCHAR RegistryPath[MAX_PATH];
                    142:      HKEY NodeHandle;
                    143: 
                    144:      //
                    145:      // Create the path to our node
                    146:      //
                    147: 
                    148:      wcscpy(RegistryPath, STR_SERVICES_NODE);
                    149:      wcscat(RegistryPath, DriverName);
                    150: 
                    151:      //
                    152:      // See if we can get a registry handle to our device data
                    153:      //
                    154: 
                    155: 
                    156:      if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                    157:                       RegistryPath,
                    158:                       0L,
                    159:                       KEY_ALL_ACCESS,
                    160:                       &NodeHandle)
                    161:          != ERROR_SUCCESS) {
                    162:          return NULL;
                    163:      } else {
                    164:          return NodeHandle;
                    165:      }
                    166:  }
                    167: 
                    168: 
                    169:  SC_HANDLE DrvOpenService(PREG_ACCESS RegAccess)
                    170:  {
                    171:      SC_HANDLE Handle;
                    172:      Handle = OpenService(RegAccess->ServiceManagerHandle,
                    173:                           RegAccess->DriverName,
                    174:                           SERVICE_ALL_ACCESS);
                    175: 
                    176: #if 0
                    177:      if (Handle == NULL) {
                    178:          char buf[100];
                    179:          sprintf(buf, "OpenService failed code %d\n", GetLastError());
                    180:          OutputDebugStringA(buf);
                    181:      }
                    182: #endif
                    183: 
                    184:      return Handle;
                    185:  }
                    186: 
                    187:  void DrvCloseService(PREG_ACCESS RegAccess, SC_HANDLE ServiceHandle)
                    188:  {
                    189:      CloseServiceHandle(ServiceHandle);
                    190:  }
                    191: 
                    192: /***************************************************************************
                    193:  *
                    194:  *  Function :
                    195:  *      DrvCreateServicesNode
                    196:  *
                    197:  *  Parameters :
                    198:  *      DriverNodeName      The name of the service node.  Same as the
                    199:  *                          name of the driver which must be
                    200:  *                          DriverNodeName.sys for the system to find it.
                    201:  *
                    202:  *      DriverType          Type of driver - see registry.h
                    203:  *
                    204:  *      ServiceNodeKey      Pointer to where to put returned handle
                    205:  *
                    206:  *  Return code :
                    207:  *
                    208:  *      Standard error code (see winerror.h)
                    209:  *
                    210:  *  Description :
                    211:  *
                    212:  *      Create the service node key
                    213:  *
                    214:  *      The class name of the registry node is ""
                    215:  *
                    216:  ***************************************************************************/
                    217: 
                    218:  BOOL
                    219:  DrvCreateServicesNode(LPTSTR DriverName,
                    220:                        SOUND_KERNEL_MODE_DRIVER_TYPE DriverType,
                    221:                        PREG_ACCESS RegAccess,
                    222:                        BOOL Create)
                    223:  {
                    224:      SERVICE_STATUS ServiceStatus;
                    225:      SC_HANDLE ServiceHandle;                 // Handle to our driver 'service'
                    226: 
                    227:      RegAccess->DriverName = DriverName;
                    228: 
                    229:      //
                    230:      // See if we can open the registry
                    231:      //
                    232: 
                    233:      if (RegAccess->ServiceManagerHandle == NULL) {
                    234:          RegAccess->ServiceManagerHandle =
                    235:              OpenSCManager(
                    236:                  NULL,                        // This machine
                    237:                  NULL,                        // The active database
                    238:                  SC_MANAGER_ALL_ACCESS);      // We want to create and change
                    239: 
                    240:          if (RegAccess->ServiceManagerHandle == NULL) {
                    241:              return FALSE;
                    242:          }
                    243:      }
                    244: 
                    245:      //
                    246:      // Open our particular service
                    247:      //
                    248: 
                    249:      ServiceHandle = DrvOpenService(RegAccess);
                    250: 
                    251:      //
                    252:      // See if that worked
                    253:      //
                    254: 
                    255:      if (ServiceHandle == NULL &&
                    256:          GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) {
                    257:          if (Create) {
                    258:              SC_LOCK ServicesDatabaseLock;
                    259:              TCHAR ServiceName[MAX_PATH];
                    260:              TCHAR BinaryPath[MAX_PATH];
                    261: 
                    262:              wcscpy(BinaryPath, STR_DRIVERS_DIR);
                    263:              wcscat(BinaryPath, DriverName);
                    264:              wcscat(BinaryPath, STR_SYS_EXT);
                    265: 
                    266:              wcscpy(ServiceName, STR_DRIVER);
                    267:              wcscat(ServiceName, DriverName);
                    268: 
                    269:             /*
                    270:              *  Lock the service controller database to avoid deadlocks
                    271:              *  we have to loop because we can't wait
                    272:              */
                    273: 
                    274: 
                    275:              for (ServicesDatabaseLock = NULL;
                    276:                   (ServicesDatabaseLock =
                    277:                        LockServiceDatabase(RegAccess->ServiceManagerHandle))
                    278:                      == NULL;
                    279:                   Sleep(100)) {
                    280:              }
                    281: 
                    282: 
                    283:             /*
                    284:              *  Create the service
                    285:              */
                    286: 
                    287: 
                    288:              ServiceHandle =
                    289:                  CreateService(
                    290:                      RegAccess->ServiceManagerHandle,
                    291:                      DriverName,               // Service name
                    292:                      NULL,                     // ???
                    293:                      SERVICE_ALL_ACCESS,       // Full access
                    294:                      SERVICE_KERNEL_DRIVER,    // Kernel driver
                    295:                      SERVICE_DEMAND_START,     // Start at sys start
                    296:                      SERVICE_ERROR_NORMAL,     // Not a disaster if fails
                    297:                      BinaryPath,               // Default path
                    298: 
                    299:                      DriverType == SoundDriverTypeSynth ?
                    300:                          STR_SYNTH_GROUP :     // Driver group
                    301:                          STR_BASE_GROUP,
                    302:                      NULL,                     // do not want TAG information
                    303:                      TEXT("\0"),               // No dependencies
                    304:                      NULL, // ServiceName,              // Driver object - optional
                    305:                      NULL);                    // No password
                    306: 
                    307:              UnlockServiceDatabase(ServicesDatabaseLock);
                    308: #if DBG
                    309:              if (ServiceHandle == NULL) {
                    310:                  TCHAR buf[100];
                    311:                  wsprintf(buf, TEXT("CreateService failed code %d\n"), GetLastError());
                    312:                  OutputDebugString(buf);
                    313:              }
                    314: #endif
                    315: 
                    316:          }
                    317:      }
                    318: 
                    319:      //
                    320:      // Check at least that it's a device driver
                    321:      //
                    322: 
                    323:      if (ServiceHandle != NULL) {
                    324:          if (!QueryServiceStatus(
                    325:                  ServiceHandle,
                    326:                  &ServiceStatus) ||
                    327:              ServiceStatus.dwServiceType != SERVICE_KERNEL_DRIVER) {
                    328: 
                    329:              //
                    330:              // Doesn't look like ours
                    331:              //
                    332: 
                    333:              CloseServiceHandle(RegAccess->ServiceManagerHandle);
                    334:              RegAccess->ServiceManagerHandle = NULL;
                    335:              DrvCloseService(RegAccess, ServiceHandle);
                    336:              return FALSE;
                    337:          }
                    338: 
                    339:      }
                    340: 
                    341:      if (ServiceHandle == NULL) {
                    342:          //
                    343:          // Leave the SC manager  handle open.  We use the presence of this
                    344:          // handle to test whether the driver can be configured (ie whether we
                    345:          // have the access rights to get into the SC manager).
                    346:          //
                    347: 
                    348:          return FALSE;
                    349:      } else {
                    350:          //
                    351:          // We can't keep this handle open (even though we'd like to) because
                    352:          // we need write access to the registry node created so that
                    353:          // we can add device parameters
                    354:          //
                    355: 
                    356:          DrvCloseService(RegAccess, ServiceHandle);
                    357:          return TRUE;
                    358:      }
                    359:  }
                    360: 
                    361: 
                    362: /***************************************************************************
                    363:  *
                    364:  *  Function :
                    365:  *      DrvCloseServicesNode
                    366:  *
                    367:  *  Parameters :
                    368:  *      ServiceNodeKey
                    369:  *
                    370:  *  Return code :
                    371:  *
                    372:  *      Standard error code (see winerror.h)
                    373:  *
                    374:  *  Description :
                    375:  *
                    376:  *      Close our handle
                    377:  *
                    378:  ***************************************************************************/
                    379: 
                    380:  VOID
                    381:  DrvCloseServiceManager(
                    382:      PREG_ACCESS RegAccess)
                    383:  {
                    384:      if (RegAccess->ServiceManagerHandle != NULL) {
                    385:          CloseServiceHandle(RegAccess->ServiceManagerHandle);
                    386:          RegAccess->ServiceManagerHandle = NULL;
                    387:      }
                    388:  }
                    389: 
                    390: /***************************************************************************
                    391:  *
                    392:  *  Function :
                    393:  *      DrvDeleteServicesNode
                    394:  *
                    395:  *  Parameters :
                    396:  *      DeviceName
                    397:  *
                    398:  *  Return code :
                    399:  *
                    400:  *      TRUE = success, FALSE = failed
                    401:  *
                    402:  *  Description :
                    403:  *
                    404:  *      Delete our node using the handle proviced
                    405:  *
                    406:  ***************************************************************************/
                    407: 
                    408:  BOOL
                    409:  DrvDeleteServicesNode(
                    410:      PREG_ACCESS RegAccess)
                    411:  {
                    412:      BOOL Success;
                    413:      SC_LOCK ServicesDatabaseLock;
                    414:      SC_HANDLE ServiceHandle;
                    415:      HKEY NodeHandle;
                    416: 
                    417:      NodeHandle = DrvOpenRegKey(RegAccess->DriverName);
                    418: 
                    419:      //
                    420:      // Make sure we're not accessing the registry ourselves and
                    421:      // that there aren't any subkeys
                    422:      //
                    423: 
                    424:      if (NodeHandle) {
                    425:          RegDeleteKey(NodeHandle, STR_DEVICE_DATA);
                    426:          RegFlushKey(NodeHandle);
                    427:          RegCloseKey(NodeHandle);
                    428:      }
                    429: 
                    430:      //
                    431:      // Delete the service node and free tha handle
                    432:      // (Note the service cannot be deleted until all handles are closed)
                    433:      //
                    434: 
                    435:      ServiceHandle = DrvOpenService(RegAccess);
                    436: 
                    437:      if (ServiceHandle == NULL) {
                    438:          LONG Error;
                    439:          Error = GetLastError();
                    440:          if (Error == ERROR_SERVICE_DOES_NOT_EXIST) {
                    441:              //
                    442:              // It's already gone !
                    443:              //
                    444:              return TRUE;
                    445:          } else {
                    446:              return FALSE; // It was there but something went wrong
                    447:          }
                    448:      }
                    449: 
                    450:     /*
                    451:      *  Lock the service controller database to avoid deadlocks
                    452:      *  we have to loop because we can't wait
                    453:      */
                    454: 
                    455: 
                    456:      for (ServicesDatabaseLock = NULL;
                    457:           (ServicesDatabaseLock =
                    458:                LockServiceDatabase(RegAccess->ServiceManagerHandle))
                    459:              == NULL;
                    460:           Sleep(100)) {
                    461:      }
                    462: 
                    463:      Success = DeleteService(ServiceHandle);
                    464: 
                    465:      UnlockServiceDatabase(ServicesDatabaseLock);
                    466: 
                    467:      DrvCloseService(RegAccess, ServiceHandle);
                    468: 
                    469:      return Success;
                    470:  }
                    471: 
                    472: 
                    473: /***************************************************************************
                    474:  *
                    475:  *  Function :
                    476:  *      DrvSetDeviceParameter
                    477:  *
                    478:  *  Parameters :
                    479:  *      ServiceNodeKey       Handle to the device services node key
                    480:  *      ValueName            Name of value to set
                    481:  *      Value                DWORD value to set
                    482:  *
                    483:  *  Return code :
                    484:  *
                    485:  *      Standard error code (see winerror.h)
                    486:  *
                    487:  *  Description :
                    488:  *
                    489:  *      Add the value to the device parameters section under the
                    490:  *      services node.
                    491:  *      This section is created if it does not already exist.
                    492:  *
                    493:  ***************************************************************************/
                    494: 
                    495:  LONG
                    496:  DrvSetDeviceParameter(
                    497:      PREG_ACCESS RegAccess,
                    498:      LPTSTR ValueName,
                    499:      DWORD Value)
                    500:  {
                    501:      HKEY ServiceNodeKey;
                    502:      HKEY ParmsKey;
                    503:      LONG ReturnCode;
                    504: 
                    505:      ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName);
                    506: 
                    507:      if (ServiceNodeKey == NULL) {
                    508:          return ERROR_FILE_NOT_FOUND;
                    509:      }
                    510: 
                    511:      //
                    512:      // First try to get a handle to the parameters subkey - which may
                    513:      // involve creating the subkey
                    514:      //
                    515: 
                    516:      ReturnCode = RegCreateKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey);
                    517: 
                    518:      RegCloseKey(ServiceNodeKey);
                    519: 
                    520:      if (ReturnCode != ERROR_SUCCESS) {
                    521:          return ReturnCode;
                    522:      }
                    523: 
                    524:      //
                    525:      // Write the value
                    526:      //
                    527: 
                    528: 
                    529:      ReturnCode = RegSetValueEx(ParmsKey,             // Registry handle
                    530:                                 ValueName,            // Name of item
                    531:                                 0,                    // Reserved 0
                    532:                                 REG_DWORD,            // Data type
                    533:                                 (LPBYTE)&Value,       // The value
                    534:                                 sizeof(Value));       // Data length
                    535: 
                    536:      //
                    537:      // Free the handles we created
                    538:      //
                    539: 
                    540:      RegCloseKey(ParmsKey);
                    541: 
                    542:      return ReturnCode;
                    543:  }
                    544: 
                    545: /***************************************************************************
                    546:  *
                    547:  *  Function :
                    548:  *      DrvCreateParamsKey
                    549:  *
                    550:  *  Parameters :
                    551:  *      RegAccess       Registry access info
                    552:  *
                    553:  *  Return code :
                    554:  *
                    555:  *      Standard error code (see winerror.h)
                    556:  *
                    557:  *  Description :
                    558:  *
                    559:  *      Create the device parameters section under the
                    560:  *      services node if it does not already exist. No values are
                    561:  *  written to the key.
                    562:  *
                    563:  ***************************************************************************/
                    564: 
                    565:  LONG
                    566:  DrvCreateParamsKey(
                    567:      PREG_ACCESS RegAccess)
                    568:  {
                    569:      HKEY ServiceNodeKey;
                    570:      HKEY ParmsKey;
                    571:      LONG ReturnCode;
                    572: 
                    573:      ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName);
                    574: 
                    575:      if (ServiceNodeKey == NULL) {
                    576:          return ERROR_FILE_NOT_FOUND;
                    577:      }
                    578: 
                    579:      //
                    580:      // Try to get a handle to the parameters subkey - which may
                    581:      // involve creating the subkey
                    582:      //
                    583: 
                    584:      ReturnCode = RegCreateKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey);
                    585: 
                    586:      RegCloseKey(ServiceNodeKey);
                    587: 
                    588:      if (ReturnCode == ERROR_SUCCESS) {
                    589:          RegCloseKey(ParmsKey);
                    590:      }
                    591: 
                    592:      return ReturnCode;
                    593: 
                    594:  }
                    595: 
                    596: /***************************************************************************
                    597:  *
                    598:  *  Function :
                    599:  *      DrvQueryDeviceParameter
                    600:  *
                    601:  *  Parameters :
                    602:  *      ServiceNodeKey       Handle to the device services node key
                    603:  *      ValueName            Name of value to query
                    604:  *      pValue               Returned value
                    605:  *
                    606:  *  Return code :
                    607:  *
                    608:  *      Standard error code (see winerror.h)
                    609:  *
                    610:  *  Description :
                    611:  *
                    612:  *      Add the value to the device parameters section under the
                    613:  *      services node.
                    614:  *      This section is created if it does not already exist.
                    615:  *
                    616:  ***************************************************************************/
                    617: 
                    618:  LONG
                    619:  DrvQueryDeviceParameter(
                    620:      PREG_ACCESS RegAccess,
                    621:      LPTSTR ValueName,
                    622:      PDWORD pValue)
                    623:  {
                    624:      HKEY ServiceNodeKey;
                    625:      HKEY ParmsKey;
                    626:      LONG ReturnCode;
                    627:      DWORD Index;
                    628: 
                    629:      ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName);
                    630: 
                    631:      if (ServiceNodeKey == NULL) {
                    632:          return ERROR_FILE_NOT_FOUND;
                    633:      }
                    634: 
                    635:      //
                    636:      // First try to get a handle to the parameters subkey
                    637:      //
                    638: 
                    639:      ReturnCode = RegOpenKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey);
                    640:      RegCloseKey(ServiceNodeKey);
                    641: 
                    642:      if (ReturnCode != ERROR_SUCCESS) {
                    643:          return ReturnCode;
                    644:      }
                    645: 
                    646:      //
                    647:      // That was OK
                    648:      // Now we have to laboriously search the key values to
                    649:      // see if one corresponds to the one we want
                    650:      //
                    651: 
                    652: 
                    653:      for (Index = 0; ; Index++) {            // Enumerate key values
                    654: 
                    655:          TCHAR ThisValueName[MAX_PATH];
                    656:          DWORD NameLength;
                    657:          DWORD Type;
                    658:          DWORD Value;
                    659:          DWORD ValueLength;
                    660: 
                    661:          NameLength = MAX_PATH;
                    662:          NameLength = sizeof(ThisValueName);
                    663:          ValueLength = sizeof(Value);
                    664: 
                    665:          ReturnCode = RegEnumValue(ParmsKey,       // Handle to key
                    666:                                    Index,          // Index of value
                    667:                                    ThisValueName,  // Where to put the name
                    668:                                    &NameLength,    // Length of the name
                    669:                                    NULL,           // Reserved NULL
                    670:                                    &Type,          // returns REG_... type
                    671:                                    (LPBYTE)&Value, // Where to put the value
                    672:                                    &ValueLength);  // Max length of data
                    673: 
                    674:          if (ReturnCode == ERROR_SUCCESS) {
                    675:              //
                    676:              // We've found something - does it's name match the
                    677:              // name we're looking for ?
                    678:              //
                    679: 
                    680:              if (0 == wcsicmp(ValueName, ThisValueName)) {
                    681:                  RegCloseKey(ParmsKey);
                    682: 
                    683:                  //
                    684:                  // If it's the wrong type there's something
                    685:                  // wrong !!
                    686:                  //
                    687: 
                    688:                  if (Type == REG_DWORD) {
                    689: 
                    690:                      //
                    691:                      // Return Value to caller
                    692:                      //
                    693: 
                    694:                      *pValue = Value;
                    695:                      return ERROR_SUCCESS;
                    696:                  } else {
                    697:                      return ERROR_FILE_NOT_FOUND;
                    698:                  }
                    699:              }
                    700:          } else {
                    701:              //
                    702:              // We didn't find the value with the name we were
                    703:              // looking for so return the default
                    704:              //
                    705: 
                    706:              RegCloseKey(ParmsKey);
                    707:              return ReturnCode;
                    708:          }
                    709:      }
                    710:  }
                    711: 
                    712: 
                    713: /***************************************************************************
                    714:  *
                    715:  *  Function :
                    716:  *      DrvLoadKernelDriver
                    717:  *
                    718:  *  Parameters :
                    719:  *      Drivername         Name of driver to load
                    720:  *
                    721:  *  Return code :
                    722:  *
                    723:  *      TRUE if successful, otherwise FALSE
                    724:  *
                    725:  *  Description :
                    726:  *
                    727:  *      Call StartService to load the driver.  This assumes the services
                    728:  *      name is the driver name
                    729:  *
                    730:  ***************************************************************************/
                    731: 
                    732:  BOOL
                    733:  DrvLoadKernelDriver(
                    734:      PREG_ACCESS RegAccess)
                    735:  {
                    736:      SC_HANDLE ServiceHandle;
                    737:      BOOL Success;
                    738:      ServiceHandle = DrvOpenService(RegAccess);
                    739: 
                    740:      if (ServiceHandle == NULL) {
                    741:          return FALSE;
                    742:      }
                    743: 
                    744:     /*
                    745:      *  StartService causes the system to try to load the kernel driver
                    746:      */
                    747: 
                    748:      Success = StartService(ServiceHandle, 0, NULL);
                    749: 
                    750:     /*
                    751:      *  If this was successful we can change the start type to system
                    752:      *  start
                    753:      */
                    754: 
                    755:      if (Success) {
                    756:          Success = ChangeServiceConfig(ServiceHandle,
                    757:                                        SERVICE_NO_CHANGE,
                    758:                                        SERVICE_SYSTEM_START,
                    759:                                        SERVICE_NO_CHANGE,
                    760:                                        NULL,
                    761:                                        NULL,
                    762:                                        NULL,
                    763:                                        NULL,
                    764:                                        NULL,
                    765:                                        NULL,
                    766:                                        NULL);
                    767:      }
                    768:      DrvCloseService(RegAccess, ServiceHandle);
                    769:      return Success;
                    770:  }
                    771: 
                    772: /***************************************************************************
                    773:  *
                    774:  *  Function :
                    775:  *      DrvUnLoadKernelDriver
                    776:  *
                    777:  *  Parameters :
                    778:  *      RegAccess          Access variables to registry and Service control
                    779:  *                         manager
                    780:  *
                    781:  *  Return code :
                    782:  *
                    783:  *      TRUE if successful, otherwise FALSE
                    784:  *
                    785:  *  Description :
                    786:  *
                    787:  *      Call ControlService to unload the driver.  This assumes the services
                    788:  *      name is the driver name
                    789:  *
                    790:  ***************************************************************************/
                    791: 
                    792:  BOOL
                    793:  DrvUnloadKernelDriver(
                    794:      PREG_ACCESS RegAccess)
                    795:  {
                    796:      SERVICE_STATUS ServiceStatus;
                    797:      SC_HANDLE ServiceHandle;
                    798:      BOOL Success;
                    799: 
                    800: 
                    801:      ServiceHandle = DrvOpenService(RegAccess);
                    802:      if (ServiceHandle == NULL) {
                    803:          return GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST;
                    804:      }
                    805: 
                    806:     /*
                    807:      *  Set it not to load at system start until we've reconfigured
                    808:      */
                    809: 
                    810:      Success = ChangeServiceConfig(ServiceHandle,
                    811:                                    SERVICE_NO_CHANGE,
                    812:                                    SERVICE_DEMAND_START,
                    813:                                    SERVICE_NO_CHANGE,
                    814:                                    NULL,
                    815:                                    NULL,
                    816:                                    NULL,
                    817:                                    NULL,
                    818:                                    NULL,
                    819:                                    NULL,
                    820:                                    NULL);
                    821: 
                    822:      if (Success) {
                    823:         /*
                    824:          *  Don't try to unload if it's not loaded
                    825:          */
                    826: 
                    827:          if (DrvIsDriverLoaded(RegAccess)) {
                    828: 
                    829:             /*
                    830:              *  Note that the driver object name will not be found if
                    831:              *  the driver is not loaded.  However, the services manager may
                    832:              *  get in first and decide that the driver file does not exist.
                    833:              */
                    834: 
                    835:              Success = ControlService(ServiceHandle,
                    836:                                       SERVICE_CONTROL_STOP,
                    837:                                       &ServiceStatus);
                    838: 
                    839:          }
                    840: 
                    841:      }
                    842: 
                    843:      DrvCloseService(RegAccess, ServiceHandle);
                    844:      return Success;
                    845:  }
                    846: 
                    847: /***************************************************************************
                    848:  *
                    849:  *  Function :
                    850:  *
                    851:  *      DrvIsDriverLoaded
                    852:  *
                    853:  *  Parameters :
                    854:  *
                    855:  *      RegAccess          Access variables to registry and Service control
                    856:  *                         manager
                    857:  *
                    858:  *  Return code :
                    859:  *
                    860:  *      TRUE if successful, otherwise FALSE
                    861:  *
                    862:  *  Description :
                    863:  *
                    864:  *      See if a service by our name is started.
                    865:  *      Note - this assumes that we think our service is installed
                    866:  *
                    867:  ***************************************************************************/
                    868:  BOOL
                    869:  DrvIsDriverLoaded(
                    870:      PREG_ACCESS RegAccess)
                    871:  {
                    872:      SERVICE_STATUS ServiceStatus;
                    873:      SC_HANDLE ServiceHandle;
                    874:      BOOL Success;
                    875:      ServiceHandle = DrvOpenService(RegAccess);
                    876:      if (ServiceHandle == NULL) {
                    877:          return FALSE;
                    878:      }
                    879: 
                    880: 
                    881:      if (!QueryServiceStatus(ServiceHandle, &ServiceStatus)) {
                    882:          DrvCloseService(RegAccess, ServiceHandle);
                    883:          return FALSE;
                    884:      }
                    885: 
                    886:      Success = ServiceStatus.dwServiceType == SERVICE_KERNEL_DRIVER &&
                    887:                ServiceStatus.dwCurrentState == SERVICE_RUNNING;
                    888: 
                    889:      DrvCloseService(RegAccess, ServiceHandle);
                    890:      return Success;
                    891:  }
                    892: 
                    893: 
                    894: /***************************************************************************
                    895:  *
                    896:  *  Function :
                    897:  *
                    898:  *      DrvConfigureDriver
                    899:  *
                    900:  *  Parameters :
                    901:  *
                    902:  *      RegAccess          Access variables to registry and Service control
                    903:  *                         manager
                    904:  *
                    905:  *      DriverName         Name of the driver
                    906:  *
                    907:  *      DriverType         Type of driver (see registry.h)
                    908:  *
                    909:  *      SetParms           Callback to set the registry parameters
                    910:  *
                    911:  *      Context            Context value for callback
                    912:  *
                    913:  *  Return code :
                    914:  *
                    915:  *      TRUE if successful, otherwise FALSE
                    916:  *
                    917:  *  Description :
                    918:  *
                    919:  *      Performs the necessary operations to (re) configure a driver :
                    920:  *
                    921:  *      1.  If the driver is already installed :
                    922:  *
                    923:  *              Unload it if necessary
                    924:  *
                    925:  *              Set its start type to Demand until we know we're safe
                    926:  *              (This is so the system won't load a bad config if we crash)
                    927:  *
                    928:  *      2.  If the driver is not installed create its service entry in the
                    929:  *          registry.
                    930:  *
                    931:  *      3.  Run the callback to set up the driver's parameters
                    932:  *
                    933:  *      4.  Load the driver
                    934:  *
                    935:  *      5.  If the load returns success set the start type to System start
                    936:  *
                    937:  ***************************************************************************/
                    938: 
                    939:  BOOL DrvConfigureDriver(
                    940:           PREG_ACCESS RegAccess,
                    941:           LPTSTR      DriverName,
                    942:           SOUND_KERNEL_MODE_DRIVER_TYPE
                    943:                       DriverType,
                    944:           BOOL (*     SetParms    )(PVOID),
                    945:           PVOID       Context)
                    946:  {
                    947:      return
                    948: 
                    949:     /*
                    950:      *  If there isn't a services node create one - this is done first
                    951:      *  because this is how the driver name gets into the REG_ACCESS
                    952:      *  structure
                    953:      */
                    954: 
                    955:      DrvCreateServicesNode(
                    956:          DriverName,
                    957:          DriverType,
                    958:          RegAccess,
                    959:          TRUE)
                    960: 
                    961:      &&
                    962: 
                    963:     /*
                    964:      *  Unload driver if it's loaded
                    965:      */
                    966: 
                    967:      DrvUnloadKernelDriver(RegAccess)
                    968: 
                    969:      &&
                    970: 
                    971:     /*
                    972:      *  Run the callback
                    973:      */
                    974: 
                    975:      (SetParms == NULL || (*SetParms)(Context))
                    976: 
                    977:      &&
                    978: 
                    979:     /*
                    980:      *  Try reloading the driver
                    981:      */
                    982: 
                    983:      DrvLoadKernelDriver(RegAccess)
                    984: 
                    985:      ;
                    986: 
                    987:  }
                    988: 
                    989: 
                    990: /***************************************************************************
                    991:  *
                    992:  *  Function :
                    993:  *
                    994:  *      DrvRemoveDriver
                    995:  *
                    996:  *  Parameters :
                    997:  *
                    998:  *      RegAccess          Access variables to registry and Service control
                    999:  *                         manager
                   1000:  *
                   1001:  *  Return code :
                   1002:  *
                   1003:  *      DRVCNF_CANCEL  - Error occurred
                   1004:  *
                   1005:  *      DRVCNF_OK      - Registry entry delete but driver wasn't loaded
                   1006:  *
                   1007:  *      DRVCNF_RESTART - Driver unloaded and registry entry deleted
                   1008:  *
                   1009:  *  Description :
                   1010:  *
                   1011:  *      Unload the driver and remove its service control entry
                   1012:  *
                   1013:  ***************************************************************************/
                   1014: 
                   1015:  LRESULT DrvRemoveDriver(
                   1016:              PREG_ACCESS RegAccess)
                   1017:  {
                   1018:      BOOL Loaded;
                   1019: 
                   1020:      Loaded = DrvIsDriverLoaded(RegAccess);
                   1021: 
                   1022:      if ((!Loaded || DrvUnloadKernelDriver(RegAccess)) &&
                   1023:          DrvDeleteServicesNode(RegAccess)) {
                   1024:          return Loaded ? DRVCNF_RESTART : DRVCNF_OK;
                   1025:      } else {
                   1026:          return DRVCNF_CANCEL;
                   1027:      }
                   1028:  }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.