991 lines
25 KiB
C
991 lines
25 KiB
C
/****************************************************************************
|
|
*
|
|
* registry.c
|
|
*
|
|
* Copyright (c) 1992 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* This file contains functions to maintain registry entries for
|
|
* kernel drivers installed via the drivers control panel applet.
|
|
*
|
|
* Note that the ONLY state maintained between calls here is whatever
|
|
* state the registry and its handles maintain.
|
|
*
|
|
* The registry entries are structured as follows :
|
|
* (see also winreg.h, winnt.h)
|
|
*
|
|
* HKEY_LOCAL_MACHINE
|
|
* SYSTEM
|
|
* CurrentControlSet
|
|
* Services
|
|
* DriverNode (eg sndblst)
|
|
* Type = SERVICE_KERNEL_DRIVER (eg)
|
|
* Group = "Base"
|
|
* ErrorControl = SERVICE_ERROR_NORMAL
|
|
* Start = SERVICE_SYSTEM_START |
|
|
* SERVICE_DEMAND_START |
|
|
* SERVICE_DISABLED
|
|
* ...
|
|
* Tag = A unique number ???
|
|
*
|
|
* Device
|
|
* Interrupt =
|
|
* Port =
|
|
* DMAChannel =
|
|
*
|
|
* The Driver node is set up by the services manager when we call
|
|
* CreateService but we have to insert the device data ourselves.
|
|
*
|
|
*
|
|
*
|
|
* The registry entries are shared between :
|
|
*
|
|
* The system loader (which uses the Services entry)
|
|
* The kernel driver (which reads from the Device entry)
|
|
* This component called from the drivers control panel applet
|
|
* The service control manager
|
|
* The Setup utility
|
|
*
|
|
* Security access
|
|
* ---------------
|
|
*
|
|
* The driver determines whether it can perform configuration and
|
|
* installation by whether it can get read and write access to the
|
|
* service control manager. This is required to manipulate the kernel
|
|
* driver database.
|
|
*
|
|
* Services controller
|
|
* -------------------
|
|
*
|
|
* The services controller is used because this is the only way we
|
|
* are allowed to load and unload kernel drivers. Only the services
|
|
* controller can call LoadDriver and UnloadDriver and not get 'access
|
|
* denied'.
|
|
*
|
|
* Note also that we can't keep the services controller handle open
|
|
* at the same time as the registry handle because then we can't get
|
|
* write access (actually we only need KEY_CREATE_SUB_KEY access) to
|
|
* our device parameters subkey.
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#ifdef UNICODE
|
|
#include <wchar.h>
|
|
#else
|
|
#include <string.h>
|
|
#define wcscat strcat
|
|
#define wcscpy strcpy
|
|
#define wcsicmp stricmp
|
|
#endif
|
|
#include <windows.h>
|
|
#include <mmsystem.h>
|
|
#include <winsvc.h>
|
|
|
|
// #include <soundcfg.h>
|
|
// include the video interface file to get the PARMS_SUBKEY defn
|
|
#include <ntddvidc.h>
|
|
|
|
#include "registry.h"
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Constants for accessing the registry
|
|
*
|
|
***************************************************************************/
|
|
|
|
/*
|
|
* Path to service node key
|
|
*/
|
|
|
|
#define STR_SERVICES_NODE TEXT("SYSTEM\\CurrentControlSet\\Services\\")
|
|
|
|
/*
|
|
* Node sub-key for device parameters
|
|
*/
|
|
|
|
#define STR_DEVICE_DATA PARMS_SUBKEY
|
|
|
|
/*
|
|
* Name of Base group where sound drivers normally go
|
|
*/
|
|
|
|
#define STR_BASE_GROUP TEXT("Base")
|
|
|
|
/*
|
|
* Name of driver group for synthesizers
|
|
* - we use our own name here to make sure
|
|
* we are loaded after things like the PAS driver. (Base is a
|
|
* known group and drivers in it are always loaded before unknown
|
|
* groups like this one).
|
|
*/
|
|
|
|
#define STR_SYNTH_GROUP TEXT("Synthesizer Drivers")
|
|
|
|
/*
|
|
* Name of service
|
|
*/
|
|
|
|
#define STR_DRIVER TEXT("\\Driver\\")
|
|
|
|
/*
|
|
* Path to kernel drivers directory from system directory
|
|
*/
|
|
|
|
#define STR_DRIVERS_DIR TEXT("\\SystemRoot\\SYSTEM32\\DRIVERS\\")
|
|
|
|
/*
|
|
* Extension for drivers
|
|
*/
|
|
|
|
#define STR_SYS_EXT TEXT(".SYS")
|
|
|
|
|
|
HKEY DrvOpenRegKey(LPTSTR DriverName)
|
|
{
|
|
TCHAR RegistryPath[MAX_PATH];
|
|
HKEY NodeHandle;
|
|
|
|
//
|
|
// Create the path to our node
|
|
//
|
|
|
|
wcscpy(RegistryPath, STR_SERVICES_NODE);
|
|
wcscat(RegistryPath, DriverName);
|
|
|
|
//
|
|
// See if we can get a registry handle to our device data
|
|
//
|
|
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
RegistryPath,
|
|
0L,
|
|
KEY_ALL_ACCESS,
|
|
&NodeHandle)
|
|
!= ERROR_SUCCESS) {
|
|
return NULL;
|
|
} else {
|
|
return NodeHandle;
|
|
}
|
|
}
|
|
|
|
|
|
SC_HANDLE DrvOpenService(PREG_ACCESS RegAccess)
|
|
{
|
|
SC_HANDLE Handle;
|
|
Handle = OpenService(RegAccess->ServiceManagerHandle,
|
|
RegAccess->DriverName,
|
|
SERVICE_ALL_ACCESS);
|
|
|
|
#if 0
|
|
if (Handle == NULL) {
|
|
char buf[100];
|
|
sprintf(buf, "OpenService failed code %d\n", GetLastError());
|
|
OutputDebugStringA(buf);
|
|
}
|
|
#endif
|
|
|
|
return Handle;
|
|
}
|
|
|
|
void DrvCloseService(PREG_ACCESS RegAccess, SC_HANDLE ServiceHandle)
|
|
{
|
|
CloseServiceHandle(ServiceHandle);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvCreateServicesNode
|
|
*
|
|
* Parameters :
|
|
* DriverNodeName The name of the service node. Same as the
|
|
* name of the driver which must be
|
|
* DriverNodeName.sys for the system to find it.
|
|
*
|
|
* DriverType Type of driver - see registry.h
|
|
*
|
|
* ServiceNodeKey Pointer to where to put returned handle
|
|
*
|
|
* Return code :
|
|
*
|
|
* Standard error code (see winerror.h)
|
|
*
|
|
* Description :
|
|
*
|
|
* Create the service node key
|
|
*
|
|
* The class name of the registry node is ""
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
DrvCreateServicesNode(LPTSTR DriverName,
|
|
SOUND_KERNEL_MODE_DRIVER_TYPE DriverType,
|
|
PREG_ACCESS RegAccess,
|
|
BOOL Create)
|
|
{
|
|
SERVICE_STATUS ServiceStatus;
|
|
SC_HANDLE ServiceHandle; // Handle to our driver 'service'
|
|
|
|
RegAccess->DriverName = DriverName;
|
|
|
|
//
|
|
// See if we can open the registry
|
|
//
|
|
|
|
if (RegAccess->ServiceManagerHandle == NULL) {
|
|
RegAccess->ServiceManagerHandle =
|
|
OpenSCManager(
|
|
NULL, // This machine
|
|
NULL, // The active database
|
|
SC_MANAGER_ALL_ACCESS); // We want to create and change
|
|
|
|
if (RegAccess->ServiceManagerHandle == NULL) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Open our particular service
|
|
//
|
|
|
|
ServiceHandle = DrvOpenService(RegAccess);
|
|
|
|
//
|
|
// See if that worked
|
|
//
|
|
|
|
if (ServiceHandle == NULL &&
|
|
GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) {
|
|
if (Create) {
|
|
SC_LOCK ServicesDatabaseLock;
|
|
TCHAR ServiceName[MAX_PATH];
|
|
TCHAR BinaryPath[MAX_PATH];
|
|
|
|
wcscpy(BinaryPath, STR_DRIVERS_DIR);
|
|
wcscat(BinaryPath, DriverName);
|
|
wcscat(BinaryPath, STR_SYS_EXT);
|
|
|
|
wcscpy(ServiceName, STR_DRIVER);
|
|
wcscat(ServiceName, DriverName);
|
|
|
|
/*
|
|
* Lock the service controller database to avoid deadlocks
|
|
* we have to loop because we can't wait
|
|
*/
|
|
|
|
|
|
for (ServicesDatabaseLock = NULL;
|
|
(ServicesDatabaseLock =
|
|
LockServiceDatabase(RegAccess->ServiceManagerHandle))
|
|
== NULL;
|
|
Sleep(100)) {
|
|
}
|
|
|
|
|
|
/*
|
|
* Create the service
|
|
*/
|
|
|
|
|
|
ServiceHandle =
|
|
CreateService(
|
|
RegAccess->ServiceManagerHandle,
|
|
DriverName, // Service name
|
|
NULL, // ???
|
|
SERVICE_ALL_ACCESS, // Full access
|
|
SERVICE_KERNEL_DRIVER, // Kernel driver
|
|
SERVICE_DEMAND_START, // Start at sys start
|
|
SERVICE_ERROR_NORMAL, // Not a disaster if fails
|
|
BinaryPath, // Default path
|
|
|
|
DriverType == SoundDriverTypeSynth ?
|
|
STR_SYNTH_GROUP : // Driver group
|
|
STR_BASE_GROUP,
|
|
NULL, // do not want TAG information
|
|
TEXT("\0"), // No dependencies
|
|
NULL, // ServiceName, // Driver object - optional
|
|
NULL); // No password
|
|
|
|
UnlockServiceDatabase(ServicesDatabaseLock);
|
|
#if DBG
|
|
if (ServiceHandle == NULL) {
|
|
TCHAR buf[100];
|
|
wsprintf(buf, TEXT("CreateService failed code %d\n"), GetLastError());
|
|
OutputDebugString(buf);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check at least that it's a device driver
|
|
//
|
|
|
|
if (ServiceHandle != NULL) {
|
|
if (!QueryServiceStatus(
|
|
ServiceHandle,
|
|
&ServiceStatus) ||
|
|
ServiceStatus.dwServiceType != SERVICE_KERNEL_DRIVER) {
|
|
|
|
//
|
|
// Doesn't look like ours
|
|
//
|
|
|
|
CloseServiceHandle(RegAccess->ServiceManagerHandle);
|
|
RegAccess->ServiceManagerHandle = NULL;
|
|
DrvCloseService(RegAccess, ServiceHandle);
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
if (ServiceHandle == NULL) {
|
|
//
|
|
// Leave the SC manager handle open. We use the presence of this
|
|
// handle to test whether the driver can be configured (ie whether we
|
|
// have the access rights to get into the SC manager).
|
|
//
|
|
|
|
return FALSE;
|
|
} else {
|
|
//
|
|
// We can't keep this handle open (even though we'd like to) because
|
|
// we need write access to the registry node created so that
|
|
// we can add device parameters
|
|
//
|
|
|
|
DrvCloseService(RegAccess, ServiceHandle);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvCloseServicesNode
|
|
*
|
|
* Parameters :
|
|
* ServiceNodeKey
|
|
*
|
|
* Return code :
|
|
*
|
|
* Standard error code (see winerror.h)
|
|
*
|
|
* Description :
|
|
*
|
|
* Close our handle
|
|
*
|
|
***************************************************************************/
|
|
|
|
VOID
|
|
DrvCloseServiceManager(
|
|
PREG_ACCESS RegAccess)
|
|
{
|
|
if (RegAccess->ServiceManagerHandle != NULL) {
|
|
CloseServiceHandle(RegAccess->ServiceManagerHandle);
|
|
RegAccess->ServiceManagerHandle = NULL;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvDeleteServicesNode
|
|
*
|
|
* Parameters :
|
|
* DeviceName
|
|
*
|
|
* Return code :
|
|
*
|
|
* TRUE = success, FALSE = failed
|
|
*
|
|
* Description :
|
|
*
|
|
* Delete our node using the handle proviced
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
DrvDeleteServicesNode(
|
|
PREG_ACCESS RegAccess)
|
|
{
|
|
BOOL Success;
|
|
SC_LOCK ServicesDatabaseLock;
|
|
SC_HANDLE ServiceHandle;
|
|
HKEY NodeHandle;
|
|
|
|
NodeHandle = DrvOpenRegKey(RegAccess->DriverName);
|
|
|
|
//
|
|
// Make sure we're not accessing the registry ourselves and
|
|
// that there aren't any subkeys
|
|
//
|
|
|
|
if (NodeHandle) {
|
|
RegDeleteKey(NodeHandle, STR_DEVICE_DATA);
|
|
RegFlushKey(NodeHandle);
|
|
RegCloseKey(NodeHandle);
|
|
}
|
|
|
|
//
|
|
// Delete the service node and free tha handle
|
|
// (Note the service cannot be deleted until all handles are closed)
|
|
//
|
|
|
|
ServiceHandle = DrvOpenService(RegAccess);
|
|
|
|
if (ServiceHandle == NULL) {
|
|
LONG Error;
|
|
Error = GetLastError();
|
|
if (Error == ERROR_SERVICE_DOES_NOT_EXIST) {
|
|
//
|
|
// It's already gone !
|
|
//
|
|
return TRUE;
|
|
} else {
|
|
return FALSE; // It was there but something went wrong
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Lock the service controller database to avoid deadlocks
|
|
* we have to loop because we can't wait
|
|
*/
|
|
|
|
|
|
for (ServicesDatabaseLock = NULL;
|
|
(ServicesDatabaseLock =
|
|
LockServiceDatabase(RegAccess->ServiceManagerHandle))
|
|
== NULL;
|
|
Sleep(100)) {
|
|
}
|
|
|
|
Success = DeleteService(ServiceHandle);
|
|
|
|
UnlockServiceDatabase(ServicesDatabaseLock);
|
|
|
|
DrvCloseService(RegAccess, ServiceHandle);
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvSetDeviceParameter
|
|
*
|
|
* Parameters :
|
|
* ServiceNodeKey Handle to the device services node key
|
|
* ValueName Name of value to set
|
|
* Value DWORD value to set
|
|
*
|
|
* Return code :
|
|
*
|
|
* Standard error code (see winerror.h)
|
|
*
|
|
* Description :
|
|
*
|
|
* Add the value to the device parameters section under the
|
|
* services node.
|
|
* This section is created if it does not already exist.
|
|
*
|
|
***************************************************************************/
|
|
|
|
LONG
|
|
DrvSetDeviceParameter(
|
|
PREG_ACCESS RegAccess,
|
|
LPTSTR ValueName,
|
|
DWORD Value)
|
|
{
|
|
HKEY ServiceNodeKey;
|
|
HKEY ParmsKey;
|
|
LONG ReturnCode;
|
|
|
|
ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName);
|
|
|
|
if (ServiceNodeKey == NULL) {
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// First try to get a handle to the parameters subkey - which may
|
|
// involve creating the subkey
|
|
//
|
|
|
|
ReturnCode = RegCreateKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey);
|
|
|
|
RegCloseKey(ServiceNodeKey);
|
|
|
|
if (ReturnCode != ERROR_SUCCESS) {
|
|
return ReturnCode;
|
|
}
|
|
|
|
//
|
|
// Write the value
|
|
//
|
|
|
|
|
|
ReturnCode = RegSetValueEx(ParmsKey, // Registry handle
|
|
ValueName, // Name of item
|
|
0, // Reserved 0
|
|
REG_DWORD, // Data type
|
|
(LPBYTE)&Value, // The value
|
|
sizeof(Value)); // Data length
|
|
|
|
//
|
|
// Free the handles we created
|
|
//
|
|
|
|
RegCloseKey(ParmsKey);
|
|
|
|
return ReturnCode;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvCreateParamsKey
|
|
*
|
|
* Parameters :
|
|
* RegAccess Registry access info
|
|
*
|
|
* Return code :
|
|
*
|
|
* Standard error code (see winerror.h)
|
|
*
|
|
* Description :
|
|
*
|
|
* Create the device parameters section under the
|
|
* services node if it does not already exist. No values are
|
|
* written to the key.
|
|
*
|
|
***************************************************************************/
|
|
|
|
LONG
|
|
DrvCreateParamsKey(
|
|
PREG_ACCESS RegAccess)
|
|
{
|
|
HKEY ServiceNodeKey;
|
|
HKEY ParmsKey;
|
|
LONG ReturnCode;
|
|
|
|
ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName);
|
|
|
|
if (ServiceNodeKey == NULL) {
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Try to get a handle to the parameters subkey - which may
|
|
// involve creating the subkey
|
|
//
|
|
|
|
ReturnCode = RegCreateKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey);
|
|
|
|
RegCloseKey(ServiceNodeKey);
|
|
|
|
if (ReturnCode == ERROR_SUCCESS) {
|
|
RegCloseKey(ParmsKey);
|
|
}
|
|
|
|
return ReturnCode;
|
|
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvQueryDeviceParameter
|
|
*
|
|
* Parameters :
|
|
* ServiceNodeKey Handle to the device services node key
|
|
* ValueName Name of value to query
|
|
* pValueType Place to return the type(REG_SZ...) of value (optional)
|
|
* pValue Returned value
|
|
* ValueLength Size of buffer for returned value (bytes)
|
|
*
|
|
*
|
|
* Return code :
|
|
*
|
|
* Standard error code (see winerror.h)
|
|
*
|
|
* Description :
|
|
*
|
|
* Add the value to the device parameters section under the
|
|
* services node.
|
|
* This section is created if it does not already exist.
|
|
*
|
|
***************************************************************************/
|
|
|
|
LONG
|
|
DrvQueryDeviceParameter(
|
|
PREG_ACCESS RegAccess,
|
|
LPTSTR ValueName,
|
|
PDWORD pValueType,
|
|
PVOID pValue,
|
|
DWORD ValueLength
|
|
)
|
|
{
|
|
HKEY ServiceNodeKey;
|
|
HKEY ParmsKey;
|
|
LONG ReturnCode;
|
|
|
|
ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName);
|
|
|
|
if (ServiceNodeKey == NULL) {
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// First try to get a handle to the parameters subkey
|
|
//
|
|
|
|
ReturnCode = RegOpenKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey);
|
|
RegCloseKey(ServiceNodeKey);
|
|
|
|
if (ReturnCode != ERROR_SUCCESS) {
|
|
return ReturnCode;
|
|
}
|
|
|
|
|
|
ReturnCode = RegQueryValueEx(
|
|
ParmsKey,
|
|
ValueName,
|
|
NULL,
|
|
pValueType,
|
|
pValue,
|
|
&ValueLength);
|
|
|
|
RegCloseKey(ParmsKey);
|
|
|
|
return(ReturnCode);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvLoadKernelDriver
|
|
*
|
|
* Parameters :
|
|
* Drivername Name of driver to load
|
|
*
|
|
* Return code :
|
|
*
|
|
* TRUE if successful, otherwise FALSE
|
|
*
|
|
* Description :
|
|
*
|
|
* Call StartService to load the driver. This assumes the services
|
|
* name is the driver name
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
DrvLoadKernelDriver(
|
|
PREG_ACCESS RegAccess)
|
|
{
|
|
SC_HANDLE ServiceHandle;
|
|
BOOL Success;
|
|
ServiceHandle = DrvOpenService(RegAccess);
|
|
|
|
if (ServiceHandle == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* StartService causes the system to try to load the kernel driver
|
|
*/
|
|
|
|
Success = StartService(ServiceHandle, 0, NULL);
|
|
|
|
/*
|
|
* If this was successful we can change the start type to system
|
|
* start
|
|
*/
|
|
|
|
if (Success) {
|
|
Success = ChangeServiceConfig(ServiceHandle,
|
|
SERVICE_NO_CHANGE,
|
|
SERVICE_SYSTEM_START,
|
|
SERVICE_NO_CHANGE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
DrvCloseService(RegAccess, ServiceHandle);
|
|
return Success;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
* DrvUnLoadKernelDriver
|
|
*
|
|
* Parameters :
|
|
* RegAccess Access variables to registry and Service control
|
|
* manager
|
|
*
|
|
* Return code :
|
|
*
|
|
* TRUE if successful, otherwise FALSE
|
|
*
|
|
* Description :
|
|
*
|
|
* Call ControlService to unload the driver. This assumes the services
|
|
* name is the driver name
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
DrvUnloadKernelDriver(
|
|
PREG_ACCESS RegAccess)
|
|
{
|
|
SERVICE_STATUS ServiceStatus;
|
|
SC_HANDLE ServiceHandle;
|
|
BOOL Success;
|
|
|
|
|
|
ServiceHandle = DrvOpenService(RegAccess);
|
|
if (ServiceHandle == NULL) {
|
|
return GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST;
|
|
}
|
|
|
|
/*
|
|
* Set it not to load at system start until we've reconfigured
|
|
*/
|
|
|
|
Success = ChangeServiceConfig(ServiceHandle,
|
|
SERVICE_NO_CHANGE,
|
|
SERVICE_DEMAND_START,
|
|
SERVICE_NO_CHANGE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (Success) {
|
|
/*
|
|
* Don't try to unload if it's not loaded
|
|
*/
|
|
|
|
if (DrvIsDriverLoaded(RegAccess)) {
|
|
|
|
/*
|
|
* Note that the driver object name will not be found if
|
|
* the driver is not loaded. However, the services manager may
|
|
* get in first and decide that the driver file does not exist.
|
|
*/
|
|
|
|
Success = ControlService(ServiceHandle,
|
|
SERVICE_CONTROL_STOP,
|
|
&ServiceStatus);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DrvCloseService(RegAccess, ServiceHandle);
|
|
return Success;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
*
|
|
* DrvIsDriverLoaded
|
|
*
|
|
* Parameters :
|
|
*
|
|
* RegAccess Access variables to registry and Service control
|
|
* manager
|
|
*
|
|
* Return code :
|
|
*
|
|
* TRUE if successful, otherwise FALSE
|
|
*
|
|
* Description :
|
|
*
|
|
* See if a service by our name is started.
|
|
* Note - this assumes that we think our service is installed
|
|
*
|
|
***************************************************************************/
|
|
BOOL
|
|
DrvIsDriverLoaded(
|
|
PREG_ACCESS RegAccess)
|
|
{
|
|
SERVICE_STATUS ServiceStatus;
|
|
SC_HANDLE ServiceHandle;
|
|
BOOL Success;
|
|
ServiceHandle = DrvOpenService(RegAccess);
|
|
if (ServiceHandle == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (!QueryServiceStatus(ServiceHandle, &ServiceStatus)) {
|
|
DrvCloseService(RegAccess, ServiceHandle);
|
|
return FALSE;
|
|
}
|
|
|
|
Success = ServiceStatus.dwServiceType == SERVICE_KERNEL_DRIVER &&
|
|
ServiceStatus.dwCurrentState == SERVICE_RUNNING;
|
|
|
|
DrvCloseService(RegAccess, ServiceHandle);
|
|
return Success;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
*
|
|
* DrvConfigureDriver
|
|
*
|
|
* Parameters :
|
|
*
|
|
* RegAccess Access variables to registry and Service control
|
|
* manager
|
|
*
|
|
* DriverName Name of the driver
|
|
*
|
|
* DriverType Type of driver (see registry.h)
|
|
*
|
|
* SetParms Callback to set the registry parameters
|
|
*
|
|
* Context Context value for callback
|
|
*
|
|
* Return code :
|
|
*
|
|
* TRUE if successful, otherwise FALSE
|
|
*
|
|
* Description :
|
|
*
|
|
* Performs the necessary operations to (re) configure a driver :
|
|
*
|
|
* 1. If the driver is already installed :
|
|
*
|
|
* Unload it if necessary
|
|
*
|
|
* Set its start type to Demand until we know we're safe
|
|
* (This is so the system won't load a bad config if we crash)
|
|
*
|
|
* 2. If the driver is not installed create its service entry in the
|
|
* registry.
|
|
*
|
|
* 3. Run the callback to set up the driver's parameters
|
|
*
|
|
* 4. Load the driver
|
|
*
|
|
* 5. If the load returns success set the start type to System start
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOL DrvConfigureDriver(
|
|
PREG_ACCESS RegAccess,
|
|
LPTSTR DriverName,
|
|
SOUND_KERNEL_MODE_DRIVER_TYPE
|
|
DriverType,
|
|
BOOL (* SetParms )(PVOID),
|
|
PVOID Context)
|
|
{
|
|
return
|
|
|
|
/*
|
|
* If there isn't a services node create one - this is done first
|
|
* because this is how the driver name gets into the REG_ACCESS
|
|
* structure
|
|
*/
|
|
|
|
DrvCreateServicesNode(
|
|
DriverName,
|
|
DriverType,
|
|
RegAccess,
|
|
TRUE)
|
|
|
|
&&
|
|
|
|
/*
|
|
* Unload driver if it's loaded
|
|
*/
|
|
|
|
DrvUnloadKernelDriver(RegAccess)
|
|
|
|
&&
|
|
|
|
/*
|
|
* Run the callback
|
|
*/
|
|
|
|
SetParms == NULL || (*SetParms)(Context)
|
|
|
|
&&
|
|
|
|
/*
|
|
* Try reloading the driver
|
|
*/
|
|
|
|
DrvLoadKernelDriver(RegAccess)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function :
|
|
*
|
|
* DrvRemoveDriver
|
|
*
|
|
* Parameters :
|
|
*
|
|
* RegAccess Access variables to registry and Service control
|
|
* manager
|
|
*
|
|
* Return code :
|
|
*
|
|
* DRVCNF_CANCEL - Error occurred
|
|
*
|
|
* DRVCNF_OK - Registry entry delete but driver wasn't loaded
|
|
*
|
|
* DRVCNF_RESTART - Driver unloaded and registry entry deleted
|
|
*
|
|
* Description :
|
|
*
|
|
* Unload the driver and remove its service control entry
|
|
*
|
|
***************************************************************************/
|
|
|
|
LRESULT DrvRemoveDriver(
|
|
PREG_ACCESS RegAccess)
|
|
{
|
|
BOOL Loaded;
|
|
|
|
Loaded = DrvIsDriverLoaded(RegAccess);
|
|
|
|
if ((!Loaded || DrvUnloadKernelDriver(RegAccess)) &&
|
|
DrvDeleteServicesNode(RegAccess)) {
|
|
|
|
// for the video driver, we do not need to restart even if loaded.
|
|
// return Loaded ? DRVCNF_RESTART : DRVCNF_OK;
|
|
return DRVCNF_OK;
|
|
} else {
|
|
return DRVCNF_CANCEL;
|
|
}
|
|
}
|