1862 lines
49 KiB
C
1862 lines
49 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995-2001 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
traverse.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the API routines that perform hardware tree
|
|||
|
traversal.
|
|||
|
CM_Locate_DevNode
|
|||
|
CM_Get_Parent
|
|||
|
CM_Get_Child
|
|||
|
CM_Get_Sibling
|
|||
|
CM_Get_Device_ID_Size
|
|||
|
CM_Get_Device_ID
|
|||
|
CM_Enumerate_Enumerators
|
|||
|
CM_Get_Device_ID_List
|
|||
|
CM_Get_Device_ID_List_Size
|
|||
|
CM_Get_Depth
|
|||
|
|
|||
|
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"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Locate_DevNode_ExW(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_W pDeviceID, OPTIONAL
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the handle of the device instance that
|
|||
|
corresponds to a specified device identifier.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pdnDevInst Supplies the address of the variable that receives the
|
|||
|
handle of a device instance.
|
|||
|
|
|||
|
pDeviceID Supplies the address of a null-terminated string specifying
|
|||
|
a device identifier. If this parameter is NULL, the API
|
|||
|
retrieves a handle to the device instance at the root of
|
|||
|
the hardware tree.
|
|||
|
|
|||
|
ulFlags Supplies flags specifying options for locating the device
|
|||
|
instance. May be a combination of the following values:
|
|||
|
|
|||
|
CM_LOCATE_DEVNODE_NORMAL - Locate only device instances
|
|||
|
that are currently alive from the ConfigMgr's point of
|
|||
|
view.
|
|||
|
CM_LOCATE_DEVNODE_PHANTOM - Allows a device instance handle
|
|||
|
to be returned for a device instance that is not
|
|||
|
currently alive, but that does exist in the registry.
|
|||
|
This may be used with other CM APIs that require a
|
|||
|
devnode handle, but for which there currently is none
|
|||
|
for a particular device (e.g., you want to set a device
|
|||
|
registry property for a device not currently present).
|
|||
|
This flag does not allow you to locate phantom devnodes
|
|||
|
created by using CM_Create_DevNode with the
|
|||
|
CM_CREATE_DEVNODE_PHANTOM flag (such device instances
|
|||
|
are only accessible by the caller who holds the devnode
|
|||
|
handle returned from that API).
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_DEVICE_ID,
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_INVALID_POINTER,
|
|||
|
CR_NO_SUCH_DEVNODE,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR szFixedUpDeviceID[MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if (!ARGUMENT_PRESENT(pdnDevInst)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_LOCATE_DEVNODE_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// initialize output parameters
|
|||
|
//
|
|||
|
*pdnDevInst = 0;
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
// if the device instance is NULL or it's a zero-length string, then
|
|||
|
// retreive the root device instance
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
if ((!ARGUMENT_PRESENT(pDeviceID)) || (lstrlen(pDeviceID) == 0)) {
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetRootDeviceInstance(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
szFixedUpDeviceID, // return device instance string
|
|||
|
MAX_DEVICE_ID_LEN); // length of DeviceInstanceID
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetRootDeviceInstance caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
// if the device instance was specified, validate the string
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
else {
|
|||
|
//
|
|||
|
// first see if the format of the device id string is valid, this
|
|||
|
// can be done on the client side
|
|||
|
//
|
|||
|
if (!IsLegalDeviceId(pDeviceID)) {
|
|||
|
Status = CR_INVALID_DEVICE_ID;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Next, fix up the device ID string for consistency (uppercase, etc)
|
|||
|
//
|
|||
|
CopyFixedUpDeviceId(szFixedUpDeviceID, pDeviceID,
|
|||
|
lstrlen(pDeviceID));
|
|||
|
|
|||
|
//
|
|||
|
// finally, validate the presense of the device ID string, this must
|
|||
|
// be done by the server
|
|||
|
//
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_ValidateDeviceInstance(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
szFixedUpDeviceID, // device id
|
|||
|
ulFlags); // locate flag
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_ValidateDeviceInstance caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
}
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
// In either case, if we're successful then we have a valid device
|
|||
|
// ID. Use the string table to assign a unique DevNode to this
|
|||
|
// device id (if it's already in the string table, it just retrieves
|
|||
|
// the existing unique value)
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
ASSERT(*szFixedUpDeviceID && IsLegalDeviceId(szFixedUpDeviceID));
|
|||
|
|
|||
|
*pdnDevInst = pSetupStringTableAddString(hStringTable,
|
|||
|
szFixedUpDeviceID,
|
|||
|
STRTAB_CASE_SENSITIVE);
|
|||
|
if (*pdnDevInst == 0xFFFFFFFF) {
|
|||
|
Status = CR_FAILURE; // probably out of memory
|
|||
|
}
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Locate_DevNode_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Parent_Ex(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the handle of the parent of a device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pdnDevInst Supplies the address of the variable that receives a
|
|||
|
handle to the parent device instance.
|
|||
|
|
|||
|
dnDevInst Supplies the handle of the child device instance string.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_INVALID_POINTER,
|
|||
|
CR_NO_SUCH_DEVNODE,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR szDeviceID[MAX_DEVICE_ID_LEN],
|
|||
|
pDeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulSize = MAX_DEVICE_ID_LEN;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(pdnDevInst)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// initialize output parameters
|
|||
|
//
|
|||
|
*pdnDevInst = 0;
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retreive device instance string that corresponds to dnDevInst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulSize);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST; // "input" devinst doesn't exist
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
ulSize = MAX_DEVICE_ID_LEN;
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetRelatedDeviceInstance(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
PNP_GET_PARENT_DEVICE_INSTANCE, // requested action
|
|||
|
pDeviceID, // base device instance
|
|||
|
szDeviceID, // returns parent device instance
|
|||
|
&ulSize,
|
|||
|
ulFlags); // not used
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetRelatedDeviceInstance caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// add the returned device id to the string table so I can get a
|
|||
|
// devnode id for it (if it's already in the string table, the
|
|||
|
// existing id will be returned)
|
|||
|
//
|
|||
|
CharUpper(szDeviceID);
|
|||
|
|
|||
|
ASSERT(*szDeviceID && IsLegalDeviceId(szDeviceID));
|
|||
|
|
|||
|
*pdnDevInst = pSetupStringTableAddString(hStringTable,
|
|||
|
szDeviceID,
|
|||
|
STRTAB_CASE_SENSITIVE);
|
|||
|
if (*pdnDevInst == 0xFFFFFFFF) {
|
|||
|
Status = CR_FAILURE; // probably out of memory
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Parent_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Child_Ex(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the first child of a given device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pdnDevInst Supplies the address of the variable that receives the
|
|||
|
handle of the device instance.
|
|||
|
|
|||
|
dnDevInst Supplies the handle of the parent device instance.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_INVALID_POINTER,
|
|||
|
CR_NO_SUCH_DEVNODE,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR szDeviceID[MAX_DEVICE_ID_LEN],
|
|||
|
pDeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulSize = MAX_DEVICE_ID_LEN;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(pdnDevInst)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// initialize output parameters
|
|||
|
//
|
|||
|
*pdnDevInst = 0;
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retreive device instance string that corresponds to dnDevInst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulSize);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST; // "input" devinst doesn't exist
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
ulSize = MAX_DEVICE_ID_LEN;
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetRelatedDeviceInstance(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
PNP_GET_CHILD_DEVICE_INSTANCE, // requested action
|
|||
|
pDeviceID, // base device instance
|
|||
|
szDeviceID, // child device instance
|
|||
|
&ulSize,
|
|||
|
ulFlags); // not used
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetRelatedDeviceInstance caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// add the returned device id to the string table so I can get a
|
|||
|
// devnode id for it (if it's already in the string table, the
|
|||
|
// existing id will be returned)
|
|||
|
//
|
|||
|
CharUpper(szDeviceID);
|
|||
|
|
|||
|
ASSERT(*szDeviceID && IsLegalDeviceId(szDeviceID));
|
|||
|
|
|||
|
*pdnDevInst = pSetupStringTableAddString(hStringTable,
|
|||
|
szDeviceID,
|
|||
|
STRTAB_CASE_SENSITIVE);
|
|||
|
if (*pdnDevInst == 0xFFFFFFFF) {
|
|||
|
Status = CR_FAILURE; // probably out of memory
|
|||
|
}
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Child_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Sibling_Ex(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the sibling of a device instance.
|
|||
|
|
|||
|
This API can be called in a loop to retrieve all the siblings of a
|
|||
|
device instance. When the API returns CR_NO_SUCH_DEVNODE, there are no
|
|||
|
more siblings to enumerate. In order to enumerate all children of a
|
|||
|
device instance, this loop must start with the device instance retrieved
|
|||
|
by calling CM_Get_Child to get the first sibling.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pdnDevInst Supplies the address of the variable that receives a
|
|||
|
handle to the sibling device instance.
|
|||
|
|
|||
|
dnDevInst Supplies the handle of a device instance.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_INVALID_POINTER,
|
|||
|
CR_NO_SUCH_DEVNODE,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR szDeviceID[MAX_DEVICE_ID_LEN],
|
|||
|
pDeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulSize = MAX_DEVICE_ID_LEN;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(pdnDevInst)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// initialize output parameters
|
|||
|
//
|
|||
|
*pdnDevInst = 0;
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle and string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retreive device instance string that corresponds to dnDevInst
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulSize);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST; // "input" devinst doesn't exist
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
ulSize = MAX_DEVICE_ID_LEN;
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetRelatedDeviceInstance(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
PNP_GET_SIBLING_DEVICE_INSTANCE, // requested action
|
|||
|
pDeviceID, // base device instance
|
|||
|
szDeviceID, // sibling device instance
|
|||
|
&ulSize,
|
|||
|
ulFlags); // not used
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetRelatedDeviceInstance caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if (Status != CR_SUCCESS) {
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// add the returned device id to the string table so I can get a
|
|||
|
// devnode id for it (if it's already in the string table, the
|
|||
|
// existing id will be returned)
|
|||
|
//
|
|||
|
CharUpper(szDeviceID);
|
|||
|
|
|||
|
ASSERT(*szDeviceID && IsLegalDeviceId(szDeviceID));
|
|||
|
|
|||
|
*pdnDevInst = pSetupStringTableAddString(hStringTable,
|
|||
|
szDeviceID,
|
|||
|
STRTAB_CASE_SENSITIVE);
|
|||
|
if (*pdnDevInst == 0xFFFFFFFF) {
|
|||
|
Status = CR_FAILURE; // probably out of memory
|
|||
|
}
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Sibling_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_Size_Ex(
|
|||
|
OUT PULONG pulLen,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the size of a device identifier from a
|
|||
|
device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pulLen Supplies the address of the variable that receives the size
|
|||
|
in characters, not including the terminating NULL, of the
|
|||
|
device identifier. The API sets the variable to 0 if no
|
|||
|
identifier exists. The size is always less than or equal to
|
|||
|
MAX_DEVICE_ID_LEN.
|
|||
|
|
|||
|
dnDevInst Supplies the handle of the device instance.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_INVALID_POINTER,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
BOOL Success;
|
|||
|
DWORD ulLen;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(pulLen)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, NULL)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the string form of the device id string
|
|||
|
// use private ulLen, since we know this is valid
|
|||
|
//
|
|||
|
ulLen = MAX_DEVICE_ID_LEN;
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|||
|
*pulLen = 0;
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
}
|
|||
|
//
|
|||
|
// discount the terminating NULL char,
|
|||
|
// included in the size reported by pSetupStringTableStringFromIdEx
|
|||
|
//
|
|||
|
*pulLen = ulLen - 1;
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Device_ID_Size_Ex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_ExW(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
OUT PWCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the device identifier for a device instance.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
dnDevNode Supplies the handle of the device instance for which to
|
|||
|
retrieve the device identifier.
|
|||
|
|
|||
|
Buffer Supplies the address of the buffer that receives the device
|
|||
|
identifier. If this buffer is larger than the device
|
|||
|
identifier, the API appends a null-terminating character to
|
|||
|
the data. If it is smaller than the device identifier, the API
|
|||
|
fills it with as much of the device identifier as will fit
|
|||
|
and returns CR_BUFFER_SMALL.
|
|||
|
|
|||
|
BufferLen Supplies the size, in characters, of the buffer for the device
|
|||
|
identifier.
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_BUFFER_SMALL,
|
|||
|
CR_INVALID_DEVNODE,
|
|||
|
CR_INVALID_FLAG,
|
|||
|
CR_INVALID_POINTER,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR pDeviceID [MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulLength = MAX_DEVICE_ID_LEN;
|
|||
|
PVOID hStringTable = NULL;
|
|||
|
BOOL Success;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if (dnDevInst == 0) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(Buffer)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// setup string table handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, &hStringTable, NULL)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// retrieve the string form of the device id string
|
|||
|
//
|
|||
|
Success = pSetupStringTableStringFromIdEx(hStringTable, dnDevInst,pDeviceID,&ulLength);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|||
|
*Buffer = '\0';
|
|||
|
Status = CR_INVALID_DEVNODE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// copy as much of the the device id string as possible to the user
|
|||
|
// buffer. the length reported by pSetupStringTableStringFromIdEx accounts
|
|||
|
// for the NULL term char; include it as well, if there is room.
|
|||
|
//
|
|||
|
memcpy(Buffer,
|
|||
|
pDeviceID,
|
|||
|
min(ulLength * sizeof(WCHAR), BufferLen * sizeof(WCHAR)));
|
|||
|
|
|||
|
//
|
|||
|
// if the length of device id string (without NULL termination) is
|
|||
|
// longer than the supplied buffer, report CR_BUFFER_SMALL.
|
|||
|
//
|
|||
|
if ((ulLength - 1) > BufferLen) {
|
|||
|
Status = CR_BUFFER_SMALL;
|
|||
|
}
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Device_ID_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Enumerate_Enumerators_ExW(
|
|||
|
IN ULONG ulEnumIndex,
|
|||
|
OUT PWCHAR Buffer,
|
|||
|
IN OUT PULONG pulLength,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine enumerates the enumerator subkeys under the Enum branch
|
|||
|
(e.g., Root, PCI, etc.). These names should not be used to access the
|
|||
|
registry directly, but may be used as input to the CM_Get_Device_ID_List
|
|||
|
routine. To enumerate enumerator subkey names, an application should
|
|||
|
initially call the CM_Enumerate_Enumerators function with the ulEnumIndex
|
|||
|
parameter set to zero. The application should then increment the
|
|||
|
ulEnumIndex parameter and call CM_Enumerate_Enumerators until there are
|
|||
|
no more subkeys (until the function returns CR_NO_SUCH_VALUE).
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
ulEnumIndex Supplies the index of the enumerator subkey name to retrieve.
|
|||
|
|
|||
|
Buffer Supplies the address of the character buffer that receives
|
|||
|
the enumerator subkey name whose index is specified by
|
|||
|
ulEnumIndex.
|
|||
|
|
|||
|
pulLength Supplies the address of the variable that contains the length,
|
|||
|
in characters, of the Buffer. Upon return, this variable
|
|||
|
will contain the number of characters (including terminating
|
|||
|
NULL) written to Buffer (if the supplied buffer is't large
|
|||
|
enough, then the routine will fail with CR_BUFFER_SMALL, and
|
|||
|
this value will indicate how large the buffer needs to be in
|
|||
|
order to succeed).
|
|||
|
|
|||
|
ulFlags Must be zero.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_POINTER,
|
|||
|
CR_BUFFER_SMALL,
|
|||
|
CR_NO_SUCH_VALUE,
|
|||
|
CR_REGISTRY_ERROR,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(Buffer)) ||
|
|||
|
(!ARGUMENT_PRESENT(pulLength))) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, 0)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// initialize output parameters
|
|||
|
//
|
|||
|
*Buffer = L'\0';
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_EnumerateSubKeys(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
PNP_ENUMERATOR_SUBKEYS, // subkeys of enum branch
|
|||
|
ulEnumIndex, // index of enumerator to enumerate
|
|||
|
Buffer, // will contain enumerator name
|
|||
|
*pulLength, // max length of Buffer in chars
|
|||
|
pulLength, // chars copied (or chars required)
|
|||
|
ulFlags); // currently unused
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_EnumerateSubKeys caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Enumerate_Enumerators_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_List_ExW(
|
|||
|
IN PCWSTR pszFilter, OPTIONAL
|
|||
|
OUT PWCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
This routine retrieve a list of all device IDs (device instance names)
|
|||
|
stored in the system.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pszFilter This string filters the list of device IDs returned. Its
|
|||
|
interpretation is dependent on the ulFlags specified. If
|
|||
|
CM_GETDEVID_FILTER_ENUMERATORS is specified, then this
|
|||
|
value can be either the name of an enumerator or the name
|
|||
|
of an enumerator plus the device id. If
|
|||
|
CM_GETDEVID_FILTER_SERVICE is specified, then this value
|
|||
|
is a service name.
|
|||
|
|
|||
|
Buffer Supplies the address of the character buffer that receives
|
|||
|
the device ID list. Each device ID is null-terminated, with
|
|||
|
an extra NULL at the end.
|
|||
|
|
|||
|
BufferLen Supplies the size, in characters, of the Buffer. This size
|
|||
|
may be ascertained by calling CM_Get_Device_ID_List_Size.
|
|||
|
|
|||
|
ulFlags Must be either CM_GETDEVID_FILTER_ENUMERATOR or
|
|||
|
CM_GETDEVID_FILTER_SERVICE. The flags value controls how
|
|||
|
the pszFilter string is used.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_POINTER,
|
|||
|
CR_BUFFER_SMALL,
|
|||
|
CR_REGISTRY_ERROR,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(Buffer)) || (BufferLen == 0)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_GETIDLIST_FILTER_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// initialize output parameters
|
|||
|
//
|
|||
|
*Buffer = L'\0';
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetDeviceList(
|
|||
|
hBinding, // RPC Binding Handle
|
|||
|
pszFilter, // filter string, optional
|
|||
|
Buffer, // will contain device list
|
|||
|
&BufferLen, // in/out size of Buffer
|
|||
|
ulFlags); // filter flag
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetDeviceList caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Device_ID_List_ExW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_List_Size_ExW(
|
|||
|
OUT PULONG pulLen,
|
|||
|
IN PCWSTR pszFilter, OPTIONAL
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the size, in characters, of a list of device
|
|||
|
identifiers. It may be used to supply the buffer size necessary for a
|
|||
|
call to CM_Get_Device_ID_List.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pulLen Supplies the address of the variable that receives the
|
|||
|
size, in characters, required to store a list of all device
|
|||
|
identifiers (possibly limited to those existing under the
|
|||
|
pszEnumerator subkey described below). The size reflects
|
|||
|
a list of null-terminated device identifiers, with an extra
|
|||
|
null at the end. For efficiency, this number represents an
|
|||
|
upper bound on the size required, and the actual list size
|
|||
|
may be slightly smaller.
|
|||
|
|
|||
|
pszFilter This string filters the list of device IDs returned. Its
|
|||
|
interpretation is dependent on the ulFlags specified. If
|
|||
|
CM_GETDEVID_FILTER_ENUMERATORS is specified, then this
|
|||
|
value can be either the name of an enumerator or the name
|
|||
|
of an enumerator plus the device id. If
|
|||
|
CM_GETDEVID_FILTER_SERVICE is specified, then this value
|
|||
|
is a service name.
|
|||
|
|
|||
|
ulFlags Must be either CM_GETDEVID_FILTER_ENUMERATOR or
|
|||
|
CM_GETDEVID_FILTER_SERVICE. The flags value controls how
|
|||
|
the pszFilter string is used.
|
|||
|
|
|||
|
hMachine Machine handle returned from CM_Connect_Machine or NULL.
|
|||
|
|
|||
|
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_POINTER,
|
|||
|
CR_REGISTRY_ERROR,
|
|||
|
CR_REMOTE_COMM_FAILURE,
|
|||
|
CR_MACHINE_UNAVAILABLE,
|
|||
|
CR_FAILURE.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
handle_t hBinding = NULL;
|
|||
|
|
|||
|
|
|||
|
try {
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if (!ARGUMENT_PRESENT(pulLen)) {
|
|||
|
Status = CR_INVALID_POINTER;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
if (INVALID_FLAGS(ulFlags, CM_GETIDLIST_FILTER_BITS)) {
|
|||
|
Status = CR_INVALID_FLAG;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// initialize output parameters
|
|||
|
//
|
|||
|
*pulLen = 0;
|
|||
|
|
|||
|
//
|
|||
|
// setup rpc binding handle
|
|||
|
//
|
|||
|
if (!PnPGetGlobalHandles(hMachine, NULL, &hBinding)) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetDeviceListSize(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
pszFilter, // Enumerator subkey, optional
|
|||
|
pulLen, // length of device list in chars
|
|||
|
ulFlags); // filter flag
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetDeviceListSize caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Device_ID_List_SizeW
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Depth_Ex(
|
|||
|
OUT PULONG pulDepth,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine retrieves the depth of a device instance in the
|
|||
|
hardware tree.
|
|||
|
|
|||
|
Parameters:
|
|||
|
|
|||
|
pulDepth Supplies the address of the variable that receives the
|
|||
|
depth of the device instance. This value is 0 to designate
|
|||
|
the root of the tree, 1 to designate a child of the root,
|
|||
|
and so on.
|
|||
|
|
|||
|
dnDevNode Supplies the handle of a device instance.
|
|||
|
|
|||
|
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 pDeviceID [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(pulDepth)) {
|
|||
|
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,pDeviceID,&ulLen);
|
|||
|
if (Success == FALSE || INVALID_DEVINST(pDeviceID)) {
|
|||
|
Status = CR_INVALID_DEVINST;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
RpcTryExcept {
|
|||
|
//
|
|||
|
// call rpc service entry point
|
|||
|
//
|
|||
|
Status = PNP_GetDepth(
|
|||
|
hBinding, // rpc binding handle
|
|||
|
pDeviceID, // device instance
|
|||
|
pulDepth, // returns the depth
|
|||
|
ulFlags); // not used
|
|||
|
}
|
|||
|
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
|||
|
KdPrintEx((DPFLTR_PNPMGR_ID,
|
|||
|
DBGF_ERRORS,
|
|||
|
"PNP_GetDepth caused an exception (%d)\n",
|
|||
|
RpcExceptionCode()));
|
|||
|
|
|||
|
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
Clean0:
|
|||
|
NOTHING;
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = CR_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Depth
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------------------------
|
|||
|
// Local Stubs
|
|||
|
//-------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Locate_DevNodeW(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_W pDeviceID, OPTIONAL
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Locate_DevNode_ExW(pdnDevInst, pDeviceID, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Locate_DevNodeA(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_A pDeviceID, OPTIONAL
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Locate_DevNode_ExA(pdnDevInst, pDeviceID, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Parent(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Child(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Child_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Sibling(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Sibling_Ex(pdnDevInst, dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_Size(
|
|||
|
OUT PULONG pulLen,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Device_ID_Size_Ex(pulLen, dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_IDW(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
OUT PWCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Device_ID_ExW(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_IDA(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
OUT PCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Device_ID_ExA(dnDevInst, Buffer, BufferLen, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Enumerate_EnumeratorsW(
|
|||
|
IN ULONG ulEnumIndex,
|
|||
|
OUT PWCHAR Buffer,
|
|||
|
IN OUT PULONG pulLength,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Enumerate_Enumerators_ExW(ulEnumIndex, Buffer, pulLength,
|
|||
|
ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Enumerate_EnumeratorsA(
|
|||
|
IN ULONG ulEnumIndex,
|
|||
|
OUT PCHAR Buffer,
|
|||
|
IN OUT PULONG pulLength,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Enumerate_Enumerators_ExA(ulEnumIndex, Buffer, pulLength,
|
|||
|
ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_ListW(
|
|||
|
IN PCWSTR pszFilter, OPTIONAL
|
|||
|
OUT PWCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Device_ID_List_ExW(pszFilter, Buffer, BufferLen,
|
|||
|
ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_ListA(
|
|||
|
IN PCSTR pszFilter, OPTIONAL
|
|||
|
OUT PCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Device_ID_List_ExA(pszFilter, Buffer, BufferLen,
|
|||
|
ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_List_SizeW(
|
|||
|
OUT PULONG pulLen,
|
|||
|
IN PCWSTR pszFilter, OPTIONAL
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Device_ID_List_Size_ExW(pulLen, pszFilter, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_List_SizeA(
|
|||
|
OUT PULONG pulLen,
|
|||
|
IN PCSTR pszFilter, OPTIONAL
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Device_ID_List_Size_ExA(pulLen, pszFilter, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Depth(
|
|||
|
OUT PULONG pulDepth,
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
IN ULONG ulFlags
|
|||
|
)
|
|||
|
{
|
|||
|
return CM_Get_Depth_Ex(pulDepth, dnDevInst, ulFlags, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------------------------
|
|||
|
// ANSI STUBS
|
|||
|
//-------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Locate_DevNode_ExA(
|
|||
|
OUT PDEVINST pdnDevInst,
|
|||
|
IN DEVINSTID_A pDeviceID, OPTIONAL
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(pDeviceID)) {
|
|||
|
//
|
|||
|
// If the DEVINSTID parameter is NULL, then no conversion is necessary,
|
|||
|
// just call the wide version
|
|||
|
//
|
|||
|
Status = CM_Locate_DevNode_ExW(pdnDevInst,
|
|||
|
NULL,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
} else {
|
|||
|
//
|
|||
|
// if a device id string was passed in, convert to UNICODE before
|
|||
|
// passing on to the wide version
|
|||
|
//
|
|||
|
PWSTR pUniDeviceID = NULL;
|
|||
|
|
|||
|
if (pSetupCaptureAndConvertAnsiArg(pDeviceID, &pUniDeviceID) == NO_ERROR) {
|
|||
|
|
|||
|
Status = CM_Locate_DevNode_ExW(pdnDevInst,
|
|||
|
pUniDeviceID,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
|
|||
|
pSetupFree(pUniDeviceID);
|
|||
|
|
|||
|
} else {
|
|||
|
Status = CR_INVALID_DEVICE_ID;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Locate_DevNode_ExA
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_ExA(
|
|||
|
IN DEVINST dnDevInst,
|
|||
|
OUT PCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR UniBuffer[MAX_DEVICE_ID_LEN];
|
|||
|
ULONG ulAnsiBufferLen;
|
|||
|
|
|||
|
//
|
|||
|
// validate essential parameters only
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(Buffer)) || (BufferLen == 0)) {
|
|||
|
return CR_INVALID_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// call the wide version, passing a unicode buffer as a parameter
|
|||
|
//
|
|||
|
Status = CM_Get_Device_ID_ExW(dnDevInst,
|
|||
|
UniBuffer,
|
|||
|
MAX_DEVICE_ID_LEN,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
|
|||
|
//
|
|||
|
// We should never return a DeviceId longer than MAX_DEVICE_ID_LEN.
|
|||
|
//
|
|||
|
ASSERT(Status != CR_BUFFER_SMALL);
|
|||
|
|
|||
|
if (Status == CR_SUCCESS) {
|
|||
|
//
|
|||
|
// if the call succeeded, convert the device id to ansi before returning
|
|||
|
//
|
|||
|
ulAnsiBufferLen = BufferLen;
|
|||
|
Status = PnPUnicodeToMultiByte(UniBuffer,
|
|||
|
(lstrlenW(UniBuffer)+1)*sizeof(WCHAR),
|
|||
|
Buffer,
|
|||
|
&ulAnsiBufferLen);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Device_ID_ExA
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Enumerate_Enumerators_ExA(
|
|||
|
IN ULONG ulEnumIndex,
|
|||
|
OUT PCHAR Buffer,
|
|||
|
IN OUT PULONG pulLength,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
WCHAR UniBuffer[MAX_DEVICE_ID_LEN];
|
|||
|
ULONG UniLen = MAX_DEVICE_ID_LEN;
|
|||
|
|
|||
|
//
|
|||
|
// validate parameters
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(Buffer)) ||
|
|||
|
(!ARGUMENT_PRESENT(pulLength))) {
|
|||
|
return CR_INVALID_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// call the wide version, passing a unicode buffer as a parameter
|
|||
|
//
|
|||
|
Status = CM_Enumerate_Enumerators_ExW(ulEnumIndex,
|
|||
|
UniBuffer,
|
|||
|
&UniLen,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
|
|||
|
ASSERT(Status != CR_BUFFER_SMALL);
|
|||
|
|
|||
|
if (Status == CR_SUCCESS) {
|
|||
|
//
|
|||
|
// convert the unicode buffer to an ansi string and copy to the caller's
|
|||
|
// buffer
|
|||
|
//
|
|||
|
Status = PnPUnicodeToMultiByte(UniBuffer,
|
|||
|
(lstrlenW(UniBuffer)+1)*sizeof(WCHAR),
|
|||
|
Buffer,
|
|||
|
pulLength);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Enumerate_Enumerators_ExA
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_List_ExA(
|
|||
|
IN PCSTR pszFilter, OPTIONAL
|
|||
|
OUT PCHAR Buffer,
|
|||
|
IN ULONG BufferLen,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
PWSTR pUniBuffer, pUniFilter = NULL;
|
|||
|
ULONG ulAnsiBufferLen;
|
|||
|
|
|||
|
//
|
|||
|
// validate input parameters
|
|||
|
//
|
|||
|
if ((!ARGUMENT_PRESENT(Buffer)) || (BufferLen == 0)) {
|
|||
|
return CR_INVALID_POINTER;
|
|||
|
}
|
|||
|
|
|||
|
if (ARGUMENT_PRESENT(pszFilter)) {
|
|||
|
//
|
|||
|
// if a filter string was passed in, convert to UNICODE before
|
|||
|
// passing on to the wide version
|
|||
|
//
|
|||
|
if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pUniFilter) != NO_ERROR) {
|
|||
|
return CR_INVALID_DATA;
|
|||
|
}
|
|||
|
ASSERT(pUniFilter != NULL);
|
|||
|
} else {
|
|||
|
ASSERT(pUniFilter == NULL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// prepare a larger buffer to hold the unicode formatted
|
|||
|
// multi_sz data returned by CM_Get_Device_ID_List.
|
|||
|
//
|
|||
|
pUniBuffer = pSetupMalloc(BufferLen*sizeof(WCHAR));
|
|||
|
if (pUniBuffer == NULL) {
|
|||
|
Status = CR_OUT_OF_MEMORY;
|
|||
|
goto Clean0;
|
|||
|
}
|
|||
|
|
|||
|
*pUniBuffer = L'\0';
|
|||
|
|
|||
|
//
|
|||
|
// call the wide version
|
|||
|
//
|
|||
|
Status = CM_Get_Device_ID_List_ExW(pUniFilter,
|
|||
|
pUniBuffer,
|
|||
|
BufferLen, // size in chars
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
if (Status == CR_SUCCESS) {
|
|||
|
//
|
|||
|
// if the call succeeded, must convert the multi_sz list to ansi before
|
|||
|
// returning
|
|||
|
//
|
|||
|
ulAnsiBufferLen = BufferLen;
|
|||
|
Status = PnPUnicodeToMultiByte(pUniBuffer,
|
|||
|
BufferLen*sizeof(WCHAR),
|
|||
|
Buffer,
|
|||
|
&ulAnsiBufferLen);
|
|||
|
}
|
|||
|
|
|||
|
pSetupFree(pUniBuffer);
|
|||
|
|
|||
|
Clean0:
|
|||
|
|
|||
|
if (pUniFilter) {
|
|||
|
pSetupFree(pUniFilter);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Device_ID_List_ExA
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CONFIGRET
|
|||
|
CM_Get_Device_ID_List_Size_ExA(
|
|||
|
OUT PULONG pulLen,
|
|||
|
IN PCSTR pszFilter, OPTIONAL
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN HMACHINE hMachine
|
|||
|
)
|
|||
|
{
|
|||
|
CONFIGRET Status = CR_SUCCESS;
|
|||
|
ULONG UniLen = MAX_DEVICE_ID_LEN;
|
|||
|
|
|||
|
|
|||
|
if (!ARGUMENT_PRESENT(pszFilter)) {
|
|||
|
//
|
|||
|
// If the filter parameter is NULL, then no conversion is necessary,
|
|||
|
// just call the wide version
|
|||
|
//
|
|||
|
Status = CM_Get_Device_ID_List_Size_ExW(pulLen,
|
|||
|
NULL,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
} else {
|
|||
|
//
|
|||
|
// if a filter string was passed in, convert to UNICODE before
|
|||
|
// passing on to the wide version
|
|||
|
//
|
|||
|
PWSTR pUniFilter = NULL;
|
|||
|
|
|||
|
if (pSetupCaptureAndConvertAnsiArg(pszFilter, &pUniFilter) == NO_ERROR) {
|
|||
|
|
|||
|
Status = CM_Get_Device_ID_List_Size_ExW(pulLen,
|
|||
|
pUniFilter,
|
|||
|
ulFlags,
|
|||
|
hMachine);
|
|||
|
pSetupFree(pUniFilter);
|
|||
|
|
|||
|
} else {
|
|||
|
Status = CR_INVALID_DATA;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
|
|||
|
} // CM_Get_Device_ID_List_Size_ExA
|
|||
|
|
|||
|
|