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
|
||
|
||
|