Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

878 lines
22 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. cutil.c
  5. Abstract:
  6. This module contains general utility routines used by both cfgmgr32
  7. and umpnpmgr.
  8. IsLegalDeviceId
  9. SplitDeviceInstanceString
  10. DeletePrivateKey
  11. RegDeleteNode
  12. Split1
  13. Split2
  14. GetDevNodeKeyPath
  15. MapRpcExceptionToCR
  16. Author:
  17. Paula Tomlinson (paulat) 7-12-1995
  18. Environment:
  19. User mode only.
  20. Revision History:
  21. 12-July-1995 paulat
  22. Creation and initial implementation.
  23. --*/
  24. //
  25. // includes
  26. //
  27. #include "precomp.h"
  28. #include "umpnplib.h"
  29. //
  30. // Common private utility routines (used by client and server)
  31. //
  32. BOOL
  33. IsLegalDeviceId(
  34. IN LPCWSTR pszDeviceInstance
  35. )
  36. /*++
  37. Routine Description:
  38. This routine parses the device instance string and validates whether it
  39. conforms to the appropriate rules, including:
  40. - Total length of the device instance path must not be longer than
  41. MAX_DEVICE_ID_LEN characters.
  42. - The device instance path must contain exactly 3 non-empty path components.
  43. - The device instance path string must not contain any "invalid characters".
  44. Invalid characters are:
  45. c <= 0x20 (' ')
  46. c > 0x7F
  47. c == 0x2C (',')
  48. Arguments:
  49. pszDeviceInstance - Device instance path.
  50. Return value:
  51. The return value is TRUE if the device instance path string conforms to the
  52. rules.
  53. --*/
  54. {
  55. BOOL Status;
  56. LPCWSTR p;
  57. ULONG ulTotalLength = 0;
  58. ULONG ulComponentLength = 0, ulComponents = 1;
  59. try {
  60. //
  61. // An empty string is used for an optional device instance path.
  62. //
  63. if ((pszDeviceInstance == NULL) || (*pszDeviceInstance == L'\0')) {
  64. Status = TRUE;
  65. goto Clean0;
  66. }
  67. //
  68. // Walk over the entire device instance path, counting the total length,
  69. // individual path component lengths, and checking for the presence of
  70. // invalid characters.
  71. //
  72. for (p = pszDeviceInstance; *p; p++) {
  73. //
  74. // Make sure the device instance path isn't too long.
  75. //
  76. ulTotalLength++;
  77. if (ulTotalLength > MAX_DEVICE_ID_LEN) {
  78. KdPrintEx((DPFLTR_PNPMGR_ID,
  79. DBGF_ERRORS,
  80. "PNP: IsLegalDeviceId: "
  81. "device instance path %ws longer than "
  82. "MAX_DEVICE_ID_LEN characters!\n",
  83. pszDeviceInstance));
  84. //ASSERT(ulTotalLength <= MAX_DEVICE_ID_LEN);
  85. Status = FALSE;
  86. goto Clean0;
  87. }
  88. //
  89. // Check for the presence of invalid characters.
  90. //
  91. if ((*p <= L' ') || (*p > (WCHAR)0x7F) || (*p == L',')) {
  92. KdPrintEx((DPFLTR_PNPMGR_ID,
  93. DBGF_ERRORS,
  94. "PNP: IsLegalDeviceId: "
  95. "device instance path %ws contains invalid character (0x%lx)!\n",
  96. pszDeviceInstance, *p));
  97. //ASSERT((*p > L' ') && (*p <= (WCHAR)0x7F) && (*p != L','));
  98. Status = FALSE;
  99. goto Clean0;
  100. }
  101. //
  102. // Check the length of individual path components.
  103. //
  104. if (*p == L'\\') {
  105. //
  106. // It is illegal for a device instance path to have multiple
  107. // consecutive path separators, or to start with one.
  108. //
  109. if (ulComponentLength == 0) {
  110. KdPrintEx((DPFLTR_PNPMGR_ID,
  111. DBGF_ERRORS,
  112. "PNP: IsLegalDeviceId: "
  113. "device instance path %ws contains "
  114. "invalid path component!\n",
  115. pszDeviceInstance));
  116. //ASSERT(ulComponentLength != 0);
  117. Status = FALSE;
  118. goto Clean0;
  119. }
  120. ulComponentLength = 0;
  121. ulComponents++;
  122. } else {
  123. //
  124. // Count the length of this path component to verify it's not empty.
  125. //
  126. ulComponentLength++;
  127. }
  128. }
  129. //
  130. // It is illegal for a device instance path to end with a path separator
  131. // character.
  132. //
  133. if (ulComponentLength == 0) {
  134. KdPrintEx((DPFLTR_PNPMGR_ID,
  135. DBGF_ERRORS,
  136. "PNP: IsLegalDeviceId: "
  137. "device instance path %ws has trailing '\\' char!\n",
  138. pszDeviceInstance));
  139. //ASSERT(ulComponentLength != 0);
  140. Status = FALSE;
  141. goto Clean0;
  142. }
  143. //
  144. // A valid device instance path must contain exactly 3 path components:
  145. // an enumerator id, a device id, and an instance id.
  146. //
  147. if (ulComponents != 3) {
  148. KdPrintEx((DPFLTR_PNPMGR_ID,
  149. DBGF_ERRORS,
  150. "PNP: IsLegalDeviceId: "
  151. "device instance path %ws contains "
  152. "invalid number of path components!\n",
  153. pszDeviceInstance));
  154. //ASSERT(ulComponents == 3);
  155. Status = FALSE;
  156. goto Clean0;
  157. }
  158. Status = TRUE;
  159. Clean0:
  160. NOTHING;
  161. } except(EXCEPTION_EXECUTE_HANDLER) {
  162. KdPrintEx((DPFLTR_PNPMGR_ID,
  163. DBGF_ERRORS,
  164. "PNP: Exception in IsLegalDeviceId!! "
  165. "exception code = %d\n",
  166. GetExceptionCode()));
  167. Status = FALSE;
  168. }
  169. return Status;
  170. } // IsLegalDeviceId
  171. BOOL
  172. SplitDeviceInstanceString(
  173. IN LPCWSTR pszDeviceInstance,
  174. OUT LPWSTR pszBase,
  175. OUT LPWSTR pszDeviceID,
  176. OUT LPWSTR pszInstanceID
  177. )
  178. /*++
  179. Routine Description:
  180. This routine parses a device instance string into it's three component
  181. parts. Since this is an internal routine, NO error checking is done on
  182. the pszBase, pszDeviceID, and pszInstanceID routines; I always assume that
  183. valid pointers are passed in and that each of these buffers is at least
  184. MAX_DEVICE_ID_LEN characters in length. I do some error checking on the
  185. pszDeviceInstance string since it is passed in from the client side.
  186. Arguments:
  187. Return value:
  188. The return value is TRUE if the function suceeds and FALSE if it fails.
  189. --*/
  190. {
  191. UINT ulLength, i, j;
  192. ulLength = lstrlen(pszDeviceInstance);
  193. //
  194. // parse the string for the first backslash character
  195. //
  196. for (i=0; i < ulLength && pszDeviceInstance[i] != '\0' &&
  197. pszDeviceInstance[i] != '\\'; i++);
  198. if (pszDeviceInstance[i] != '\\') {
  199. lstrcpyn(pszBase, pszDeviceInstance,MAX_DEVICE_ID_LEN);
  200. *pszDeviceID = '\0';
  201. *pszInstanceID = '\0';
  202. return FALSE; // not a complete device instance string
  203. }
  204. i++; // increment past the backslash character
  205. if (i < ulLength && pszDeviceInstance[i] != '\0') {
  206. lstrcpyn(pszBase, pszDeviceInstance, min(i,MAX_DEVICE_ID_LEN));
  207. }
  208. else {
  209. *pszBase = '\0';
  210. *pszDeviceID = '\0';
  211. *pszInstanceID = '\0';
  212. return FALSE;
  213. }
  214. //
  215. // parse the string for second backslash character
  216. //
  217. for (j=i; j < ulLength && pszDeviceInstance[j] != '\0' &&
  218. pszDeviceInstance[j] != '\\'; j++);
  219. if (pszDeviceInstance[j] != '\\' || j > ulLength) {
  220. lstrcpyn(pszDeviceID, &pszDeviceInstance[i],MAX_DEVICE_ID_LEN);
  221. *pszInstanceID = '\0';
  222. return FALSE;
  223. }
  224. j++;
  225. lstrcpyn(pszDeviceID, &pszDeviceInstance[i], min(j-i,MAX_DEVICE_ID_LEN));
  226. lstrcpyn(pszInstanceID, &pszDeviceInstance[j], min((ulLength-j+1),MAX_DEVICE_ID_LEN));
  227. return TRUE;
  228. } // SplitDeviceInstanceString
  229. CONFIGRET
  230. DeletePrivateKey(
  231. IN HKEY hBranchKey,
  232. IN LPCWSTR pszParentKey,
  233. IN LPCWSTR pszChildKey
  234. )
  235. {
  236. CONFIGRET Status = CR_SUCCESS;
  237. LONG RegStatus = ERROR_SUCCESS;
  238. WCHAR RegStr[2*MAX_CM_PATH],
  239. szKey1[MAX_CM_PATH],
  240. szKey2[MAX_CM_PATH];
  241. HKEY hKey = NULL;
  242. ULONG ulSubKeys = 0;
  243. //
  244. // Make sure the specified registry key paths are valid.
  245. //
  246. if ((pszParentKey == NULL) ||
  247. (pszChildKey == NULL) ||
  248. ((lstrlen(pszParentKey) + 1) > MAX_CM_PATH) ||
  249. ((lstrlen(pszChildKey) + 1) > MAX_CM_PATH)) {
  250. Status = CR_INVALID_POINTER;
  251. goto Clean0;
  252. }
  253. //
  254. // is the specified child key a compound registry key?
  255. //
  256. if (!Split1(pszChildKey, szKey1, szKey2)) {
  257. //------------------------------------------------------------------
  258. // Only a single child key was specified, so just open the parent
  259. // registry key and delete the child (and any of its subkeys)
  260. //------------------------------------------------------------------
  261. if (RegOpenKeyEx(hBranchKey, pszParentKey, 0,
  262. KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS) {
  263. goto Clean0; // no error, nothing to delete
  264. }
  265. if (!RegDeleteNode(hKey, pszChildKey)) {
  266. Status = CR_REGISTRY_ERROR;
  267. goto Clean0;
  268. }
  269. }
  270. else {
  271. //------------------------------------------------------------------
  272. // if a compound registry path was passed in, such as key1\key2
  273. // then always delete key2 but delete key1 only if it has no other
  274. // subkeys besides key2.
  275. //------------------------------------------------------------------
  276. //
  277. // open the first level key
  278. //
  279. wsprintf(RegStr, TEXT("%s\\%s"),
  280. pszParentKey,
  281. szKey1);
  282. RegStatus = RegOpenKeyEx(
  283. hBranchKey, RegStr, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
  284. &hKey);
  285. if (RegStatus != ERROR_SUCCESS) {
  286. goto Clean0; // no error, nothing to delete
  287. }
  288. //
  289. // try to delete the second level key
  290. //
  291. if (!RegDeleteNode(hKey, szKey2)) {
  292. goto Clean0; // no error, nothing to delete
  293. }
  294. //
  295. // How many subkeys are remaining?
  296. //
  297. RegStatus = RegQueryInfoKey(
  298. hKey, NULL, NULL, NULL, &ulSubKeys,
  299. NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  300. if (RegStatus != ERROR_SUCCESS) {
  301. goto Clean0; // nothing to delete
  302. }
  303. //
  304. // if no more subkeys, then delete the first level key
  305. //
  306. if (ulSubKeys == 0) {
  307. RegCloseKey(hKey);
  308. hKey = NULL;
  309. RegStatus = RegOpenKeyEx(
  310. hBranchKey, pszParentKey, 0,
  311. KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey);
  312. if (RegStatus != ERROR_SUCCESS) {
  313. goto Clean0; // no error, nothing to delete
  314. }
  315. if (!RegDeleteNode(hKey, szKey1)) {
  316. Status = CR_REGISTRY_ERROR;
  317. goto Clean0;
  318. }
  319. }
  320. }
  321. Clean0:
  322. if (hKey != NULL) {
  323. RegCloseKey(hKey);
  324. }
  325. return Status;
  326. } // DeletePrivateKey
  327. BOOL
  328. RegDeleteNode(
  329. HKEY hParentKey,
  330. LPCWSTR szKey
  331. )
  332. {
  333. ULONG ulSize = 0;
  334. LONG RegStatus = ERROR_SUCCESS;
  335. HKEY hKey = NULL;
  336. WCHAR szSubKey[MAX_PATH];
  337. //
  338. // attempt to delete the key
  339. //
  340. if (RegDeleteKey(hParentKey, szKey) != ERROR_SUCCESS) {
  341. RegStatus = RegOpenKeyEx(
  342. hParentKey, szKey, 0, KEY_ALL_ACCESS, &hKey);
  343. //
  344. // enumerate subkeys and delete those nodes
  345. //
  346. while (RegStatus == ERROR_SUCCESS) {
  347. //
  348. // enumerate the first level children under the profile key
  349. // (always use index 0, enumeration looses track when a key
  350. // is added or deleted)
  351. //
  352. ulSize = MAX_PATH;
  353. RegStatus = RegEnumKeyEx(
  354. hKey, 0, szSubKey, &ulSize, NULL, NULL, NULL, NULL);
  355. if (RegStatus == ERROR_SUCCESS) {
  356. RegDeleteNode(hKey, szSubKey);
  357. }
  358. }
  359. //
  360. // either an error occured that prevents me from deleting the
  361. // keys (like the key doesn't exist in the first place or an
  362. // access violation) or the subkeys have been deleted, try
  363. // deleting the top level key again
  364. //
  365. RegCloseKey(hKey);
  366. RegDeleteKey(hParentKey, szKey);
  367. }
  368. return TRUE;
  369. } // RegDeleteNode
  370. BOOL
  371. Split1(
  372. IN LPCWSTR pszString,
  373. OUT LPWSTR pszString1,
  374. OUT LPWSTR pszString2
  375. )
  376. {
  377. BOOL Status = TRUE;
  378. LPWSTR p;
  379. //
  380. // Split the string at the first backslash character
  381. //
  382. try {
  383. lstrcpy(pszString1, pszString);
  384. for (p = pszString1; (*p) && (*p != TEXT('\\')); p++);
  385. if (*p == TEXT('\0')) {
  386. Status = FALSE;
  387. goto Clean0;
  388. }
  389. *p = TEXT('\0'); // truncate string1
  390. p++;
  391. lstrcpy(pszString2, p); // the rest is string2
  392. Clean0:
  393. NOTHING;
  394. } except(EXCEPTION_EXECUTE_HANDLER) {
  395. Status = FALSE;
  396. }
  397. return Status;
  398. } // Split1
  399. BOOL
  400. Split2(
  401. IN LPCWSTR pszString,
  402. OUT LPWSTR pszString1,
  403. OUT LPWSTR pszString2
  404. )
  405. {
  406. BOOL Status = TRUE;
  407. LPWSTR p;
  408. //
  409. // Split the string at the second backslash character
  410. //
  411. try {
  412. lstrcpy(pszString1, pszString);
  413. for (p = pszString1; (*p) && (*p != TEXT('\\')); p++); // first
  414. for (p++; (*p) && (*p != TEXT('\\')); p++); // second
  415. *p = TEXT('\0'); // truncate string1
  416. p++;
  417. lstrcpy(pszString2, p); // the rest is string2
  418. } except(EXCEPTION_EXECUTE_HANDLER) {
  419. Status = FALSE;
  420. }
  421. return Status;
  422. } // Split2
  423. CONFIGRET
  424. GetDevNodeKeyPath(
  425. IN handle_t hBinding,
  426. IN LPCWSTR pDeviceID,
  427. IN ULONG ulFlags,
  428. IN ULONG ulHardwareProfile,
  429. OUT LPWSTR pszBaseKey,
  430. OUT LPWSTR pszPrivateKey
  431. )
  432. {
  433. CONFIGRET Status = CR_SUCCESS;
  434. WCHAR szClassInstance[MAX_PATH], szEnumerator[MAX_DEVICE_ID_LEN];
  435. ULONG ulSize, ulDataType = 0;
  436. ULONG ulTransferLen;
  437. //-------------------------------------------------------------
  438. // form the key for the software branch case
  439. //-------------------------------------------------------------
  440. if (ulFlags & CM_REGISTRY_SOFTWARE) {
  441. //
  442. // retrieve the class name and instance ordinal by calling
  443. // the server's reg prop routine
  444. //
  445. ulSize = ulTransferLen = sizeof(szClassInstance);
  446. RpcTryExcept {
  447. Status = PNP_GetDeviceRegProp(
  448. hBinding,
  449. pDeviceID,
  450. CM_DRP_DRIVER,
  451. &ulDataType,
  452. (LPBYTE)szClassInstance,
  453. &ulTransferLen,
  454. &ulSize,
  455. 0);
  456. }
  457. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  458. KdPrintEx((DPFLTR_PNPMGR_ID,
  459. DBGF_ERRORS,
  460. "PNP_GetDeviceRegProp caused an exception (%d)\n",
  461. RpcExceptionCode()));
  462. Status = MapRpcExceptionToCR(RpcExceptionCode());
  463. }
  464. RpcEndExcept
  465. if (Status != CR_SUCCESS || *szClassInstance == '\0') {
  466. //
  467. // no Driver (class instance) value yet so ask the server to
  468. // create a new unique one
  469. //
  470. ulSize = sizeof(szClassInstance);
  471. RpcTryExcept {
  472. Status = PNP_GetClassInstance(
  473. hBinding,
  474. pDeviceID,
  475. szClassInstance,
  476. ulSize);
  477. }
  478. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode())) {
  479. KdPrintEx((DPFLTR_PNPMGR_ID,
  480. DBGF_ERRORS,
  481. "PNP_GetClassInstance caused an exception (%d)\n",
  482. RpcExceptionCode()));
  483. Status = MapRpcExceptionToCR(RpcExceptionCode());
  484. }
  485. RpcEndExcept
  486. if (Status != CR_SUCCESS) {
  487. goto Clean0;
  488. }
  489. }
  490. //
  491. // the <instance> part of the class instance is the private part
  492. //
  493. Split1(szClassInstance, szClassInstance, pszPrivateKey);
  494. //
  495. // config-specific software branch case
  496. //
  497. if (ulFlags & CM_REGISTRY_CONFIG) {
  498. //
  499. // curent config
  500. //
  501. // System\CCC\Hardware Profiles\Current
  502. // \System\CCC\Control\Class\<DevNodeClassInstance>
  503. //
  504. if (ulHardwareProfile == 0) {
  505. wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
  506. REGSTR_PATH_HWPROFILES,
  507. REGSTR_KEY_CURRENT,
  508. REGSTR_PATH_CLASS_NT,
  509. szClassInstance);
  510. }
  511. //
  512. // all configs, use substitute string for profile id
  513. //
  514. else if (ulHardwareProfile == 0xFFFFFFFF) {
  515. wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
  516. REGSTR_PATH_HWPROFILES,
  517. TEXT("%s"),
  518. REGSTR_PATH_CLASS_NT,
  519. szClassInstance);
  520. }
  521. //
  522. // specific profile specified
  523. //
  524. // System\CCC\Hardware Profiles\<profile>
  525. // \System\CCC\Control\Class\<DevNodeClassInstance>
  526. //
  527. else {
  528. wsprintf(pszBaseKey, TEXT("%s\\%04u\\%s\\%s"),
  529. REGSTR_PATH_HWPROFILES,
  530. ulHardwareProfile,
  531. REGSTR_PATH_CLASS_NT,
  532. szClassInstance);
  533. }
  534. }
  535. //
  536. // not config-specific
  537. // System\CCC\Control\Class\<DevNodeClassInstance>
  538. //
  539. else {
  540. wsprintf(pszBaseKey, TEXT("%s\\%s"),
  541. REGSTR_PATH_CLASS_NT,
  542. szClassInstance);
  543. }
  544. }
  545. //-------------------------------------------------------------
  546. // form the key for the hardware branch case
  547. //-------------------------------------------------------------
  548. else {
  549. //
  550. // config-specific hardware branch case
  551. //
  552. if (ulFlags & CM_REGISTRY_CONFIG) {
  553. //
  554. // for profile specific, the <device>\<instance> part of
  555. // the device id is the private part
  556. //
  557. Split1(pDeviceID, szEnumerator, pszPrivateKey);
  558. //
  559. // curent config
  560. //
  561. if (ulHardwareProfile == 0) {
  562. wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
  563. REGSTR_PATH_HWPROFILES,
  564. REGSTR_KEY_CURRENT,
  565. REGSTR_PATH_SYSTEMENUM,
  566. szEnumerator);
  567. }
  568. //
  569. // all configs, use replacement symbol for profile id
  570. //
  571. else if (ulHardwareProfile == 0xFFFFFFFF) {
  572. wsprintf(pszBaseKey, TEXT("%s\\%s\\%s\\%s"),
  573. REGSTR_PATH_HWPROFILES,
  574. TEXT("%s"),
  575. REGSTR_PATH_SYSTEMENUM,
  576. szEnumerator);
  577. }
  578. //
  579. // specific profile specified
  580. //
  581. else {
  582. wsprintf(pszBaseKey, TEXT("%s\\%04u\\%s\\%s"),
  583. REGSTR_PATH_HWPROFILES,
  584. ulHardwareProfile,
  585. REGSTR_PATH_SYSTEMENUM,
  586. szEnumerator);
  587. }
  588. }
  589. else if (ulFlags & CM_REGISTRY_USER) {
  590. //
  591. // for hardware user key, the <device>\<instance> part of
  592. // the device id is the private part
  593. //
  594. Split1(pDeviceID, szEnumerator, pszPrivateKey);
  595. wsprintf(pszBaseKey, TEXT("%s\\%s"),
  596. REGSTR_PATH_SYSTEMENUM,
  597. szEnumerator);
  598. }
  599. //
  600. // not config-specific
  601. //
  602. else {
  603. wsprintf(pszBaseKey, TEXT("%s\\%s"),
  604. REGSTR_PATH_SYSTEMENUM,
  605. pDeviceID);
  606. lstrcpy(pszPrivateKey, REGSTR_KEY_DEVICEPARAMETERS);
  607. }
  608. }
  609. Clean0:
  610. return Status;
  611. } // GetDevNodeKeyPath
  612. CONFIGRET
  613. MapRpcExceptionToCR(
  614. ULONG ulRpcExceptionCode
  615. )
  616. /*++
  617. Routine Description:
  618. This routine takes an rpc exception code (typically received by
  619. calling RpcExceptionCode) and returns a corresponding CR_ error
  620. code.
  621. Arguments:
  622. ulRpcExceptionCode An RPC_S_ or RPC_X_ exception error code.
  623. Return Value:
  624. Return value is one of the CR_ error codes.
  625. --*/
  626. {
  627. CONFIGRET Status = CR_FAILURE;
  628. switch(ulRpcExceptionCode) {
  629. //
  630. // binding or machine name errors
  631. //
  632. case RPC_S_INVALID_STRING_BINDING: // 1700L
  633. case RPC_S_WRONG_KIND_OF_BINDING: // 1701L
  634. case RPC_S_INVALID_BINDING: // 1702L
  635. case RPC_S_PROTSEQ_NOT_SUPPORTED: // 1703L
  636. case RPC_S_INVALID_RPC_PROTSEQ: // 1704L
  637. case RPC_S_INVALID_STRING_UUID: // 1705L
  638. case RPC_S_INVALID_ENDPOINT_FORMAT: // 1706L
  639. case RPC_S_INVALID_NET_ADDR: // 1707L
  640. case RPC_S_NO_ENDPOINT_FOUND: // 1708L
  641. case RPC_S_NO_MORE_BINDINGS: // 1806L
  642. case RPC_S_CANT_CREATE_ENDPOINT: // 1720L
  643. Status = CR_INVALID_MACHINENAME;
  644. break;
  645. //
  646. // general rpc communication failure
  647. //
  648. case RPC_S_INVALID_NETWORK_OPTIONS: // 1724L
  649. case RPC_S_CALL_FAILED: // 1726L
  650. case RPC_S_CALL_FAILED_DNE: // 1727L
  651. case RPC_S_PROTOCOL_ERROR: // 1728L
  652. case RPC_S_UNSUPPORTED_TRANS_SYN: // 1730L
  653. Status = CR_REMOTE_COMM_FAILURE;
  654. break;
  655. //
  656. // couldn't make connection to that machine
  657. //
  658. case RPC_S_SERVER_UNAVAILABLE: // 1722L
  659. case RPC_S_SERVER_TOO_BUSY: // 1723L
  660. Status = CR_MACHINE_UNAVAILABLE;
  661. break;
  662. //
  663. // server doesn't exist or not right version
  664. //
  665. case RPC_S_INVALID_VERS_OPTION: // 1756L
  666. case RPC_S_INTERFACE_NOT_FOUND: // 1759L
  667. case RPC_S_UNKNOWN_IF: // 1717L
  668. Status = CR_NO_CM_SERVICES;
  669. break;
  670. //
  671. // any other RPC exceptions will just be general failures
  672. //
  673. default:
  674. Status = CR_FAILURE;
  675. break;
  676. }
  677. return Status;
  678. } // MapRpcExceptionToCR
  679.