Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

711 lines
17 KiB

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
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_InitDetection
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"
#pragma hdrstop
#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);
try {
//
// validate parameters
//
if (INVALID_FLAGS(ulFlags, 0)) {
Status = CR_INVALID_FLAG;
goto Clean0;
}
//
// The following CM global state flags are always set.
//
*pulState =
CM_GLOBAL_STATE_CAN_DO_UI |
CM_GLOBAL_STATE_SERVICES_AVAILABLE;
//
// If the service is shutting down, specify the corresponding CM global
// state flag.
//
if ((CurrentServiceState == SERVICE_STOP_PENDING) ||
(CurrentServiceState == SERVICE_STOPPED)) {
*pulState |= CM_GLOBAL_STATE_SHUTTING_DOWN;
}
Clean0:
NOTHING;
} 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;
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) {
Status = CR_SUCCESS;
goto Clean0;
}
//
// 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) {
if (FAILED(StringCchPrintf(
RegStr,
SIZECHARS(RegStr),
L"%s\\%s",
pszRegPathEnum,
pszDevice))) {
continue;
}
//
// 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
)
{
CONFIGRET Status;
UNREFERENCED_PARAMETER(hBinding);
UNREFERENCED_PARAMETER(pszDeviceID);
UNREFERENCED_PARAMETER(ResourceID);
UNREFERENCED_PARAMETER(ulFlags);
try {
if (ARGUMENT_PRESENT(pulSize)) {
*pulSize = 0;
}
Status = CR_CALL_NOT_IMPLEMENTED;
} except(EXCEPTION_EXECUTE_HANDLER) {
Status = CR_FAILURE;
}
return Status;
} // PNP_QueryArbitratorFreeSize
//---------------------------------------------------------------------------
// Debugging interface - initiate detection through private debug interface
//---------------------------------------------------------------------------
CONFIGRET
PNP_InitDetection(
handle_t hBinding
)
/*++
Routine Description:
This routine is a private debugging interface to initiate device detection.
Arguments:
hBinding - RPC binding handle.
Return Value:
Currently returns CR_CALL_NOT_IMPLEMENTED.
Notes:
Previously, this routine would kick off the InitializePnPManager thread on
checked builds only.
Presumably, this dates way back to a time when this routine actually sought
out non-configured devices and initiated installation on them (as is
currently done at the start of the ThreadProc_DeviceInstall thread procedure
routine).
Since InitializePnPManager no longer does this, so this behavior has been
removed altogether. It is currently never valid to perform initialization
more than once, however this routine may be used to implement detection of
non-configured devices.
--*/
{
//
// Verify client "execute" access
//
if (!VerifyClientAccess(hBinding,
PLUGPLAY_EXECUTE)) {
return CR_ACCESS_DENIED;
}
//
// Verify client privilege
//
if (!VerifyClientPrivilege(hBinding,
SE_LOAD_DRIVER_PRIVILEGE,
L"Plug and Play Action (not implemeted)")) {
return CR_ACCESS_DENIED;
}
return CR_CALL_NOT_IMPLEMENTED;
} // PNP_InitDetection
CONFIGRET
PNP_RunDetection(
IN handle_t hBinding,
IN ULONG ulFlags
)
{
UNREFERENCED_PARAMETER(ulFlags);
//
// Verify client "execute" access
//
if (!VerifyClientAccess(hBinding,
PLUGPLAY_EXECUTE)) {
return CR_ACCESS_DENIED;
}
//
// Verify client privilege
//
if (!VerifyClientPrivilege(hBinding,
SE_LOAD_DRIVER_PRIVILEGE,
L"Plug and Play Action (not implemeted)")) {
return CR_ACCESS_DENIED;
}
return CR_CALL_NOT_IMPLEMENTED;
} // PNP_RunDetection
CONFIGRET
PNP_Connect(
IN PNP_HANDLE UNCServerName
)
{
//
// Note that although this routine is listed in the PNP RPC interface, it
// uses automatic binding, and does not reference any implicit binding handle
// (which is how the interface has come to be defined). As such, it is not
// callable through the existing PNP RPC interface.
//
UNREFERENCED_PARAMETER(UNCServerName);
return CR_CALL_NOT_IMPLEMENTED;
} // PNP_Connect
CONFIGRET
PNP_Disconnect(
IN PNP_HANDLE UNCServerName
)
{
//
// Note that although this routine is listed in the PNP RPC interface, it
// uses automatic binding, and does not reference any implicit binding handle
// (which is how the interface has come to be defined). As such, it is not
// callable through the existing PNP RPC interface.
//
UNREFERENCED_PARAMETER(UNCServerName);
return CR_CALL_NOT_IMPLEMENTED;
} // 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