windows-nt/Source/XPSP1/NT/base/pnp/umpnpmgr/rmisc.c

590 lines
13 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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