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
|