590 lines
13 KiB
C
590 lines
13 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995-2001 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
rmisc.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the server-side misc configuration manager routines.
|
|||
|
|
|||
|
PNP_GetVersion
|
|||
|
PNP_GetVersionInternal
|
|||
|
PNP_GetGlobalState
|
|||
|
PNP_SetActiveService
|
|||
|
PNP_QueryArbitratorFreeData
|
|||
|
PNP_QueryArbitratorFreeSize
|
|||
|
PNP_RunDetection
|
|||
|
PNP_Connect
|
|||
|
PNP_Disconnect
|
|||
|
PNP_GetBlockedDriverInfo
|
|||
|
|
|||
|
The following routines are used by the RPC server stubs to allocate and free memory.
|
|||
|
|
|||
|
MIDL_user_allocate
|
|||
|
MIDL_user_free
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Paula Tomlinson (paulat) 6-28-1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User-mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
28-June-1995 paulat
|
|||
|
|
|||
|
Creation and initial implementation.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// includes
|
|||
|
//
|
|||
|
#include "precomp.h"
|
|||
|
#include "umpnpi.h"
|
|||
|
#include "umpnpdat.h"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// global data
|
|||
|
//
|
|||
|
|
|||
|
extern DWORD CurrentServiceState; // current state of the PlugPlay service - DO NOT MODIFY
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_GetVersion(
|
|||
|
IN handle_t hBinding,
|
|||
|
IN OUT WORD * pVersion
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the RPC server entry point, it returns the version
|
|||
|
number for the server-side component.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hBinding Not used.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return the version number, with the major version in the high byte and
|
|||
|
the minor version number in the low byte.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
*pVersion = (WORD)PNP_VERSION;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // PNP_GetVersion
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_GetVersionInternal(
|
|||
|
IN handle_t hBinding,
|
|||
|
IN OUT WORD * pwVersion
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the RPC server entry point, it returns the internal version
|
|||
|
number for the server-side component.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hBinding Not used.
|
|||
|
|
|||
|
pwVersion Receives the internal cfgmgr32 version number, returns the
|
|||
|
internal server version number, with the major version in the
|
|||
|
high byte and the minor version number in the low byte.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return CR_SUCCESS if the function succeeds, otherwise it returns one
|
|||
|
of the CR_* errors.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
|
|||
|
try {
|
|||
|
*pwVersion = (WORD)PNP_VERSION_INTERNAL;
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // PNP_GetVersionInternal
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_GetGlobalState(
|
|||
|
IN handle_t hBinding,
|
|||
|
OUT PULONG pulState,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the RPC server entry point, it returns the Global State of the
|
|||
|
Configuration Manager.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hBinding Not used.
|
|||
|
|
|||
|
pulState Returns the current global state.
|
|||
|
|
|||
|
ulFlags Not used, must be zero.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return CR_SUCCESS if the function succeeds, otherwise it returns one
|
|||
|
of the CR_* errors.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
return CR_INVALID_FLAG;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
*pulState =
|
|||
|
CM_GLOBAL_STATE_CAN_DO_UI |
|
|||
|
CM_GLOBAL_STATE_SERVICES_AVAILABLE;
|
|||
|
|
|||
|
if ((CurrentServiceState == SERVICE_STOP_PENDING) ||
|
|||
|
(CurrentServiceState == SERVICE_STOPPED)) {
|
|||
|
*pulState |= CM_GLOBAL_STATE_SHUTTING_DOWN;
|
|||
|
}
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // PNP_GetGlobalState
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_SetActiveService(
|
|||
|
IN handle_t hBinding,
|
|||
|
IN LPCWSTR pszService,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is currently not an rpc routine, it is called directly
|
|||
|
and privately by the service controller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hBinding RPC binding handle, not used.
|
|||
|
|
|||
|
pszService Specifies the service name.
|
|||
|
|
|||
|
ulFlags Either PNP_SERVICE_STARTED or PNP_SERVICE_STOPPED.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return CR_SUCCESS if the function succeeds, otherwise it returns one
|
|||
|
of the CR_* errors.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
ULONG ulSize = 0, ulStatus = 0;
|
|||
|
LPWSTR pDeviceList = NULL, pszDevice = NULL;
|
|||
|
HKEY hKey = NULL, hControlKey = NULL;
|
|||
|
WCHAR RegStr[MAX_PATH];
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (pszService == NULL) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if ((ulFlags != PNP_SERVICE_STOPPED) &&
|
|||
|
(ulFlags != PNP_SERVICE_STARTED)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// not handling stops right now, everything beyond here assumes
|
|||
|
// the service is starting (or at least it attempted to start)
|
|||
|
//
|
|||
|
if (ulFlags == PNP_SERVICE_STOPPED) {
|
|||
|
goto Clean0; // not handling this right now
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// retreive the list of devices that this service is controlling
|
|||
|
//
|
|||
|
Status = PNP_GetDeviceListSize(NULL, pszService, &ulSize,
|
|||
|
CM_GETIDLIST_FILTER_SERVICE);
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
pDeviceList = HeapAlloc(ghPnPHeap, 0, ulSize * sizeof(WCHAR));
|
|||
|
if (pDeviceList == NULL) {
|
|||
|
Status = CR_OUT_OF_MEMORY;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
Status = PNP_GetDeviceList(NULL, pszService, pDeviceList, &ulSize,
|
|||
|
CM_GETIDLIST_FILTER_SERVICE);
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// set the ActiveService value for each device
|
|||
|
//
|
|||
|
for (pszDevice = pDeviceList;
|
|||
|
*pszDevice;
|
|||
|
pszDevice += lstrlen(pszDevice) + 1) {
|
|||
|
|
|||
|
wsprintf(RegStr, TEXT("%s\\%s"),
|
|||
|
pszRegPathEnum,
|
|||
|
pszDevice);
|
|||
|
|
|||
|
//
|
|||
|
// open the device instance key
|
|||
|
//
|
|||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegStr, 0, KEY_ALL_ACCESS,
|
|||
|
&hKey) == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// open/create the volatile Control key
|
|||
|
//
|
|||
|
if (RegCreateKeyEx(hKey, pszRegKeyDeviceControl, 0, NULL,
|
|||
|
REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL,
|
|||
|
&hControlKey, NULL) == ERROR_SUCCESS) {
|
|||
|
|
|||
|
RegSetValueEx(hControlKey, pszRegValueActiveService,
|
|||
|
0, REG_SZ, (LPBYTE)pszService,
|
|||
|
(lstrlen(pszService) + 1) * sizeof(WCHAR));
|
|||
|
|
|||
|
//
|
|||
|
// set the statusflag to DN_STARTED
|
|||
|
//
|
|||
|
SetDeviceStatus(pszDevice, DN_STARTED, 0);
|
|||
|
|
|||
|
RegCloseKey(hControlKey);
|
|||
|
hControlKey = NULL;
|
|||
|
}
|
|||
|
|
|||
|
RegCloseKey(hKey);
|
|||
|
hKey = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (pDeviceList != NULL) {
|
|||
|
HeapFree(ghPnPHeap, 0, pDeviceList);
|
|||
|
}
|
|||
|
if (hKey != NULL) {
|
|||
|
RegCloseKey(hKey);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // PNP_SetActiveService
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//--------------------------------------------------------------------
|
|||
|
// Stub server side CM routines - not implemented yet
|
|||
|
//--------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_QueryArbitratorFreeData(
|
|||
|
IN handle_t hBinding,
|
|||
|
OUT LPBYTE pData,
|
|||
|
IN ULONG ulDataLen,
|
|||
|
IN LPCWSTR pszDeviceID,
|
|||
|
IN RESOURCEID ResourceID,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
UNREFERENCED_PARAMETER(pData);
|
|||
|
UNREFERENCED_PARAMETER(ulDataLen);
|
|||
|
UNREFERENCED_PARAMETER(pszDeviceID);
|
|||
|
UNREFERENCED_PARAMETER(ResourceID);
|
|||
|
UNREFERENCED_PARAMETER(ulFlags);
|
|||
|
|
|||
|
return CR_CALL_NOT_IMPLEMENTED;
|
|||
|
|
|||
|
} // PNP_QueryArbitratorFreeData
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_QueryArbitratorFreeSize(
|
|||
|
IN handle_t hBinding,
|
|||
|
OUT PULONG pulSize,
|
|||
|
IN LPCWSTR pszDeviceID,
|
|||
|
IN RESOURCEID ResourceID,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
UNREFERENCED_PARAMETER(pszDeviceID);
|
|||
|
UNREFERENCED_PARAMETER(ResourceID);
|
|||
|
UNREFERENCED_PARAMETER(ulFlags);
|
|||
|
|
|||
|
try {
|
|||
|
if (ARGUMENT_PRESENT(pulSize)) {
|
|||
|
*pulSize = 0;
|
|||
|
}
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
NOTHING;
|
|||
|
}
|
|||
|
|
|||
|
return CR_CALL_NOT_IMPLEMENTED;
|
|||
|
|
|||
|
} // PNP_QueryArbitratorFreeSize
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_RunDetection(
|
|||
|
IN handle_t hBinding,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
UNREFERENCED_PARAMETER(ulFlags);
|
|||
|
|
|||
|
return CR_CALL_NOT_IMPLEMENTED;
|
|||
|
|
|||
|
} // PNP_RunDetection
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_Connect(
|
|||
|
IN PNP_HANDLE UNCServerName
|
|||
|
)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(UNCServerName);
|
|||
|
return CR_SUCCESS;
|
|||
|
|
|||
|
} // PNP_Connect
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_Disconnect(
|
|||
|
IN PNP_HANDLE UNCServerName
|
|||
|
)
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(UNCServerName);
|
|||
|
return CR_SUCCESS;
|
|||
|
|
|||
|
} // PNP_Disconnect
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
PNP_GetBlockedDriverInfo(
|
|||
|
IN handle_t hBinding,
|
|||
|
OUT LPBYTE Buffer,
|
|||
|
OUT PULONG pulTransferLen,
|
|||
|
IN OUT PULONG pulLength,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the RPC server entry point for the CMP_GetBlockedDriverInfo routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hBinding - RPC binding handle, not used.
|
|||
|
|
|||
|
Buffer - Supplies the address of the buffer that receives the
|
|||
|
list. Can be NULL when simply retrieving data size.
|
|||
|
|
|||
|
pulTransferLen - Used by stubs, indicates how much data (in bytes) to
|
|||
|
copy back into user buffer.
|
|||
|
|
|||
|
pulLength - Parameter passed in by caller, on entry it contains the
|
|||
|
size (in bytes) of the buffer, on exit it contains either
|
|||
|
the number of bytes transferred to the caller's buffer (if
|
|||
|
a transfer occured) or else the size of buffer required to
|
|||
|
hold the list.
|
|||
|
|
|||
|
ulFlags Not used, must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Return CR_SUCCESS if the function succeeds, otherwise it returns one of the
|
|||
|
CR_* errors.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
NTSTATUS ntStatus;
|
|||
|
PLUGPLAY_CONTROL_BLOCKED_DRIVER_DATA controlData;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(hBinding);
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// Validate parameters
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(pulTransferLen)) ||
|
|||
|
(!ARGUMENT_PRESENT(pulLength))) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if ((!ARGUMENT_PRESENT(Buffer)) && (*pulLength != 0)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We should never have both arguments pointing to the same memory...
|
|||
|
//
|
|||
|
ASSERT(pulTransferLen != pulLength);
|
|||
|
|
|||
|
//
|
|||
|
// ...but if we do, fail the call.
|
|||
|
//
|
|||
|
if (pulTransferLen == pulLength) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Retrieve the blocked driver list via kernel-mode.
|
|||
|
//
|
|||
|
|
|||
|
memset(&controlData, 0, sizeof(PLUGPLAY_CONTROL_BLOCKED_DRIVER_DATA));
|
|||
|
controlData.Buffer = Buffer;
|
|||
|
controlData.BufferLength = *pulLength;
|
|||
|
controlData.Flags = ulFlags;
|
|||
|
|
|||
|
ntStatus = NtPlugPlayControl(PlugPlayControlGetBlockedDriverList,
|
|||
|
&controlData,
|
|||
|
sizeof(controlData));
|
|||
|
|
|||
|
if (NT_SUCCESS(ntStatus)) {
|
|||
|
*pulTransferLen = *pulLength; // Transfer everything back
|
|||
|
*pulLength = controlData.BufferLength; // Length of valid data
|
|||
|
|
|||
|
} else if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
|
|||
|
*pulTransferLen = 0; // Nothing to transfer
|
|||
|
*pulLength = controlData.BufferLength;
|
|||
|
Status = CR_BUFFER_SMALL;
|
|||
|
|
|||
|
} else {
|
|||
|
*pulLength = *pulTransferLen = 0; // Nothing to transfer
|
|||
|
Status = MapNtStatusToCmError(ntStatus);
|
|||
|
}
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // PNP_GetBlockedDriverInfo
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void __RPC_FAR * __RPC_USER
|
|||
|
MIDL_user_allocate(
|
|||
|
size_t cBytes
|
|||
|
)
|
|||
|
{
|
|||
|
return HeapAlloc(ghPnPHeap, 0, cBytes);
|
|||
|
|
|||
|
} // MIDL_user_allocate
|
|||
|
|
|||
|
|
|||
|
void __RPC_USER
|
|||
|
MIDL_user_free(
|
|||
|
void __RPC_FAR * pBuffer
|
|||
|
)
|
|||
|
{
|
|||
|
HeapFree(ghPnPHeap, 0, pBuffer);
|
|||
|
|
|||
|
} // MIDL_user_free
|