Windows NT 4.0 source code leak
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.

1028 lines
27 KiB

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