879 lines
22 KiB
C
879 lines
22 KiB
C
/*++
|
||
|
||
Copyright (c) 1995-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
cutil.c
|
||
|
||
Abstract:
|
||
|
||
This module contains general utility routines used by both cfgmgr32
|
||
and umpnpmgr.
|
||
|
||
IsLegalDeviceId
|
||
SplitDeviceInstanceString
|
||
DeletePrivateKey
|
||
RegDeleteNode
|
||
Split1
|
||
Split2
|
||
GetDevNodeKeyPath
|
||
MapRpcExceptionToCR
|
||
|
||
Author:
|
||
|
||
Paula Tomlinson (paulat) 7-12-1995
|
||
|
||
Environment:
|
||
|
||
User mode only.
|
||
|
||
Revision History:
|
||
|
||
12-July-1995 paulat
|
||
|
||
Creation and initial implementation.
|
||
|
||
--*/
|
||
|
||
|
||
//
|
||
// includes
|
||
//
|
||
#include "precomp.h"
|
||
#include "umpnplib.h"
|
||
|
||
|
||
|
||
//
|
||
// Common private utility routines (used by client and server)
|
||
//
|
||
|
||
BOOL
|
||
IsLegalDeviceId(
|
||
IN LPCWSTR pszDeviceInstance
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine parses the device instance string and validates whether it
|
||
conforms to the appropriate rules, including:
|
||
|
||
- Total length of the device instance path must not be longer than
|
||
MAX_DEVICE_ID_LEN characters.
|
||
|
||
- The device instance path must contain exactly 3 non-empty path components.
|
||
|
||
- The device instance path string must not contain any "invalid characters".
|
||
|
||
Invalid characters are:
|
||
c <= 0x20 (' ')
|
||
c > 0x7F
|
||
c == 0x2C (',')
|
||
|
||
Arguments:
|
||
|
||
pszDeviceInstance - Device instance path.
|
||
|
||
Return value:
|
||
|
||
The return value is TRUE if the device instance path string conforms to the
|
||
rules.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Status;
|
||
LPCWSTR p;
|
||
ULONG ulTotalLength = 0;
|
||
ULONG ulComponentLength = 0, ulComponents = 1;
|
||
|
||
try {
|
||
//
|
||
// An empty string is used for an optional device instance path.
|
||
//
|
||
if ((pszDeviceInstance == NULL) || (*pszDeviceInstance == L'\0')) {
|
||
Status = TRUE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Walk over the entire device instance path, counting the total length,
|
||
// individual path component lengths, and checking for the presence of
|
||
// invalid characters.
|
||
//
|
||
for (p = pszDeviceInstance; *p; p++) {
|
||
//
|
||
// Make sure the device instance path isn't too long.
|
||
//
|
||
ulTotalLength++;
|
||
|
||
if (ulTotalLength > MAX_DEVICE_ID_LEN) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP: IsLegalDeviceId: "
|
||
"device instance path %ws longer than "
|
||
"MAX_DEVICE_ID_LEN characters!\n",
|
||
pszDeviceInstance));
|
||
//ASSERT(ulTotalLength <= MAX_DEVICE_ID_LEN);
|
||
Status = FALSE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Check for the presence of invalid characters.
|
||
//
|
||
if ((*p <= L' ') || (*p > (WCHAR)0x7F) || (*p == L',')) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP: IsLegalDeviceId: "
|
||
"device instance path %ws contains invalid character (0x%lx)!\n",
|
||
pszDeviceInstance, *p));
|
||
//ASSERT((*p > L' ') && (*p <= (WCHAR)0x7F) && (*p != L','));
|
||
Status = FALSE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// Check the length of individual path components.
|
||
//
|
||
if (*p == L'\\') {
|
||
//
|
||
// It is illegal for a device instance path to have multiple
|
||
// consecutive path separators, or to start with one.
|
||
//
|
||
if (ulComponentLength == 0) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP: IsLegalDeviceId: "
|
||
"device instance path %ws contains "
|
||
"invalid path component!\n",
|
||
pszDeviceInstance));
|
||
//ASSERT(ulComponentLength != 0);
|
||
Status = FALSE;
|
||
goto Clean0;
|
||
}
|
||
|
||
ulComponentLength = 0;
|
||
ulComponents++;
|
||
|
||
} else {
|
||
//
|
||
// Count the length of this path component to verify it's not empty.
|
||
//
|
||
ulComponentLength++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// It is illegal for a device instance path to end with a path separator
|
||
// character.
|
||
//
|
||
if (ulComponentLength == 0) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP: IsLegalDeviceId: "
|
||
"device instance path %ws has trailing '\\' char!\n",
|
||
pszDeviceInstance));
|
||
//ASSERT(ulComponentLength != 0);
|
||
Status = FALSE;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// A valid device instance path must contain exactly 3 path components:
|
||
// an enumerator id, a device id, and an instance id.
|
||
//
|
||
if (ulComponents != 3) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP: IsLegalDeviceId: "
|
||
"device instance path %ws contains "
|
||
"invalid number of path components!\n",
|
||
pszDeviceInstance));
|
||
//ASSERT(ulComponents == 3);
|
||
Status = FALSE;
|
||
goto Clean0;
|
||
}
|
||
|
||
Status = TRUE;
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP: Exception in IsLegalDeviceId!! "
|
||
"exception code = %d\n",
|
||
GetExceptionCode()));
|
||
Status = FALSE;
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // IsLegalDeviceId
|
||
|
||
|
||
|
||
BOOL
|
||
SplitDeviceInstanceString(
|
||
IN LPCWSTR pszDeviceInstance,
|
||
OUT LPWSTR pszBase,
|
||
OUT LPWSTR pszDeviceID,
|
||
OUT LPWSTR pszInstanceID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine parses a device instance string into it's three component
|
||
parts. Since this is an internal routine, NO error checking is done on
|
||
the pszBase, pszDeviceID, and pszInstanceID routines; I always assume that
|
||
valid pointers are passed in and that each of these buffers is at least
|
||
MAX_DEVICE_ID_LEN characters in length. I do some error checking on the
|
||
pszDeviceInstance string since it is passed in from the client side.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return value:
|
||
|
||
The return value is TRUE if the function suceeds and FALSE if it fails.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT ulLength, i, j;
|
||
|
||
|
||
ulLength = lstrlen(pszDeviceInstance);
|
||
|
||
//
|
||
// parse the string for the first backslash character
|
||
//
|
||
|
||
for (i=0; i < ulLength && pszDeviceInstance[i] != '\0' &&
|
||
pszDeviceInstance[i] != '\\'; i++);
|
||
|
||
if (pszDeviceInstance[i] != '\\') {
|
||
lstrcpyn(pszBase, pszDeviceInstance,MAX_DEVICE_ID_LEN);
|
||
*pszDeviceID = '\0';
|
||
*pszInstanceID = '\0';
|
||
return FALSE; // not a complete device instance string
|
||
}
|
||
|
||
i++; // increment past the backslash character
|
||
if (i < ulLength && pszDeviceInstance[i] != '\0') {
|
||
lstrcpyn(pszBase, pszDeviceInstance, min(i,MAX_DEVICE_ID_LEN));
|
||
}
|
||
else {
|
||
*pszBase = '\0';
|
||
*pszDeviceID = '\0';
|
||
*pszInstanceID = '\0';
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
//
|
||
// parse the string for second backslash character
|
||
//
|
||
for (j=i; j < ulLength && pszDeviceInstance[j] != '\0' &&
|
||
pszDeviceInstance[j] != '\\'; j++);
|
||
|
||
if (pszDeviceInstance[j] != '\\' || j > ulLength) {
|
||
lstrcpyn(pszDeviceID, &pszDeviceInstance[i],MAX_DEVICE_ID_LEN);
|
||
*pszInstanceID = '\0';
|
||
return FALSE;
|
||
}
|
||
|
||
j++;
|
||
lstrcpyn(pszDeviceID, &pszDeviceInstance[i], min(j-i,MAX_DEVICE_ID_LEN));
|
||
lstrcpyn(pszInstanceID, &pszDeviceInstance[j], min((ulLength-j+1),MAX_DEVICE_ID_LEN));
|
||
|
||
return TRUE;
|
||
|
||
} // SplitDeviceInstanceString
|
||
|
||
|
||
|
||
CONFIGRET
|
||
DeletePrivateKey(
|
||
IN HKEY hBranchKey,
|
||
IN LPCWSTR pszParentKey,
|
||
IN LPCWSTR pszChildKey
|
||
)
|
||
{
|
||
CONFIGRET Status = CR_SUCCESS;
|
||
LONG RegStatus = ERROR_SUCCESS;
|
||
WCHAR RegStr[2*MAX_CM_PATH],
|
||
szKey1[MAX_CM_PATH],
|
||
szKey2[MAX_CM_PATH];
|
||
HKEY hKey = NULL;
|
||
ULONG ulSubKeys = 0;
|
||
|
||
|
||
//
|
||
// Make sure the specified registry key paths are valid.
|
||
//
|
||
if ((pszParentKey == NULL) ||
|
||
(pszChildKey == NULL) ||
|
||
((lstrlen(pszParentKey) + 1) > MAX_CM_PATH) ||
|
||
((lstrlen(pszChildKey) + 1) > MAX_CM_PATH)) {
|
||
Status = CR_INVALID_POINTER;
|
||
goto Clean0;
|
||
}
|
||
|
||
//
|
||
// is the specified child key a compound registry key?
|
||
//
|
||
if (!Split1(pszChildKey, szKey1, szKey2)) {
|
||
|
||
//------------------------------------------------------------------
|
||
// Only a single child key was specified, so just open the parent
|
||
// registry key and delete the child (and any of its subkeys)
|
||
//------------------------------------------------------------------
|
||
|
||
if (RegOpenKeyEx(hBranchKey, pszParentKey, 0,
|
||
KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS) {
|
||
goto Clean0; // no error, nothing to delete
|
||
}
|
||
|
||
if (!RegDeleteNode(hKey, pszChildKey)) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
|
||
else {
|
||
|
||
//------------------------------------------------------------------
|
||
// if a compound registry path was passed in, such as key1\key2
|
||
// then always delete key2 but delete key1 only if it has no other
|
||
// subkeys besides key2.
|
||
//------------------------------------------------------------------
|
||
|
||
//
|
||
// open the first level key
|
||
//
|
||
wsprintf(RegStr, TEXT("%s\\%s"),
|
||
pszParentKey,
|
||
szKey1);
|
||
|
||
RegStatus = RegOpenKeyEx(
|
||
hBranchKey, RegStr, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
|
||
&hKey);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
goto Clean0; // no error, nothing to delete
|
||
}
|
||
|
||
//
|
||
// try to delete the second level key
|
||
//
|
||
if (!RegDeleteNode(hKey, szKey2)) {
|
||
goto Clean0; // no error, nothing to delete
|
||
}
|
||
|
||
//
|
||
// How many subkeys are remaining?
|
||
//
|
||
RegStatus = RegQueryInfoKey(
|
||
hKey, NULL, NULL, NULL, &ulSubKeys,
|
||
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
goto Clean0; // nothing to delete
|
||
}
|
||
|
||
//
|
||
// if no more subkeys, then delete the first level key
|
||
//
|
||
if (ulSubKeys == 0) {
|
||
|
||
RegCloseKey(hKey);
|
||
hKey = NULL;
|
||
|
||
RegStatus = RegOpenKeyEx(
|
||
hBranchKey, pszParentKey, 0,
|
||
KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey);
|
||
|
||
if (RegStatus != ERROR_SUCCESS) {
|
||
goto Clean0; // no error, nothing to delete
|
||
}
|
||
|
||
if (!RegDeleteNode(hKey, szKey1)) {
|
||
Status = CR_REGISTRY_ERROR;
|
||
goto Clean0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
Clean0:
|
||
|
||
if (hKey != NULL) {
|
||
RegCloseKey(hKey);
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // DeletePrivateKey
|
||
|
||
|
||
|
||
BOOL
|
||
RegDeleteNode(
|
||
HKEY hParentKey,
|
||
LPCWSTR szKey
|
||
)
|
||
{
|
||
ULONG ulSize = 0;
|
||
LONG RegStatus = ERROR_SUCCESS;
|
||
HKEY hKey = NULL;
|
||
WCHAR szSubKey[MAX_PATH];
|
||
|
||
|
||
//
|
||
// attempt to delete the key
|
||
//
|
||
if (RegDeleteKey(hParentKey, szKey) != ERROR_SUCCESS) {
|
||
|
||
RegStatus = RegOpenKeyEx(
|
||
hParentKey, szKey, 0, KEY_ALL_ACCESS, &hKey);
|
||
|
||
//
|
||
// enumerate subkeys and delete those nodes
|
||
//
|
||
while (RegStatus == ERROR_SUCCESS) {
|
||
//
|
||
// enumerate the first level children under the profile key
|
||
// (always use index 0, enumeration looses track when a key
|
||
// is added or deleted)
|
||
//
|
||
ulSize = MAX_PATH;
|
||
RegStatus = RegEnumKeyEx(
|
||
hKey, 0, szSubKey, &ulSize, NULL, NULL, NULL, NULL);
|
||
|
||
if (RegStatus == ERROR_SUCCESS) {
|
||
RegDeleteNode(hKey, szSubKey);
|
||
}
|
||
}
|
||
|
||
//
|
||
// either an error occured that prevents me from deleting the
|
||
// keys (like the key doesn't exist in the first place or an
|
||
// access violation) or the subkeys have been deleted, try
|
||
// deleting the top level key again
|
||
//
|
||
RegCloseKey(hKey);
|
||
RegDeleteKey(hParentKey, szKey);
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
} // RegDeleteNode
|
||
|
||
|
||
|
||
BOOL
|
||
Split1(
|
||
IN LPCWSTR pszString,
|
||
OUT LPWSTR pszString1,
|
||
OUT LPWSTR pszString2
|
||
)
|
||
{
|
||
BOOL Status = TRUE;
|
||
LPWSTR p;
|
||
|
||
|
||
//
|
||
// Split the string at the first backslash character
|
||
//
|
||
|
||
try {
|
||
|
||
lstrcpy(pszString1, pszString);
|
||
for (p = pszString1; (*p) && (*p != TEXT('\\')); p++);
|
||
|
||
if (*p == TEXT('\0')) {
|
||
Status = FALSE;
|
||
goto Clean0;
|
||
}
|
||
|
||
*p = TEXT('\0'); // truncate string1
|
||
p++;
|
||
lstrcpy(pszString2, p); // the rest is string2
|
||
|
||
|
||
Clean0:
|
||
NOTHING;
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = FALSE;
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // Split1
|
||
|
||
|
||
|
||
BOOL
|
||
Split2(
|
||
IN LPCWSTR pszString,
|
||
OUT LPWSTR pszString1,
|
||
OUT LPWSTR pszString2
|
||
)
|
||
{
|
||
BOOL Status = TRUE;
|
||
LPWSTR p;
|
||
|
||
|
||
//
|
||
// Split the string at the second backslash character
|
||
//
|
||
|
||
try {
|
||
|
||
lstrcpy(pszString1, pszString);
|
||
for (p = pszString1; (*p) && (*p != TEXT('\\')); p++); // first
|
||
for (p++; (*p) && (*p != TEXT('\\')); p++); // second
|
||
|
||
*p = TEXT('\0'); // truncate string1
|
||
p++;
|
||
lstrcpy(pszString2, p); // the rest is string2
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
Status = FALSE;
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // Split2
|
||
|
||
|
||
|
||
CONFIGRET
|
||
GetDevNodeKeyPath(
|
||
IN handle_t hBinding,
|
||
IN LPCWSTR pDeviceID,
|
||
IN ULONG ulFlags,
|
||
IN ULONG ulHardwareProfile,
|
||
OUT LPWSTR pszBaseKey,
|
||
OUT LPWSTR pszPrivateKey
|
||
)
|
||
{
|
||
CONFIGRET Status = CR_SUCCESS;
|
||
WCHAR szClassInstance[MAX_PATH], szEnumerator[MAX_DEVICE_ID_LEN];
|
||
ULONG ulSize, ulDataType = 0;
|
||
ULONG ulTransferLen;
|
||
|
||
|
||
//-------------------------------------------------------------
|
||
// form the key for the software branch case
|
||
//-------------------------------------------------------------
|
||
|
||
if (ulFlags & CM_REGISTRY_SOFTWARE) {
|
||
//
|
||
// retrieve the class name and instance ordinal by calling
|
||
// the server's reg prop routine
|
||
//
|
||
ulSize = ulTransferLen = sizeof(szClassInstance);
|
||
|
||
RpcTryExcept {
|
||
|
||
Status = PNP_GetDeviceRegProp(
|
||
hBinding,
|
||
pDeviceID,
|
||
CM_DRP_DRIVER,
|
||
&ulDataType,
|
||
(LPBYTE)szClassInstance,
|
||
&ulTransferLen,
|
||
&ulSize,
|
||
0);
|
||
}
|
||
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP_GetDeviceRegProp caused an exception (%d)\n",
|
||
RpcExceptionCode()));
|
||
|
||
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
||
}
|
||
RpcEndExcept
|
||
|
||
if (Status != CR_SUCCESS || *szClassInstance == '\0') {
|
||
//
|
||
// no Driver (class instance) value yet so ask the server to
|
||
// create a new unique one
|
||
//
|
||
ulSize = sizeof(szClassInstance);
|
||
|
||
RpcTryExcept {
|
||
|
||
Status = PNP_GetClassInstance(
|
||
hBinding,
|
||
pDeviceID,
|
||
szClassInstance,
|
||
ulSize);
|
||
}
|
||
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
|
||
KdPrintEx((DPFLTR_PNPMGR_ID,
|
||
DBGF_ERRORS,
|
||
"PNP_GetClassInstance caused an exception (%d)\n",
|
||
RpcExceptionCode()));
|
||
|
||
Status = MapRpcExceptionToCR(RpcExceptionCode());
|
||
}
|
||
RpcEndExcept
|
||
|
||
if (Status != CR_SUCCESS) {
|
||
goto Clean0;
|
||
}
|
||
}
|
||
|
||
//
|
||
// the <instance> part of the class instance is the private part
|
||
//
|
||
Split1(szClassInstance, szClassInstance, pszPrivateKey);
|
||
|
||
//
|
||
// config-specific software branch case
|
||
//
|
||
if (ulFlags & CM_REGISTRY_CONFIG) {
|
||
//
|
||
// curent config
|
||
//
|
||
// System\CCC\Hardware Profiles\Current
|
||
// \System\CCC\Control\Class\<DevNodeClassInstance>
|
||
//
|
||
if (ulHardwareProfile == 0) {
|
||
|
||
wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
|
||
REGSTR_PATH_HWPROFILES,
|
||
REGSTR_KEY_CURRENT,
|
||
REGSTR_PATH_CLASS_NT,
|
||
szClassInstance);
|
||
}
|
||
|
||
//
|
||
// all configs, use substitute string for profile id
|
||
//
|
||
else if (ulHardwareProfile == 0xFFFFFFFF) {
|
||
|
||
wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
|
||
REGSTR_PATH_HWPROFILES,
|
||
TEXT("%s"),
|
||
REGSTR_PATH_CLASS_NT,
|
||
szClassInstance);
|
||
}
|
||
|
||
//
|
||
// specific profile specified
|
||
//
|
||
// System\CCC\Hardware Profiles\<profile>
|
||
// \System\CCC\Control\Class\<DevNodeClassInstance>
|
||
//
|
||
else {
|
||
wsprintf(pszBaseKey, TEXT("%s\\%04u\\%s\\%s"),
|
||
REGSTR_PATH_HWPROFILES,
|
||
ulHardwareProfile,
|
||
REGSTR_PATH_CLASS_NT,
|
||
szClassInstance);
|
||
}
|
||
}
|
||
|
||
//
|
||
// not config-specific
|
||
// System\CCC\Control\Class\<DevNodeClassInstance>
|
||
//
|
||
else {
|
||
wsprintf(pszBaseKey, TEXT("%s\\%s"),
|
||
REGSTR_PATH_CLASS_NT,
|
||
szClassInstance);
|
||
}
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------
|
||
// form the key for the hardware branch case
|
||
//-------------------------------------------------------------
|
||
|
||
else {
|
||
//
|
||
// config-specific hardware branch case
|
||
//
|
||
if (ulFlags & CM_REGISTRY_CONFIG) {
|
||
|
||
//
|
||
// for profile specific, the <device>\<instance> part of
|
||
// the device id is the private part
|
||
//
|
||
Split1(pDeviceID, szEnumerator, pszPrivateKey);
|
||
|
||
//
|
||
// curent config
|
||
//
|
||
if (ulHardwareProfile == 0) {
|
||
|
||
wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
|
||
REGSTR_PATH_HWPROFILES,
|
||
REGSTR_KEY_CURRENT,
|
||
REGSTR_PATH_SYSTEMENUM,
|
||
szEnumerator);
|
||
}
|
||
|
||
//
|
||
// all configs, use replacement symbol for profile id
|
||
//
|
||
else if (ulHardwareProfile == 0xFFFFFFFF) {
|
||
|
||
wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
|
||
REGSTR_PATH_HWPROFILES,
|
||
TEXT("%s"),
|
||
REGSTR_PATH_SYSTEMENUM,
|
||
szEnumerator);
|
||
}
|
||
|
||
//
|
||
// specific profile specified
|
||
//
|
||
else {
|
||
wsprintf(pszBaseKey, TEXT("%s\\%04u\\%s\\%s"),
|
||
REGSTR_PATH_HWPROFILES,
|
||
ulHardwareProfile,
|
||
REGSTR_PATH_SYSTEMENUM,
|
||
szEnumerator);
|
||
}
|
||
}
|
||
|
||
else if (ulFlags & CM_REGISTRY_USER) {
|
||
//
|
||
// for hardware user key, the <device>\<instance> part of
|
||
// the device id is the private part
|
||
//
|
||
Split1(pDeviceID, szEnumerator, pszPrivateKey);
|
||
|
||
wsprintf(pszBaseKey, TEXT("%s\\%s"),
|
||
REGSTR_PATH_SYSTEMENUM,
|
||
szEnumerator);
|
||
}
|
||
|
||
//
|
||
// not config-specific
|
||
//
|
||
else {
|
||
wsprintf(pszBaseKey, TEXT("%s\\%s"),
|
||
REGSTR_PATH_SYSTEMENUM,
|
||
pDeviceID);
|
||
|
||
lstrcpy(pszPrivateKey, REGSTR_KEY_DEVICEPARAMETERS);
|
||
}
|
||
}
|
||
|
||
|
||
Clean0:
|
||
|
||
return Status;
|
||
|
||
} // GetDevNodeKeyPath
|
||
|
||
|
||
|
||
CONFIGRET
|
||
MapRpcExceptionToCR(
|
||
ULONG ulRpcExceptionCode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine takes an rpc exception code (typically received by
|
||
calling RpcExceptionCode) and returns a corresponding CR_ error
|
||
code.
|
||
|
||
Arguments:
|
||
|
||
ulRpcExceptionCode An RPC_S_ or RPC_X_ exception error code.
|
||
|
||
Return Value:
|
||
|
||
Return value is one of the CR_ error codes.
|
||
|
||
--*/
|
||
|
||
{
|
||
CONFIGRET Status = CR_FAILURE;
|
||
|
||
|
||
switch(ulRpcExceptionCode) {
|
||
|
||
//
|
||
// binding or machine name errors
|
||
//
|
||
case RPC_S_INVALID_STRING_BINDING: // 1700L
|
||
case RPC_S_WRONG_KIND_OF_BINDING: // 1701L
|
||
case RPC_S_INVALID_BINDING: // 1702L
|
||
case RPC_S_PROTSEQ_NOT_SUPPORTED: // 1703L
|
||
case RPC_S_INVALID_RPC_PROTSEQ: // 1704L
|
||
case RPC_S_INVALID_STRING_UUID: // 1705L
|
||
case RPC_S_INVALID_ENDPOINT_FORMAT: // 1706L
|
||
case RPC_S_INVALID_NET_ADDR: // 1707L
|
||
case RPC_S_NO_ENDPOINT_FOUND: // 1708L
|
||
case RPC_S_NO_MORE_BINDINGS: // 1806L
|
||
case RPC_S_CANT_CREATE_ENDPOINT: // 1720L
|
||
|
||
Status = CR_INVALID_MACHINENAME;
|
||
break;
|
||
|
||
//
|
||
// general rpc communication failure
|
||
//
|
||
case RPC_S_INVALID_NETWORK_OPTIONS: // 1724L
|
||
case RPC_S_CALL_FAILED: // 1726L
|
||
case RPC_S_CALL_FAILED_DNE: // 1727L
|
||
case RPC_S_PROTOCOL_ERROR: // 1728L
|
||
case RPC_S_UNSUPPORTED_TRANS_SYN: // 1730L
|
||
|
||
Status = CR_REMOTE_COMM_FAILURE;
|
||
break;
|
||
|
||
//
|
||
// couldn't make connection to that machine
|
||
//
|
||
case RPC_S_SERVER_UNAVAILABLE: // 1722L
|
||
case RPC_S_SERVER_TOO_BUSY: // 1723L
|
||
|
||
Status = CR_MACHINE_UNAVAILABLE;
|
||
break;
|
||
|
||
|
||
//
|
||
// server doesn't exist or not right version
|
||
//
|
||
case RPC_S_INVALID_VERS_OPTION: // 1756L
|
||
case RPC_S_INTERFACE_NOT_FOUND: // 1759L
|
||
case RPC_S_UNKNOWN_IF: // 1717L
|
||
|
||
Status = CR_NO_CM_SERVICES;
|
||
break;
|
||
|
||
//
|
||
// any other RPC exceptions will just be general failures
|
||
//
|
||
default:
|
||
Status = CR_FAILURE;
|
||
break;
|
||
}
|
||
|
||
return Status;
|
||
|
||
} // MapRpcExceptionToCR
|
||
|
||
|
||
|