Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1123 lines
29 KiB

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