NT4/private/windows/media/vidcap/vcuser/vcinstal.c

460 lines
11 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*
* Copyright (c) Microsoft Corporation 1993. All Rights Reserved.
*/
/*
* vcinstal.c
*
* 32-bit Video Capture driver
* User-mode support library - kernel driver install/remove
*
*
* Geraint Davies, Feb 93
*/
#include <windows.h>
#include <mmsystem.h>
#include <msvideo.h>
#include <mmddk.h>
#include <devioctl.h>
#include <vcstruct.h>
#include <ntddvidc.h>
#include <vcuser.h>
#include "vcupriv.h"
#include "registry.h"
/*
* Driver Install/Remove
*
* we use the standard functions in registry.c to start and
* stop the kernel driver, and to read/write the registry for
* driver configuration information. This module is essentially a
* wrapper to permit common win-16/nt driver code.
*
*/
/*
* we return an (opaque) pointer to this structure from the
* VC_OpenProfileAccess function. It contains the information we need
* to call the registry functions.
*/
struct _VC_PROFILE_INFO {
REG_ACCESS RegAccess;
};
typedef struct _VC_PROFILE_INFO VC_PROFILE_INFO;
/*
* open a handle to whatever functions are needed to access the registry,
* service controller or profile. Must call this function before
* calls to the other VC_ configuration routines.
*
* The argument is the name of the driver. This should be the name of
* the kernel driver file (without path or extension). It will also be used
* as the registry key name or profile section name.
*
* Even if the open fails, we still return the allocated structure - so
* that the absence of open handles within the structure can be used
* by DrvAccess operations to test if we have sufficient privilege.
*/
PVC_PROFILE_INFO
VC_OpenProfileAccess(PWCHAR DriverName)
{
PVC_PROFILE_INFO pProf;
/*
* allocate the profileinfo from the global heap
*/
pProf = GlobalLock(GlobalAlloc(GPTR, sizeof(VC_PROFILE_INFO)));
if (pProf == NULL) {
return(NULL);
}
/*
* set the driver name, but don't access the services controller
* unless we need to (administrators only can do this)
*/
pProf->RegAccess.DriverName = DriverName;
pProf->RegAccess.ServiceManagerHandle = NULL;
return(pProf);
}
/*
* close the handles opened during OpenProfileAccess.
*/
VOID
VC_CloseProfileAccess(PVC_PROFILE_INFO pProf)
{
ASSERT(pProf != NULL);
/*
* close the service controller handle opened by DrvCreateServiceNode
*/
DrvCloseServiceManager(&pProf->RegAccess);
/*
* free up the profile info structure that we allocated from the global
* heap.
*/
GlobalFree(GlobalHandle(pProf));
return;
}
/*
* start the hardware-access portion of the driver. Call the callback
* function at a moment when it is possible to write configuration information
* to the profile using VC_WriteProfile.
* Returns DRVCNF_OK if all is ok, DRVCNF_CANCEL for failure, or DRVCNF_RESTART if
* all is ok but a system-restart is needed before the driver will load correctly.
*/
LRESULT
VC_InstallDriver(
PVC_PROFILE_INFO pProfile, // access info returned by OpenProfileAccess
PPROFILE_CALLBACK pCallback, // callback function
PVOID pContext // context info for callback
)
{
// must have called OpenProfileAccess first.
ASSERT(pProfile != NULL);
/*
* open a handle to the service entry in the registry - force
* creation of the entry if it does not exist.
*/
if (!DrvCreateServicesNode(
pProfile->RegAccess.DriverName, // name of node and driver file
SoundDriverTypeNormal, // determines dependency order
&pProfile->RegAccess, // open handle info
TRUE // create the node if not present
)) {
return(DRVCNF_CANCEL);
}
/* ensure that the driver is not currently loaded */
DrvUnloadKernelDriver(&pProfile->RegAccess);
/* now its safe to store items in the registry */
if (pCallback != NULL) {
if (!pCallback(pContext)) {
return(DRVCNF_CANCEL);
}
}
/* now load the driver */
if (!DrvLoadKernelDriver(&pProfile->RegAccess)) {
return(DRVCNF_CANCEL);
} else {
return(DRVCNF_OK);
}
}
/*
* Write a single string keyword and DWORD value to the registry or profile
* for this driver.
* This can be re-read from the h/w driver using VC_ReadProfile (in kernel mode).
*
* return TRUE for success or FALSE for failure.
*/
BOOL
VC_WriteProfile(PVC_PROFILE_INFO pProfile, PWCHAR ValueName, DWORD Value)
{
LONG lRet;
lRet = DrvSetDeviceParameter(&pProfile->RegAccess, ValueName, Value);
if (lRet == ERROR_SUCCESS) {
return(TRUE);
} else {
return(FALSE);
}
}
/*
* read back a driver-specific DWORD profile parameter that was written with
* VC_WriteProfile. If the valuename cannot be found, the default is returned.
*
* use RegOpenKeyEx directly instead of via registry.c so that we can get
* read-only use and permit capture from a non-admin.
*/
DWORD VC_ReadProfile(PVC_PROFILE_INFO pProfile, PWCHAR ValueName, DWORD dwDefault)
{
LONG lRet;
DWORD dwResult;
DWORD dwType;
DWORD dwLength;
HKEY hkParams;
TCHAR RegistryPath[MAX_PATH];
//
// Create the path to our node
//
wcscpy(RegistryPath, TEXT("SYSTEM\\CurrentControlSet\\Services\\"));
wcscat(RegistryPath, pProfile->RegAccess.DriverName);
wcscat(RegistryPath, TEXT("\\"));
wcscat(RegistryPath, PARMS_SUBKEY);
//
// See if we can get a registry handle to our device data
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
RegistryPath,
0L,
KEY_QUERY_VALUE,
&hkParams)
!= ERROR_SUCCESS) {
return dwDefault;
}
dwLength = sizeof(dwResult); // initialise to size of result field
lRet = RegQueryValueEx(
hkParams,
ValueName,
NULL,
&dwType,
(PCHAR)&dwResult,
&dwLength);
RegCloseKey(hkParams);
if ((lRet != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
return dwDefault;
} else {
return dwResult;
}
}
static const WCHAR gszUserParmsPath[] = L"Software\\Microsoft\\Multimedia\\Video Capture\\";
#define USERPARMSPATH gszUserParmsPath
/*
* read back a driver-specific DWORD profile parameter that was written with
* VC_WriteProfileUser. If the valuename cannot be found, the default is returned.
*/
DWORD VC_ReadProfileUser(PVC_PROFILE_INFO pProfile, PWCHAR ValueName, DWORD dwDefault)
{
LONG lRet;
DWORD dwResult;
DWORD dwType;
DWORD dwLength;
HKEY hkParams;
TCHAR RegistryPath[MAX_PATH];
//
// Create the path to our node
//
wcscpy(RegistryPath, USERPARMSPATH);
wcscat(RegistryPath, pProfile->RegAccess.DriverName);
//
// See if we can get a registry handle to our device data
//
if (RegOpenKeyExW(HKEY_CURRENT_USER,
RegistryPath,
0L,
KEY_QUERY_VALUE,
&hkParams)
!= ERROR_SUCCESS) {
return dwDefault;
}
dwLength = sizeof(dwResult); // initialise to size of result field
lRet = RegQueryValueExW(
hkParams,
ValueName,
NULL,
&dwType,
(PCHAR)&dwResult,
&dwLength);
RegCloseKey(hkParams);
if ((lRet != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
return dwDefault;
} else {
return dwResult;
}
}
/*
* write a driver-specific DWORD profile parameter for current user use.
*/
BOOL VC_WriteProfileUser(PVC_PROFILE_INFO pProfile, PWCHAR ValueName, DWORD Value)
{
LONG lRet;
DWORD dwDisposition;
HKEY hkParams;
WCHAR RegistryPath[MAX_PATH];
//
// Create the path to our node
//
wcscpy(RegistryPath, USERPARMSPATH);
wcscat(RegistryPath, pProfile->RegAccess.DriverName);
//
// See if we can get a registry handle to our device data
//
if (ERROR_SUCCESS == RegCreateKeyExW(HKEY_CURRENT_USER,
RegistryPath,
0L,
NULL, // no class name
0, // no special options (this is NOT volatile data)
KEY_WRITE,
NULL, // no special security
&hkParams,
&dwDisposition))
{
lRet = RegSetValueExW(
hkParams,
ValueName,
0,
REG_DWORD,
(PCHAR)&Value,
sizeof(Value));
RegCloseKey(hkParams);
if (ERROR_SUCCESS == lRet) {
return TRUE;
}
}
return(FALSE);
}
/*
* read a string parameter from the device's profile. returns FALSE
* if it fails to read the string.
*/
BOOL
VC_ReadProfileString(
PVC_PROFILE_INFO pProfile,
PWCHAR ValueName,
PWCHAR ValueString,
DWORD ValueLength
)
{
LONG lRet;
DWORD dwType;
HKEY hkParams;
TCHAR RegistryPath[MAX_PATH];
/*
* fill the whole string with 0s to ensure that it is null
* terminated on return
*/
FillMemory(ValueString, ValueLength, 0);
//
// Create the path to our node
//
wcscpy(RegistryPath, TEXT("SYSTEM\\CurrentControlSet\\Services\\"));
wcscat(RegistryPath, pProfile->RegAccess.DriverName);
wcscat(RegistryPath, TEXT("\\"));
wcscat(RegistryPath, PARMS_SUBKEY);
//
// See if we can get a registry handle to our device data
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
RegistryPath,
0L,
KEY_QUERY_VALUE,
&hkParams)
!= ERROR_SUCCESS) {
return FALSE;
}
lRet = RegQueryValueEx(
hkParams,
ValueName,
NULL,
&dwType,
(PUCHAR) ValueString,
&ValueLength);
RegCloseKey(hkParams);
if ((lRet != ERROR_SUCCESS) || (dwType != REG_SZ)) {
return(FALSE);
} else {
return(TRUE);
}
}
/*
* unload a driver. On NT, this stops and removes the kernel-mode driver.
* On win-16, this would call the Cleanup callback.
*
* the VC_PROFILE_INFO structure is not valid after this call.
*
* return DRVCNF_OK if the unload was successful, DRVCNF_CANCEL if it failed, and
* DRVCNF_RESTART if a system-restart is needed before the removal takes effect.
*/
LRESULT
VC_RemoveDriver(PVC_PROFILE_INFO pProf)
{
ASSERT(pProf != NULL);
return(DrvRemoveDriver(&pProf->RegAccess));
}
/*
* do we have sufficient privilege to access the services controller,
* registry and anything else we need to configure the driver ?
*/
BOOL
VC_ConfigAccess(PVC_PROFILE_INFO pProf)
{
//
// Access the services node
//
/*
* open the services node without creating it, to init
* the RegAccess structure
*/
DrvCreateServicesNode(
pProf->RegAccess.DriverName, // file/node name
SoundDriverTypeNormal, // decides starting order/dependency
&pProf->RegAccess, // storage for registry handles etc
FALSE // don't create node if not there
);
return(DrvAccess(&pProf->RegAccess));
}