2163 lines
57 KiB
C
2163 lines
57 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995-2001 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
devnode.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the API routines that operate directly on device
|
|||
|
instances (or DevNodes, in Win95 terminology).
|
|||
|
|
|||
|
CM_Create_DevNode
|
|||
|
CM_Setup_DevNode
|
|||
|
CM_Disable_DevNode
|
|||
|
CM_Enable_DevNode
|
|||
|
CM_Get_DevNode_Status
|
|||
|
CM_Set_DevNode_Problem
|
|||
|
CM_Reenumerate_DevNode
|
|||
|
CM_Query_And_Remove_SubTree
|
|||
|
CM_Uninstall_DevNode
|
|||
|
CM_Request_Device_Eject
|
|||
|
CM_Add_ID
|
|||
|
CM_Register_Device_Driver
|
|||
|
|
|||
|
This module also contains the following API routines which are
|
|||
|
not implemented.
|
|||
|
|
|||
|
CM_Move_DevNode
|
|||
|
CM_Query_Remove_Subtree
|
|||
|
CM_Remove_SubTree
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Paula Tomlinson (paulat) 6-20-1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
6-Jun-1995 paulat
|
|||
|
|
|||
|
Creation and initial implementation.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// includes
|
|||
|
//
|
|||
|
#include "precomp.h"
|
|||
|
#include "cfgi.h"
|
|||
|
|
|||
|
#include "setupapi.h"
|
|||
|
#include "spapip.h"
|
|||
|
#include <pnpmgr.h>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Create_DevNode_ExW(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_W pDeviceID,
|
|||
|
IN DEVINST dnParent,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine creates a new device instance in the hardware tree.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pdnDevNode Supplies the address of the variable that receives a handle
|
|||
|
to the new device instance.
|
|||
|
|
|||
|
pDeviceID Supplies a pointer to a NULL-terminated string specifying
|
|||
|
the device instance ID for this new device instance. This
|
|||
|
is the registry path (relative to the Enum branch) where
|
|||
|
this device instance will be located (e.g., Root\*PNP0500\0000).
|
|||
|
In Windows NT, this parameter is not optional.
|
|||
|
|
|||
|
dnParent Supplies the handle of the device instance that is the parent
|
|||
|
of the device instance being created.
|
|||
|
|
|||
|
ulFlags Supplies flags specifying options for the creation of the
|
|||
|
device instance. May be one of the following values:
|
|||
|
|
|||
|
CM_CREATE_DEVNODE_NORMAL
|
|||
|
Create the device instance now, and perform installation
|
|||
|
for it at a later time.
|
|||
|
CM_CREATE_DEVNODE_NO_WAIT_INSTALL
|
|||
|
Create the device instance, and perform installation for
|
|||
|
it immediately.
|
|||
|
CM_CREATE_DEVNODE_PHANTOM
|
|||
|
Create a phantom device instance (i.e., a handle to a
|
|||
|
device instance that is not alive as far as the ConfigMgr
|
|||
|
APIs are concerned). This may be used for CM APIs that
|
|||
|
require a devnode handle, but for which no real devnode
|
|||
|
currently exists (e.g., registry property APIs). This
|
|||
|
flag may not be specified with CR_CREATE_DEVNODE_NORMAL
|
|||
|
or CR_CREATE_DEVNODE_NO_WAIT_INSTALL. A phantom devnode
|
|||
|
created in this manner is not accessible to other callers
|
|||
|
(i.e., CM_Locate_DevNode won't find it). However, callers
|
|||
|
attempting to create a devnode with the same name as this
|
|||
|
phantom devnode will not be able to do so (they will get
|
|||
|
CR_ALREADY_SUCH_DEVNODE).
|
|||
|
CM_CREATE_DEVNODE_GENERATE_ID
|
|||
|
Create a Root-enumerated devnode using a unique device
|
|||
|
instance ID generated from the supplied device ID in
|
|||
|
pDeviceID. If this flag is set, then pDeviceID is assumed
|
|||
|
to contain simply a device ID (i.e., no enumerator key
|
|||
|
prefix, and no device instance suffix). A unique 4-digit,
|
|||
|
base-10 identifier string will be created under
|
|||
|
Enum\Root\<pDeviceID>, and the devnode will be created
|
|||
|
based on that device instance ID. For instance, to add a
|
|||
|
new legacy COM port devnode, this API would be called with
|
|||
|
a pDeviceID of *PNP0500. Assuming there was already one
|
|||
|
COM port instance in the registry (instance 0000), the new
|
|||
|
device instance ID would be: Root\*PNP0500\0001
|
|||
|
The caller may find out what device instance name was
|
|||
|
generated by calling CM_Get_Device_ID with the devnode
|
|||
|
returned from this API.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_ALREADY_SUCH_DEVNODE,
|
|||
|
CR_INVALID_DEVICE_ID,
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_INVALID_POINTER, or
|
|||
|
CR_OUT_OF_MEMORY.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR ParentID[MAX_DEVICE_ID_LEN];
|
|||
|
WCHAR szNewDeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen=MAX_DEVICE_ID_LEN;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (!ARGUMENT_PRESENT(pdnDevInst)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (dnParent == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// the length of the supplied device id string must be shorter than
|
|||
|
// MAX_DEVICE_ID_LEN chars so that there is also room for the NULL term
|
|||
|
// char in a buffer of this size. (many of the CM_ APIs make different
|
|||
|
// assumptions about the consideration of the NULL term char in
|
|||
|
// MAX_DEVICE_ID_LEN; account for the NULL term char to be safe)
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(pDeviceID)) ||
|
|||
|
(lstrlen(pDeviceID) >= MAX_DEVICE_ID_LEN)) {
|
|||
|
Status = CR_INVALID_DEVICE_ID;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_CREATE_DEVNODE_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Windows NT 5.0 does not support CM_CREATE_DEVNODE_NO_WAIT_INSTALL
|
|||
|
//
|
|||
|
if (ulFlags & CM_CREATE_DEVNODE_NO_WAIT_INSTALL) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the caller's devnode. This will have the side effect of
|
|||
|
// generating an exception before we actually do anything if the caller
|
|||
|
// supplied a bogus address.
|
|||
|
//
|
|||
|
*pdnDevInst = 0;
|
|||
|
|
|||
|
//
|
|||
|
// retreive device instance string that corresponds to dnParent
|
|||
|
// (note that this is not optional, even a first level device instance
|
|||
|
// has a parent (the root device instance)
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnParent,ParentID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(ParentID)) {
|
|||
|
Status = CR_INVALID_DEVNODE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// make sure the new device instance is properly formatted
|
|||
|
//
|
|||
|
CopyFixedUpDeviceId(szNewDeviceID, pDeviceID, lstrlen(pDeviceID));
|
|||
|
|
|||
|
//
|
|||
|
// If not requesting instance generation, then it must be a
|
|||
|
// valid device instance path.
|
|||
|
//
|
|||
|
if (!(ulFlags & CM_CREATE_DEVINST_GENERATE_ID)) {
|
|||
|
if ((!*szNewDeviceID) ||
|
|||
|
(!IsLegalDeviceId(szNewDeviceID))) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_CreateDevInst(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
szNewDeviceID, // device instance to create
|
|||
|
ParentID, // parent device instance
|
|||
|
MAX_DEVICE_ID_LEN, // max length of szNewDeviceID
|
|||
|
ulFlags); // flags
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_CreateDevInst caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// assign a unique device instance value to the newly created device
|
|||
|
// instance
|
|||
|
//
|
|||
|
|
|||
|
ASSERT(*szNewDeviceID && IsLegalDeviceId(szNewDeviceID));
|
|||
|
|
|||
|
*pdnDevInst = pSetupStringTableAddString(hStringTable, szNewDeviceID,
|
|||
|
STRTAB_CASE_SENSITIVE);
|
|||
|
|
|||
|
if (*pdnDevInst == 0) {
|
|||
|
Status = CR_NO_SUCH_DEVNODE;
|
|||
|
}
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Create_DevNode_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Move_DevNode_Ex(
|
|||
|
IN DEVINST dnFromDevInst,
|
|||
|
IN DEVINST dnToDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine replaces a root-enumerated device instance by the valid
|
|||
|
non-root-enumerated device instance. The device installer uses this
|
|||
|
service when it detects that a non-root enumerated device instance is
|
|||
|
really the same as its root enumerated counterpart. This API migrates
|
|||
|
the old device instance to the new location, and marks the old location
|
|||
|
as having a problem.
|
|||
|
|
|||
|
** THIS ROUTINE IS NOT IMPLEMENTED **
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnFromDevNode Supplies the handle of the device instance that has been
|
|||
|
root enumerated.
|
|||
|
|
|||
|
dnToDevNode Supplies the handle of the device instance that is a
|
|||
|
reenumeration (duplicate) of the root device instance.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_OUT_OF_MEMORY.
|
|||
|
(Windows 95 may also return CR_NOT_AT_APPY_TIME.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(dnFromDevInst);
|
|||
|
UNREFERENCED_PARAMETER(dnToDevInst);
|
|||
|
UNREFERENCED_PARAMETER(ulFlags);
|
|||
|
UNREFERENCED_PARAMETER(hMachine);
|
|||
|
|
|||
|
return CR_CALL_NOT_IMPLEMENTED;
|
|||
|
|
|||
|
} // CM_Move_DevNode_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Setup_DevNode_Ex(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reenables and configures a specified device instance or
|
|||
|
retrieves information from its enumerator.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevNode Supplies the handle of the device instance which may be
|
|||
|
reconfigured.
|
|||
|
|
|||
|
ulFlags Supplies a flag indicating the action to take. Can be one
|
|||
|
of the following values:
|
|||
|
|
|||
|
CM_SETUP_DEVNODE_READY
|
|||
|
Reenable the device instance that had a problem.
|
|||
|
|
|||
|
CM_SETUP_DOWNLOAD
|
|||
|
Retrieve information about this device instance
|
|||
|
from its enumerator.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_OUT_OF_MEMORY, or
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen=MAX_DEVICE_ID_LEN;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_SETUP_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_DeviceInstanceAction(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
PNP_DEVINST_SETUP, // requested major action - SETUP
|
|||
|
ulFlags, // requested minor action
|
|||
|
DeviceID, // device instance to create
|
|||
|
NULL); // (not used)
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_DeviceInstanceAction caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Setup_DevNode_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Disable_DevNode_Ex(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine disables a device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevNode Supplies the handle of the device instance to be disabled.
|
|||
|
|
|||
|
ulFlags May be one of CM_DISABLE_BITS.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_NOT_DISABLEABLE, or
|
|||
|
CR_INVALID_DEVNODE.
|
|||
|
(Note, Windows 95 also may return CR_NOT_AT_APPY_TIME.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
BOOL Success;
|
|||
|
PNP_VETO_TYPE vetoType, *pVetoType;
|
|||
|
WCHAR vetoName[MAX_DEVICE_ID_LEN], *pszVetoName;
|
|||
|
ULONG ulNameLength;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_DISABLE_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (ulFlags & CM_DISABLE_UI_NOT_OK) {
|
|||
|
vetoType = PNP_VetoTypeUnknown;
|
|||
|
pVetoType = &vetoType;
|
|||
|
vetoName[0] = L'\0';
|
|||
|
pszVetoName = &vetoName[0];
|
|||
|
ulNameLength = MAX_DEVICE_ID_LEN;
|
|||
|
} else {
|
|||
|
pVetoType = NULL;
|
|||
|
pszVetoName = NULL;
|
|||
|
ulNameLength = 0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_DisableDevInst(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
DeviceID, // device instance to create
|
|||
|
pVetoType,
|
|||
|
pszVetoName,
|
|||
|
ulNameLength,
|
|||
|
ulFlags); // requested minor action (not used)
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_DisableDevInst caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Disable_DevNode_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Enable_DevNode_Ex(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine enables a device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevNode Supplies the handle of the device instance to enable.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_FLAG or
|
|||
|
CR_INVALID_DEVNODE.
|
|||
|
(Note, Windows 95 also may return CR_NOT_AT_APPY_TIME.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_DeviceInstanceAction(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
PNP_DEVINST_ENABLE, // requested major action - ENABLE
|
|||
|
ulFlags, // requested minor action (not used)
|
|||
|
DeviceID, // device instance to create
|
|||
|
NULL); // (not used)
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_DeviceInstanceAction caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Enable_DevNode_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_DevNode_Status_Ex(
|
|||
|
OUT PULONG pulStatus,
|
|||
|
OUT PULONG pulProblemNumber,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the status of a device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pulStatus Supplies the address of the variable that receives the
|
|||
|
status flag of the device instance. Can be a combination
|
|||
|
of the DN_* values.
|
|||
|
|
|||
|
pulProblemNumber Supplies the address of the variable that receives an
|
|||
|
identifier indicating the problem. Can be one of the
|
|||
|
CM_PROB_* values.
|
|||
|
|
|||
|
|
|||
|
dnDevNode Supplies the handle of the device instance for which
|
|||
|
to retrieve status.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG, or
|
|||
|
CR_INVALID_POINTER.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if ((!ARGUMENT_PRESENT(pulStatus)) ||
|
|||
|
(!ARGUMENT_PRESENT(pulProblemNumber))) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetDeviceStatus(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
DeviceID, // device instance to get status for
|
|||
|
pulStatus, // return StatusFlags here
|
|||
|
pulProblemNumber, // return Problem here
|
|||
|
ulFlags); // (not used)
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetDeviceStatus caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_DevNode_Status_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Set_DevNode_Problem_Ex(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulProblem,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine clears or set the problem of a device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevNode Supplies the handle of the device instance for which
|
|||
|
to set the problem.
|
|||
|
|
|||
|
ulProblem Supplies the new problem value. Can be one of the
|
|||
|
CM_PROB_* values. If zero, the problem is cleared.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_SET_DEVNODE_PROBLEM_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_SetDeviceProblem(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
DeviceID, // device instance
|
|||
|
ulProblem, // specifies new Problem
|
|||
|
ulFlags); // (not used)
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_SetDeviceProblem caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Set_DevNode_Problem_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Reenumerate_DevNode_Ex(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine causes the specified device instance to be enumerated
|
|||
|
(if it is enumerable).
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevNode Supplies the handle of the device instance to be enumerated.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is CR_INVALID_FLAG (i.e., the
|
|||
|
function does not fail). The device instance is not checked for validity.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_REENUMERATE_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_DeviceInstanceAction(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
PNP_DEVINST_REENUMERATE, // requested major action-REMOVESUBTREE
|
|||
|
ulFlags, // requested minor action
|
|||
|
DeviceID, // device instance subtree to remove
|
|||
|
NULL); // (not used)
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_DeviceInstanceAction caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Reenumerate_DevNode_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Query_And_Remove_SubTree_ExW(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPWSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks whether a device instance and its progeny can be
|
|||
|
removed. If the query isn't vetoed then a remove is done. The replaces
|
|||
|
the old CM_Query_Remove_SubTree followed by CM_Remove_SubTree.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnAncestor Supplies the handle of the device instance at the root of
|
|||
|
the subtree to be removed.
|
|||
|
|
|||
|
ulFlags Specifies whether UI should be presented for
|
|||
|
this action. Can be one of the following values:
|
|||
|
|
|||
|
CM_REMOVE_UI_OK - OK to present UI for query-removal.
|
|||
|
CM_REMOVE_UI_NOT_OK - Don't present UI for query-removal.
|
|||
|
CM_REMOVE_NO_RESTART - Don't attempt to restart the devnode.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_REMOVE_VETOED. (Windows 95 may also return CR_NOT_AT_APPY_TIME.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnAncestor == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_REMOVE_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
pSetupStringTableStringFromIdEx(hStringTable, dnAncestor,pDeviceID,&ulLen);
|
|||
|
|
|||
|
ASSERT(pDeviceID && *pDeviceID && IsLegalDeviceId(pDeviceID));
|
|||
|
|
|||
|
if (pDeviceID == NULL || INVALID_DEVINST(pDeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (ulNameLength == 0) {
|
|||
|
pszVetoName = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (pszVetoName != NULL) {
|
|||
|
*pszVetoName = L'\0';
|
|||
|
}
|
|||
|
|
|||
|
if (pVetoType != NULL) {
|
|||
|
*pVetoType = PNP_VetoTypeUnknown;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_QueryRemove(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
pDeviceID, // device instance subtree to remove
|
|||
|
pVetoType,
|
|||
|
pszVetoName,
|
|||
|
ulNameLength,
|
|||
|
ulFlags);
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_QueryRemove caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Query_And_Remove_SubTree_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Query_Remove_SubTree_Ex(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks whether a device instance and its progeny can be
|
|||
|
removed. This API must be called before calling CM_Remove_SubTree to
|
|||
|
make sure applications prepare for the removal of the device or to
|
|||
|
give the applications a chance to deny the request to remove the device.
|
|||
|
If the removal happens ?surprise style? (i.e., there?s no advanced
|
|||
|
warning or chance to veto), then this API should not be called before
|
|||
|
calling CM_Remove_SubTree.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnAncestor Supplies the handle of the device instance at the root of
|
|||
|
the subtree to be removed.
|
|||
|
|
|||
|
ulFlags Specifies whether UI should be presented for
|
|||
|
this action. Can be one of the following values:
|
|||
|
|
|||
|
CM_QUERY_REMOVE_UI_OK - OK to present UI for query-removal.
|
|||
|
CM_QUERY_REMOVE_UI_NOT_OK -Don't present UI for query-removal.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_REMOVE_VETOED. (Windows 95 may also return CR_NOT_AT_APPY_TIME.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(dnAncestor);
|
|||
|
UNREFERENCED_PARAMETER(ulFlags);
|
|||
|
UNREFERENCED_PARAMETER(hMachine);
|
|||
|
|
|||
|
return CR_CALL_NOT_IMPLEMENTED;
|
|||
|
|
|||
|
} // CM_Query_Remove_SubTree_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Remove_SubTree_Ex(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine removes a device instance and its children from the
|
|||
|
running system. This API notifies each device instance in the subtree
|
|||
|
of the dnAncestor parameter of the device's removal. (On Windows NT,
|
|||
|
this means that each driver/service controlling a device in this
|
|||
|
subtree receives a device removal notification.)
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnAncestor Supplies the handle of the device instance that is being removed.
|
|||
|
|
|||
|
ulFlags Must be either CM_REMOVE_UI_OK or CM_REMOVE_UI_NOT_OK.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
** PRESENTLY, ALWAYS RETURNS CR_CALL_NOT_IMPLEMENTED **
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_DEVNODE or
|
|||
|
CR_INVALID_FLAG.
|
|||
|
(Windows 95 may also return CR_NOT_AT_APPY_TIME.)
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(dnAncestor);
|
|||
|
UNREFERENCED_PARAMETER(ulFlags);
|
|||
|
UNREFERENCED_PARAMETER(hMachine);
|
|||
|
|
|||
|
return CR_CALL_NOT_IMPLEMENTED;
|
|||
|
|
|||
|
} // CM_Remove_SubTree_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Uninstall_DevNode_Ex(
|
|||
|
IN DEVNODE dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine uninstalls a device instance (i.e., deletes its registry
|
|||
|
key(s) in the Enum branch). This API can only be called for phantom
|
|||
|
device instances, and the handle supplied is invalid after the call.
|
|||
|
This API does not attempt to delete all possible storage locations
|
|||
|
associated with the device instance. It will do a recursive delete on
|
|||
|
the devnode key, so that any subkeys will be removed. It will also
|
|||
|
delete the devnode key (and any subkeys) located in the Enum branch
|
|||
|
of each hardware profile. It will not delete any software keys or user
|
|||
|
keys (CM_Delete_DevNode_Key must be called to do that before calling
|
|||
|
this API).
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnPhantom Handle of a phantom device instance to uninstall. This
|
|||
|
handle is typically retrieved by a call to CM_Locate_DevNode
|
|||
|
or CM_Create_DevNode.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG, or
|
|||
|
CR_REGISTRY_ERROR
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
WCHAR szParentKey[MAX_CM_PATH], szChildKey[MAX_CM_PATH],
|
|||
|
DeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_UninstallDevInst(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
DeviceID, // device instance to uninstall
|
|||
|
ulFlags); // (unused)
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_UninstallDevInst caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
// after deleting the main hw key and the config specific hw keys,
|
|||
|
// cleanup the user hw key, which can only be done on the client
|
|||
|
// side.
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
//
|
|||
|
// form the user hardware registry key path
|
|||
|
//
|
|||
|
Status = GetDevNodeKeyPath(hBinding, DeviceID,
|
|||
|
CM_REGISTRY_HARDWARE | CM_REGISTRY_USER,
|
|||
|
0, szParentKey, szChildKey);
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// delete the specified private user key
|
|||
|
//
|
|||
|
Status = DeletePrivateKey(HKEY_CURRENT_USER, szParentKey, szChildKey);
|
|||
|
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Uninstall_DevNode_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Request_Device_Eject_ExW(
|
|||
|
IN DEVNODE dnDevInst,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPWSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevInst Handle of a device instance. This handle is typically
|
|||
|
retrieved by a call to CM_Locate_DevNode or CM_Create_DevNode.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is one of the following:
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG, or
|
|||
|
CR_REGISTRY_ERROR
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (ulNameLength == 0) {
|
|||
|
pszVetoName = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (pszVetoName != NULL) {
|
|||
|
*pszVetoName = L'\0';
|
|||
|
}
|
|||
|
|
|||
|
if (pVetoType != NULL) {
|
|||
|
*pVetoType = PNP_VetoTypeUnknown;
|
|||
|
}
|
|||
|
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// no flags are currently valid
|
|||
|
//
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_RequestDeviceEject(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
DeviceID, // device instance subtree to remove
|
|||
|
pVetoType,
|
|||
|
pszVetoName,
|
|||
|
ulNameLength,
|
|||
|
ulFlags);
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_RequestDeviceEject caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Request_Device_Eject_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Add_ID_ExW(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN PWSTR pszID,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
This routine adds a device ID to a device instance's HardwareID or
|
|||
|
CompatibleIDs list.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevInst Handle of a device instance. This handle is typically
|
|||
|
retrieved by a call to CM_Locate_DevNode or CM_Create_DevNode.
|
|||
|
|
|||
|
pszID Supplies a pointer to a NULL-terminated string specifying
|
|||
|
the ID to be added.
|
|||
|
|
|||
|
ulFlags Supplies flags for the ID. May be one of the following values:
|
|||
|
|
|||
|
ID Type Flags:
|
|||
|
CM_ADD_ID_HARDWARE The specified ID is a hardware ID. Add
|
|||
|
it to the device instance's HardwareID
|
|||
|
list.
|
|||
|
CM_ADD_ID_COMPATIBLE The specified ID is a compatible ID.
|
|||
|
Add it to the device instance's
|
|||
|
CompatibleIDs list.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is a CR error code.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(pszID)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_ADD_ID_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_AddID(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
DeviceID, // device instance
|
|||
|
pszID, // id to add
|
|||
|
ulFlags); // hardware or compatible
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_AddID caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Add_ID_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CMAPI
|
|||
|
CONFIGRET
|
|||
|
CM_Register_Device_Driver_Ex(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
This routine registers the device driver for the specified device.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevInst Handle of a device instance. This handle is typically
|
|||
|
retrieved by a call to CM_Locate_DevNode or CM_Create_DevNode.
|
|||
|
|
|||
|
ulFlags Supplies flags for register the driver. May be one of the
|
|||
|
following values:
|
|||
|
|
|||
|
CM_REGISTER_DEVICE_DRIVER_STATIC
|
|||
|
CM_REGISTER_DEVICE_DRIVER_DISABLEABLE
|
|||
|
CM_REGISTER_DEVICE_DRIVER_REMOVABLE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
If the function succeeds, the return value is CR_SUCCESS.
|
|||
|
If the function fails, the return value is a CR error code.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR DeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
ULONG ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_REGISTER_DEVICE_DRIVER_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the device instance ID string associated with the devinst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,DeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(DeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_RegisterDriver(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
DeviceID, // device instance
|
|||
|
ulFlags); // hardware or compatible
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_RegisterDriver caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Register_Device_Driver_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------------------------
|
|||
|
// Local Stubs
|
|||
|
//-------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Create_DevNodeW(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_W pDeviceID,
|
|||
|
IN DEVINST dnParent,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Create_DevNode_ExW(pdnDevInst, pDeviceID, dnParent,
|
|||
|
ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Create_DevNodeA(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_A pDeviceID,
|
|||
|
IN DEVINST dnParent,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Create_DevNode_ExA(pdnDevInst, pDeviceID, dnParent,
|
|||
|
ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Move_DevNode(
|
|||
|
IN DEVINST dnFromDevInst,
|
|||
|
IN DEVINST dnToDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Move_DevNode_Ex(dnFromDevInst, dnToDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Setup_DevNode(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Setup_DevNode_Ex(dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Disable_DevNode(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Disable_DevNode_Ex(dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Enable_DevNode(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Enable_DevNode_Ex(dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_DevNode_Status(
|
|||
|
OUT PULONG pulStatus,
|
|||
|
OUT PULONG pulProblemNumber,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_DevNode_Status_Ex(pulStatus, pulProblemNumber,
|
|||
|
dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Set_DevNode_Problem(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulProblem,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Set_DevNode_Problem_Ex(dnDevInst, ulProblem, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Reenumerate_DevNode(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Reenumerate_DevNode_Ex(dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Query_And_Remove_SubTree(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPWSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Query_And_Remove_SubTree_Ex( dnAncestor,
|
|||
|
pVetoType,
|
|||
|
pszVetoName,
|
|||
|
ulNameLength,
|
|||
|
ulFlags,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Query_And_Remove_SubTreeA(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Query_And_Remove_SubTree_ExA( dnAncestor,
|
|||
|
pVetoType,
|
|||
|
pszVetoName,
|
|||
|
ulNameLength,
|
|||
|
ulFlags,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Remove_SubTree(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Remove_SubTree_Ex(dnAncestor, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Uninstall_DevNode(
|
|||
|
IN DEVNODE dnPhantom,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Uninstall_DevNode_Ex(dnPhantom, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Add_IDW(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN PWSTR pszID,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Add_ID_ExW(dnDevInst, pszID, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Add_IDA(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN PSTR pszID,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Add_ID_ExA(dnDevInst, pszID, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CMAPI
|
|||
|
CONFIGRET
|
|||
|
CM_Register_Device_Driver(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Register_Device_Driver_Ex(dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Query_Remove_SubTree(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Query_Remove_SubTree_Ex(dnAncestor, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Request_Device_EjectW(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPWSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Request_Device_Eject_ExW(dnDevInst,
|
|||
|
pVetoType,
|
|||
|
pszVetoName,
|
|||
|
ulNameLength,
|
|||
|
ulFlags,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Request_Device_EjectA(
|
|||
|
IN DEVNODE dnDevInst,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Request_Device_Eject_ExA( dnDevInst,
|
|||
|
pVetoType,
|
|||
|
pszVetoName,
|
|||
|
ulNameLength,
|
|||
|
ulFlags,
|
|||
|
NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------------------------
|
|||
|
// ANSI STUBS
|
|||
|
//-------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Add_ID_ExA(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN PSTR pszID,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
PWSTR pUniID = NULL;
|
|||
|
|
|||
|
|
|||
|
if (pSetupCaptureAndConvertAnsiArg(pszID, &pUniID) == NO_ERROR) {
|
|||
|
|
|||
|
Status = CM_Add_ID_ExW(dnDevInst,
|
|||
|
pUniID,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
pSetupFree(pUniID);
|
|||
|
|
|||
|
} else {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Add_ID_ExA
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Create_DevNode_ExA(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_A pDeviceID,
|
|||
|
IN DEVINST dnParent,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
PWSTR pUniDeviceID = NULL;
|
|||
|
|
|||
|
|
|||
|
if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pUniDeviceID) == NO_ERROR) {
|
|||
|
|
|||
|
Status = CM_Create_DevNode_ExW(pdnDevInst,
|
|||
|
pUniDeviceID,
|
|||
|
dnParent,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
pSetupFree(pUniDeviceID);
|
|||
|
|
|||
|
} else {
|
|||
|
Status = CR_INVALID_DEVICE_ID;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Create_DevNode_ExA
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Query_And_Remove_SubTree_ExA(
|
|||
|
IN DEVINST dnAncestor,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
PWSTR pUniVetoName = NULL;
|
|||
|
ULONG ulAnsiBufferLen;
|
|||
|
|
|||
|
//
|
|||
|
// validate essential parameters only
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(pszVetoName)) && (ulNameLength != 0)) {
|
|||
|
return CR_INVALID_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
if (ulNameLength != 0) {
|
|||
|
//
|
|||
|
// pass a Unicode buffer instead and convert back to caller's
|
|||
|
// ANSI buffer on return
|
|||
|
//
|
|||
|
pUniVetoName = pSetupMalloc(MAX_VETO_NAME_LENGTH*sizeof(WCHAR));
|
|||
|
if (pUniVetoName == NULL) {
|
|||
|
return CR_OUT_OF_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// call the wide version
|
|||
|
//
|
|||
|
Status = CM_Query_And_Remove_SubTree_ExW(dnAncestor,
|
|||
|
pVetoType,
|
|||
|
pUniVetoName,
|
|||
|
MAX_VETO_NAME_LENGTH,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
|
|||
|
//
|
|||
|
// We should never return a veto name longer than MAX_VETO_NAME_LENGTH.
|
|||
|
//
|
|||
|
ASSERT(Status != CR_BUFFER_SMALL);
|
|||
|
|
|||
|
if (Status == CR_REMOVE_VETOED) {
|
|||
|
//
|
|||
|
// convert the unicode buffer to an ANSI string and copy to the caller's
|
|||
|
// buffer
|
|||
|
//
|
|||
|
ulAnsiBufferLen = ulNameLength;
|
|||
|
Status = PnPUnicodeToMultiByte(pUniVetoName,
|
|||
|
(lstrlenW(pUniVetoName)+1)*sizeof(WCHAR),
|
|||
|
pszVetoName,
|
|||
|
&ulAnsiBufferLen);
|
|||
|
}
|
|||
|
|
|||
|
if (pUniVetoName != NULL) {
|
|||
|
pSetupFree(pUniVetoName);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Query_And_Remove_SubTree_ExA
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Request_Device_Eject_ExA(
|
|||
|
IN DEVNODE dnDevInst,
|
|||
|
OUT PPNP_VETO_TYPE pVetoType,
|
|||
|
OUT LPSTR pszVetoName,
|
|||
|
IN ULONG ulNameLength,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
PWSTR pUniVetoName = NULL;
|
|||
|
ULONG ulAnsiBufferLen;
|
|||
|
|
|||
|
//
|
|||
|
// validate essential parameters only
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(pszVetoName)) && (ulNameLength != 0)) {
|
|||
|
return CR_INVALID_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
if (ulNameLength != 0) {
|
|||
|
//
|
|||
|
// pass a Unicode buffer instead and convert back to caller's
|
|||
|
// ANSI buffer on return
|
|||
|
//
|
|||
|
pUniVetoName = pSetupMalloc(MAX_VETO_NAME_LENGTH*sizeof(WCHAR));
|
|||
|
if (pUniVetoName == NULL) {
|
|||
|
return CR_OUT_OF_MEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// call the wide version
|
|||
|
//
|
|||
|
Status = CM_Request_Device_Eject_ExW(dnDevInst,
|
|||
|
pVetoType,
|
|||
|
pUniVetoName,
|
|||
|
MAX_VETO_NAME_LENGTH,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
|
|||
|
//
|
|||
|
// We should never return a veto name longer than MAX_VETO_NAME_LENGTH.
|
|||
|
//
|
|||
|
ASSERT(Status != CR_BUFFER_SMALL);
|
|||
|
|
|||
|
if (Status == CR_REMOVE_VETOED) {
|
|||
|
//
|
|||
|
// convert the unicode buffer to an ANSI string and copy to the caller's
|
|||
|
// buffer
|
|||
|
//
|
|||
|
ulAnsiBufferLen = ulNameLength;
|
|||
|
Status = PnPUnicodeToMultiByte(pUniVetoName,
|
|||
|
(lstrlenW(pUniVetoName)+1)*sizeof(WCHAR),
|
|||
|
pszVetoName,
|
|||
|
&ulAnsiBufferLen);
|
|||
|
}
|
|||
|
|
|||
|
if (pUniVetoName != NULL) {
|
|||
|
pSetupFree(pUniVetoName);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Request_Device_Eject_ExA
|
|||
|
|
|||
|
|
|||
|
|