Leaked source code of windows server 2003
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.

722 lines
21 KiB

  1. /*
  2. * oleutil.c - OLE utility functions module.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. #include "oleutil.h"
  9. /* Macros
  10. *********/
  11. /* macro for translating an HRESULT to a TWINRESULT */
  12. #define HRESULTToTWINRESULT(hr, TR) case hr: tr = TR; break
  13. /* Constants
  14. ************/
  15. /* maximum allowed registry lengths */
  16. #define MAX_REG_KEY_LEN MAX_PATH_LEN
  17. #define MAX_REG_VALUE_LEN MAX_PATH_LEN
  18. /* subkeys and associated lengths */
  19. #define CLSID_SUBKEY TEXT("CLSID")
  20. /* CLSID subkey length in bytes, including null terminator */
  21. #define CLSID_SUBKEY_LEN (5 + 1)
  22. #define IN_PROC_SERVER_SUBKEY TEXT("InProcServer32")
  23. /* InProcServer32 subkey length in bytes, including null terminator */
  24. #define IN_PROC_SERVER_SUBKEY_LEN (14 + 1)
  25. #define LOCAL_SERVER_SUBKEY TEXT("LocalServer32")
  26. /* LocalServer32 subkey length in bytes, including null terminator */
  27. #define LOCAL_SERVER_SUBKEY_LEN (13 + 1)
  28. #define RECONCILER_SUBKEY TEXT("Roles\\Reconciler")
  29. /* InProcServer32 subkey length in bytes, including null terminator */
  30. #define RECONCILER_SUBKEY_LEN (5 + 1 + 10 + 1)
  31. #define NOTIFY_SUBKEY TEXT("Roles\\NotifyReplica")
  32. /* InProcServer32 subkey length in bytes, including null terminator */
  33. #define NOTIFY_SUBKEY_LEN (5 + 1 + 13 + 1)
  34. #define COPY_SUBKEY TEXT("SingleChangeHook")
  35. /* copy subkey length in bytes, including null terminator */
  36. #define COPY_SUBKEY_LEN (16 + 1)
  37. /*
  38. * length of GUID subkey string in bytes, including null terminator
  39. *
  40. * "{12345678-1234-1234-1234-123456789012}"
  41. */
  42. #define GUID_SUBKEY_LEN (1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  43. /*
  44. * class ID key length in bytes, including null terminator
  45. *
  46. * "CLSID\{12345678-1234-1234-1234-123456789012}"
  47. */
  48. #define CLSID_REG_KEY_LEN (CLSID_SUBKEY_LEN + GUID_SUBKEY_LEN)
  49. /*
  50. * InProcServer32 key length in bytes, including null terminator
  51. *
  52. * "CLSID\{12345678-1234-1234-1234-123456789012}\InProcServer32"
  53. */
  54. #define IN_PROC_SERVER_REG_KEY_LEN (CLSID_REG_KEY_LEN + IN_PROC_SERVER_SUBKEY_LEN)
  55. /*
  56. * LocalServer32 key length in bytes, including null terminator
  57. *
  58. * "CLSID\{12345678-1234-1234-1234-123456789012}\LocalServer32"
  59. */
  60. #define LOCAL_SERVER_REG_KEY_LEN (CLSID_REG_KEY_LEN + LOCAL_SERVER_SUBKEY_LEN)
  61. /*
  62. * reconciler key length in bytes, including null terminator
  63. *
  64. * "CLSID\{12345678-1234-1234-1234-123456789012}\Roles\Reconciler"
  65. */
  66. #define RECONCILER_REG_KEY_LEN (CLSID_REG_KEY_LEN + RECONCILER_SUBKEY_LEN)
  67. /*
  68. * notify replica key length in bytes, including null terminator
  69. *
  70. * "CLSID\{12345678-1234-1234-1234-123456789012}\Roles\NotifyReplica"
  71. */
  72. #define NOTIFY_REG_KEY_LEN (CLSID_REG_KEY_LEN + NOTIFY_SUBKEY_LEN)
  73. /*
  74. * copy key length in bytes, including null terminator
  75. *
  76. * "CLSID\{12345678-1234-1234-1234-123456789012}\SingleChangeHook"
  77. */
  78. #define COPY_REG_KEY_LEN (CLSID_REG_KEY_LEN + COPY_SUBKEY_LEN)
  79. /* Macros
  80. *********/
  81. /*
  82. * Determine whether or not an integer value is within a given inclusive range.
  83. */
  84. #define IsWithin(test, first, last) ((UINT)((test) - (first)) <= (UINT)((last) - (first)))
  85. /***************************** Private Functions *****************************/
  86. /* Module Prototypes
  87. ********************/
  88. PRIVATE_CODE void MakeClsIDSubKey(PCGUID, LPCTSTR, LPTSTR, int);
  89. PRIVATE_CODE BOOL HexStringToDWORD(LPCTSTR *, PDWORD, UINT, TCHAR);
  90. PRIVATE_CODE BOOL StringToGUID(LPCTSTR, PGUID);
  91. PRIVATE_CODE HRESULT GetClassID(LPCTSTR, LPCTSTR, PCLSID);
  92. /*
  93. ** MakeClsIDSubKey()
  94. **
  95. **
  96. **
  97. ** Arguments:
  98. **
  99. ** Returns:
  100. **
  101. ** Side Effects: none
  102. */
  103. PRIVATE_CODE void MakeClsIDSubKey(PCGUID pcguid, LPCTSTR pcszSubKey,
  104. LPTSTR pszRegKeyBuf, int cchMax)
  105. {
  106. ASSERT(IS_VALID_STRUCT_PTR(pcguid, CGUID));
  107. ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR));
  108. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszRegKeyBuf, STR, CLSID_REG_KEY_LEN + lstrlen(pcszSubKey) + 1));
  109. /* (- 1) for null terminator. */
  110. EVAL(wnsprintf(pszRegKeyBuf, cchMax,
  111. TEXT("CLSID\\{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\\%s"),
  112. pcguid->Data1,
  113. pcguid->Data2,
  114. pcguid->Data3,
  115. pcguid->Data4[0],
  116. pcguid->Data4[1],
  117. pcguid->Data4[2],
  118. pcguid->Data4[3],
  119. pcguid->Data4[4],
  120. pcguid->Data4[5],
  121. pcguid->Data4[6],
  122. pcguid->Data4[7],
  123. pcszSubKey)
  124. == CLSID_REG_KEY_LEN + lstrlen(pcszSubKey));
  125. return;
  126. }
  127. /*
  128. ** HexStringToDWORD()
  129. **
  130. **
  131. **
  132. ** Arguments:
  133. **
  134. ** Returns:
  135. **
  136. ** Side Effects: none
  137. */
  138. PRIVATE_CODE BOOL HexStringToDWORD(LPCTSTR *ppcsz, PDWORD pdwValue, UINT ucDigits,
  139. TCHAR chDelimiter)
  140. {
  141. BOOL bResult = TRUE;
  142. UINT u;
  143. /* chDelimiter may be any value. */
  144. ASSERT(IS_VALID_WRITE_PTR(ppcsz, LPCTSTR));
  145. ASSERT(IS_VALID_STRING_PTR(*ppcsz, CSTR));
  146. ASSERT(IS_VALID_WRITE_PTR(pdwValue, DWORD));
  147. ASSERT(ucDigits <= 8);
  148. *pdwValue = 0;
  149. for (u = 0; u < ucDigits; u++)
  150. {
  151. TCHAR ch = (*ppcsz)[u];
  152. if (IsWithin(ch, TEXT('0'), TEXT('9')))
  153. *pdwValue = (*pdwValue << 4) + ch - TEXT('0');
  154. else if (IsWithin((ch |= (TEXT('a') - TEXT('A'))), TEXT('a'), TEXT('f')))
  155. *pdwValue = (*pdwValue << 4) + ch - TEXT('a') + 10;
  156. else
  157. {
  158. WARNING_OUT((TEXT("HexStringToDWORD(): Found unrecognized hex digit %c."),
  159. ch));
  160. bResult = FALSE;
  161. break;
  162. }
  163. }
  164. if (bResult)
  165. {
  166. if (chDelimiter)
  167. {
  168. bResult = ((*ppcsz)[u++] == chDelimiter);
  169. if (! bResult)
  170. WARNING_OUT((TEXT("HexStringToDWORD(): Character %c does not match required delimiter %c."),
  171. (*ppcsz)[u],
  172. chDelimiter));
  173. }
  174. *ppcsz += u;
  175. }
  176. ASSERT(IS_VALID_STRING_PTR(*ppcsz, CSTR));
  177. return(bResult);
  178. }
  179. /*
  180. ** StringToGUID()
  181. **
  182. **
  183. **
  184. ** Arguments:
  185. **
  186. ** Returns:
  187. **
  188. ** Side Effects: none
  189. */
  190. PRIVATE_CODE BOOL StringToGUID(LPCTSTR pcszGUID, PGUID pguid)
  191. {
  192. BOOL bResult = FALSE;
  193. DWORD dwValue;
  194. LPCTSTR pcszNext = pcszGUID;
  195. ASSERT(IS_VALID_STRING_PTR(pcszGUID, CSTR));
  196. ASSERT(IS_VALID_WRITE_PTR(pguid, GUID));
  197. if (*pcszNext++ == TEXT('{') &&
  198. HexStringToDWORD(&pcszNext, &(pguid->Data1), sizeof(DWORD) * 2, TEXT('-')) &&
  199. HexStringToDWORD(&pcszNext, &dwValue, sizeof(WORD) * 2, TEXT('-')))
  200. {
  201. pguid->Data2 = (WORD)dwValue;
  202. if (HexStringToDWORD(&pcszNext, &dwValue, sizeof(WORD) * 2, TEXT('-')))
  203. {
  204. UINT u;
  205. static const TCHAR SrgcchDelimiters[] = { 0, TEXT('-'), 0, 0, 0, 0, 0, TEXT('}') };
  206. pguid->Data3 = (WORD)dwValue;
  207. bResult = TRUE;
  208. for (u = 0; u < ARRAY_ELEMENTS(pguid->Data4); u++)
  209. {
  210. if (HexStringToDWORD(&pcszNext, &dwValue, sizeof(BYTE) * 2,
  211. SrgcchDelimiters[u]))
  212. pguid->Data4[u] = (BYTE)dwValue;
  213. else
  214. {
  215. bResult = FALSE;
  216. break;
  217. }
  218. }
  219. if (bResult)
  220. {
  221. ASSERT(u == ARRAY_ELEMENTS(pguid->Data4));
  222. if (*pcszNext)
  223. {
  224. bResult = FALSE;
  225. WARNING_OUT((TEXT("StringToGUID(): Found %c instead of }."),
  226. *pcszNext));
  227. }
  228. }
  229. else
  230. WARNING_OUT((TEXT("StringToGUID(): Bad GUID string %s."),
  231. pcszGUID));
  232. }
  233. }
  234. ASSERT(! bResult ||
  235. IS_VALID_STRUCT_PTR(pguid, CGUID));
  236. return(bResult);
  237. }
  238. /*
  239. ** GetClassID()
  240. **
  241. **
  242. **
  243. ** Arguments:
  244. **
  245. ** Returns:
  246. **
  247. ** Side Effects: none
  248. */
  249. PRIVATE_CODE HRESULT GetClassID(LPCTSTR pcszPath, LPCTSTR pcszSubKey, PCLSID pclsid)
  250. {
  251. HRESULT hr;
  252. CLSID clsidFile;
  253. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  254. ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR));
  255. ASSERT(IS_VALID_WRITE_PTR(pclsid, CLSID));
  256. /* Verify string length constants. */
  257. /* (+ 1) for each null terminator. */
  258. ASSERT(lstrlen(CLSID_SUBKEY) + 1 == CLSID_SUBKEY_LEN);
  259. ASSERT(lstrlen(IN_PROC_SERVER_SUBKEY) + 1 == IN_PROC_SERVER_SUBKEY_LEN);
  260. ASSERT(lstrlen(LOCAL_SERVER_SUBKEY) + 1 == LOCAL_SERVER_SUBKEY_LEN);
  261. ASSERT(lstrlen(RECONCILER_SUBKEY) + 1 == RECONCILER_SUBKEY_LEN);
  262. ASSERT(lstrlen(NOTIFY_SUBKEY) + 1 == NOTIFY_SUBKEY_LEN);
  263. ASSERT(lstrlen(COPY_SUBKEY) + 1 == COPY_SUBKEY_LEN);
  264. ASSERT(lstrlen( TEXT("{12345678-1234-1234-1234-123456789012}")) + 1 == GUID_SUBKEY_LEN);
  265. ASSERT(lstrlen(TEXT("CLSID\\{12345678-1234-1234-1234-123456789012}")) + 1 == CLSID_REG_KEY_LEN);
  266. ASSERT(lstrlen(TEXT("CLSID\\{12345678-1234-1234-1234-123456789012}\\InProcServer32")) + 1 == IN_PROC_SERVER_REG_KEY_LEN);
  267. ASSERT(lstrlen(TEXT("CLSID\\{12345678-1234-1234-1234-123456789012}\\LocalServer32")) + 1 == LOCAL_SERVER_REG_KEY_LEN);
  268. ASSERT(lstrlen(TEXT("CLSID\\{12345678-1234-1234-1234-123456789012}\\Roles\\Reconciler")) + 1 == RECONCILER_REG_KEY_LEN);
  269. ASSERT(lstrlen(TEXT("CLSID\\{12345678-1234-1234-1234-123456789012}\\Roles\\NotifyReplica")) + 1 == NOTIFY_REG_KEY_LEN);
  270. ASSERT(lstrlen(TEXT("CLSID\\{12345678-1234-1234-1234-123456789012}\\SingleChangeHook")) + 1 == COPY_REG_KEY_LEN);
  271. hr = GetClassFileByExtension(pcszPath, &clsidFile);
  272. if (SUCCEEDED(hr))
  273. {
  274. TCHAR rgchRecRegKey[MAX_REG_KEY_LEN];
  275. TCHAR rgchRecGUID[GUID_SUBKEY_LEN];
  276. DWORD dwcbLen = sizeof(rgchRecGUID);
  277. hr = REGDB_E_CLASSNOTREG;
  278. MakeClsIDSubKey(&clsidFile, pcszSubKey, rgchRecRegKey, ARRAYSIZE(rgchRecRegKey));
  279. if (GetDefaultRegKeyValue(HKEY_CLASSES_ROOT, rgchRecRegKey, rgchRecGUID,
  280. &dwcbLen) == ERROR_SUCCESS)
  281. {
  282. /* (+ 1) for null terminator. */
  283. ASSERT((DWORD)(lstrlen(rgchRecGUID) + 1) * sizeof(TCHAR) == dwcbLen);
  284. ASSERT(dwcbLen * sizeof(TCHAR) <= sizeof(rgchRecGUID));
  285. if (StringToGUID(rgchRecGUID, pclsid))
  286. {
  287. hr = S_OK;
  288. #ifdef DEBUG
  289. {
  290. TCHAR rgchInProcServerKey[IN_PROC_SERVER_REG_KEY_LEN];
  291. TCHAR rgchInProcServerValue[MAX_REG_VALUE_LEN];
  292. DWORD dwcbInProcLen = sizeof(rgchInProcServerValue);
  293. /* Display the path to the registered reconciler. */
  294. wnsprintf(rgchInProcServerKey, ARRAYSIZE(rgchInProcServerKey), TEXT("%s\\%s\\%s"), CLSID_SUBKEY,
  295. rgchRecGUID, IN_PROC_SERVER_SUBKEY);
  296. if (GetDefaultRegKeyValue(HKEY_CLASSES_ROOT,
  297. rgchInProcServerKey,
  298. rgchInProcServerValue, &dwcbInProcLen)
  299. == ERROR_SUCCESS)
  300. TRACE_OUT((TEXT("GetClassID(): Found registered %s reconciler %s for file %s."),
  301. IN_PROC_SERVER_SUBKEY,
  302. rgchInProcServerValue,
  303. pcszPath));
  304. else
  305. {
  306. dwcbInProcLen = sizeof(rgchInProcServerValue);
  307. wnsprintf(rgchInProcServerKey, ARRAYSIZE(rgchInProcServerKey), TEXT("%s\\%s\\%s"), CLSID_SUBKEY,
  308. rgchRecGUID, LOCAL_SERVER_SUBKEY);
  309. if (GetDefaultRegKeyValue(HKEY_CLASSES_ROOT,
  310. rgchInProcServerKey,
  311. rgchInProcServerValue,
  312. &dwcbInProcLen)
  313. == ERROR_SUCCESS)
  314. TRACE_OUT((TEXT("GetClassID(): Found registered %s reconciler %s for file %s."),
  315. LOCAL_SERVER_SUBKEY,
  316. rgchInProcServerValue,
  317. pcszPath));
  318. else
  319. WARNING_OUT((TEXT("GetClassID(): Unregistered class ID %s listed as reconciler in %s for file %s."),
  320. rgchRecGUID,
  321. rgchRecRegKey,
  322. pcszPath));
  323. }
  324. }
  325. #endif
  326. }
  327. else
  328. WARNING_OUT((TEXT("GetClassID(): Bad reconciler class ID %s specified for key %s."),
  329. rgchRecGUID,
  330. rgchRecRegKey));
  331. }
  332. else
  333. TRACE_OUT((TEXT("GetClassID(): No reconciler registered for file %s."),
  334. pcszPath));
  335. }
  336. else
  337. TRACE_OUT((TEXT("GetClassID(): No class ID registered for file %s."),
  338. pcszPath));
  339. ASSERT(FAILED(hr) ||
  340. IS_VALID_STRUCT_PTR(pclsid, CCLSID));
  341. return(hr);
  342. }
  343. /****************************** Public Functions *****************************/
  344. /*
  345. ** GetClassFileByExtension()
  346. **
  347. **
  348. **
  349. ** Arguments:
  350. **
  351. ** Returns:
  352. **
  353. ** Side Effects: none
  354. */
  355. PUBLIC_CODE HRESULT GetClassFileByExtension(LPCTSTR pcszFile, PCLSID pclsid)
  356. {
  357. HRESULT hr = MK_E_INVALIDEXTENSION;
  358. LPCTSTR pcszExtension;
  359. ASSERT(IS_VALID_STRING_PTR(pcszFile, CSTR));
  360. ASSERT(IS_VALID_WRITE_PTR(pclsid, CLSID));
  361. pcszExtension = ExtractExtension(pcszFile);
  362. if (*pcszExtension)
  363. {
  364. TCHAR rgchFileType[MAX_REG_VALUE_LEN];
  365. DWORD dwcbBufLen = sizeof(rgchFileType);
  366. ASSERT(*pcszExtension == PERIOD);
  367. if (GetDefaultRegKeyValue(HKEY_CLASSES_ROOT, pcszExtension, rgchFileType,
  368. &dwcbBufLen) == ERROR_SUCCESS)
  369. {
  370. /* dwcbBufLen includes rgchFileType's null terminator. */
  371. if (dwcbBufLen + sizeof(CLSID_SUBKEY) <= sizeof(rgchFileType))
  372. {
  373. TCHAR rgchFileClsID[GUID_SUBKEY_LEN];
  374. DWORD dwcbFileClsIDBufLen = sizeof(rgchFileClsID);
  375. CatPath(rgchFileType, CLSID_SUBKEY, ARRAYSIZE(rgchFileType));
  376. if (GetDefaultRegKeyValue(HKEY_CLASSES_ROOT, rgchFileType,
  377. rgchFileClsID, &dwcbFileClsIDBufLen)
  378. == ERROR_SUCCESS)
  379. {
  380. if (StringToGUID(rgchFileClsID, pclsid))
  381. {
  382. hr = S_OK;
  383. TRACE_OUT((TEXT("GetClassFileByExtension(): Retrieved class ID %s for file %s."),
  384. rgchFileClsID,
  385. pcszFile));
  386. }
  387. else
  388. WARNING_OUT((TEXT("GetClassFileByExtension(): Invalid class ID \"%s\" in %s\\%s. No class ID will be used."),
  389. rgchFileClsID,
  390. rgchFileType,
  391. CLSID_SUBKEY));
  392. }
  393. else
  394. TRACE_OUT((TEXT("GetClassFileByExtension(): No %s subkey for file type key \"%s\". No class ID will be used."),
  395. CLSID_SUBKEY,
  396. rgchFileType));
  397. }
  398. else
  399. WARNING_OUT((TEXT("GetClassFileByExtension(): File type \"%s\" for extension %s of file %s is too long. No class ID will be used."),
  400. rgchFileType,
  401. pcszExtension,
  402. pcszFile));
  403. }
  404. else
  405. TRACE_OUT((TEXT("GetClassFileByExtension(): No file type for extension %s of file %s. No class ID will be used."),
  406. pcszExtension,
  407. pcszFile));
  408. }
  409. else
  410. TRACE_OUT((TEXT("GetClassFileByExtension(): File %s has no extension. No class ID will be used."),
  411. pcszFile));
  412. ASSERT(FAILED(hr) ||
  413. IS_VALID_STRUCT_PTR(pclsid, CCLSID));
  414. return(hr);
  415. }
  416. /*
  417. ** GetReconcilerClassID()
  418. **
  419. **
  420. **
  421. ** Arguments:
  422. **
  423. ** Returns:
  424. **
  425. ** Side Effects: none
  426. */
  427. PUBLIC_CODE HRESULT GetReconcilerClassID(LPCTSTR pcszPath, PCLSID pclsid)
  428. {
  429. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  430. ASSERT(IS_VALID_WRITE_PTR(pclsid, CLSID));
  431. return(GetClassID(pcszPath, RECONCILER_SUBKEY, pclsid));
  432. }
  433. /*
  434. ** GetCopyHandlerClassID()
  435. **
  436. **
  437. **
  438. ** Arguments:
  439. **
  440. ** Returns:
  441. **
  442. ** Side Effects: none
  443. */
  444. PUBLIC_CODE HRESULT GetCopyHandlerClassID(LPCTSTR pcszPath, PCLSID pclsid)
  445. {
  446. HRESULT hr;
  447. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  448. ASSERT(IS_VALID_WRITE_PTR(pclsid, CLSID));
  449. hr = GetReconcilerClassID(pcszPath, pclsid);
  450. if (SUCCEEDED(hr))
  451. {
  452. TCHAR rgchCopyRegKey[COPY_REG_KEY_LEN];
  453. MakeClsIDSubKey(pclsid, COPY_SUBKEY, rgchCopyRegKey, ARRAYSIZE(rgchCopyRegKey));
  454. if (RegKeyExists(HKEY_CLASSES_ROOT, rgchCopyRegKey))
  455. hr = S_OK;
  456. else
  457. hr = REGDB_E_CLASSNOTREG;
  458. }
  459. return(hr);
  460. }
  461. /*
  462. ** GetReplicaNotificationClassID()
  463. **
  464. **
  465. **
  466. ** Arguments:
  467. **
  468. ** Returns:
  469. **
  470. ** Side Effects: none
  471. */
  472. PUBLIC_CODE HRESULT GetReplicaNotificationClassID(LPCTSTR pcszPath, PCLSID pclsid)
  473. {
  474. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  475. ASSERT(IS_VALID_WRITE_PTR(pclsid, CLSID));
  476. return(GetClassID(pcszPath, NOTIFY_SUBKEY, pclsid));
  477. }
  478. /*
  479. ** CompareGUIDs()
  480. **
  481. **
  482. **
  483. ** Arguments:
  484. **
  485. ** Returns:
  486. **
  487. ** Side Effects: none
  488. */
  489. PUBLIC_CODE COMPARISONRESULT CompareGUIDs(PCGUID pcguid1, PCGUID pcguid2)
  490. {
  491. ASSERT(IS_VALID_STRUCT_PTR(pcguid1, CGUID));
  492. ASSERT(IS_VALID_STRUCT_PTR(pcguid2, CGUID));
  493. return(MyMemComp(pcguid1, pcguid2, sizeof(*pcguid1)));
  494. }
  495. /*
  496. ** TranslateHRESULTToTWINRESULT()
  497. **
  498. **
  499. **
  500. ** Arguments:
  501. **
  502. ** Returns:
  503. **
  504. ** Side Effects: none
  505. */
  506. PUBLIC_CODE TWINRESULT TranslateHRESULTToTWINRESULT(HRESULT hr)
  507. {
  508. TWINRESULT tr;
  509. switch (hr)
  510. {
  511. HRESULTToTWINRESULT(S_OK, TR_SUCCESS);
  512. HRESULTToTWINRESULT(REC_S_NOTCOMPLETE, TR_MERGE_INCOMPLETE);
  513. HRESULTToTWINRESULT(REC_S_NOTCOMPLETEBUTPROPAGATE, TR_MERGE_INCOMPLETE);
  514. HRESULTToTWINRESULT(E_ABORT, TR_ABORT);
  515. HRESULTToTWINRESULT(E_OUTOFMEMORY, TR_OUT_OF_MEMORY);
  516. HRESULTToTWINRESULT(E_FAIL, TR_RH_LOAD_FAILED);
  517. HRESULTToTWINRESULT(REC_E_ABORTED, TR_ABORT);
  518. HRESULTToTWINRESULT(REC_E_TOODIFFERENT, TR_TOO_DIFFERENT);
  519. default:
  520. if (SUCCEEDED(hr))
  521. {
  522. tr = TR_SUCCESS;
  523. WARNING_OUT((TEXT("TranslateHRESULTToTWINRESULT(): Translating unlisted success HRESULT %s into TWINRESULT %s."),
  524. GetHRESULTString(hr),
  525. GetTWINRESULTString(tr)));
  526. }
  527. else
  528. {
  529. tr = TR_RH_LOAD_FAILED;
  530. WARNING_OUT((TEXT("TranslateHRESULTToTWINRESULT(): Translating unlisted failure HRESULT %s into TWINRESULT %s."),
  531. GetHRESULTString(hr),
  532. GetTWINRESULTString(tr)));
  533. }
  534. break;
  535. }
  536. return(tr);
  537. }
  538. #if defined(DEBUG) || defined(VSTF)
  539. /*
  540. ** IsValidPCINotifyReplica()
  541. **
  542. **
  543. **
  544. ** Arguments:
  545. **
  546. ** Returns:
  547. **
  548. ** Side Effects: none
  549. */
  550. PUBLIC_CODE BOOL IsValidPCINotifyReplica(PCINotifyReplica pcinr)
  551. {
  552. return(IS_VALID_READ_PTR(pcinr, CINotifyReplica) &&
  553. IS_VALID_READ_PTR(pcinr->lpVtbl, sizeof(*(pcinr->lpVtbl))) &&
  554. IS_VALID_STRUCT_PTR((PCIUnknown)pcinr, CIUnknown) &&
  555. IS_VALID_CODE_PTR(pcinr->lpVtbl->YouAreAReplica, YouAreAReplica));
  556. }
  557. /*
  558. ** IsValidPCIReconcileInitiator()
  559. **
  560. **
  561. **
  562. ** Arguments:
  563. **
  564. ** Returns:
  565. **
  566. ** Side Effects: none
  567. */
  568. PUBLIC_CODE BOOL IsValidPCIReconcileInitiator(PCIReconcileInitiator pciri)
  569. {
  570. return(IS_VALID_READ_PTR(pciri, CIReconcileInitiator) &&
  571. IS_VALID_READ_PTR(pciri->lpVtbl, sizeof(*(pciri->lpVtbl))) &&
  572. IS_VALID_STRUCT_PTR((PCIUnknown)pciri, CIUnknown) &&
  573. IS_VALID_CODE_PTR(pciri->lpVtbl->SetAbortCallback, SetAbortCallback) &&
  574. IS_VALID_CODE_PTR(pciri->lpVtbl->SetProgressFeedback, SetProgressFeedback));
  575. }
  576. #endif