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.

1258 lines
33 KiB

  1. /*
  2. * findbc.c - Briefcase enumeration module.
  3. */
  4. /*
  5. */
  6. /* Headers
  7. **********/
  8. #include "project.h"
  9. #pragma hdrstop
  10. #include "findbc.h"
  11. /* Macros
  12. *********/
  13. /* macro for translating an LRESULT to a TWINRESULT */
  14. #define LRESULTToTWINRESULT(lr, TR) case lr: tr = TR; break
  15. /* Constants
  16. ************/
  17. /* briefcase registry keys */
  18. #define HKEY_BRIEFCASE_ROOT HKEY_CURRENT_USER
  19. #ifdef DEBUG
  20. #define HKEY_BRIEFCASE_ROOT_STRING TEXT("HKEY_CURRENT_USER")
  21. #endif
  22. #define BRIEFCASE_SUBKEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Briefcase\\Briefcases")
  23. /* maximum briefcase value name length, including null terminator */
  24. #define MAX_VALUE_NAME_LEN (8 + 1)
  25. /* Types
  26. ********/
  27. /* EnumBriefcases() callback function */
  28. typedef LONG (*ENUMBRIEFCASESPROC)(PCLINKINFO, PCVOID, PBOOL);
  29. /* briefcase iterator */
  30. typedef struct _brfcaseiter
  31. {
  32. HPTRARRAY hpa;
  33. ARRAYINDEX aiNext;
  34. }
  35. BRFCASEITER;
  36. DECLARE_STANDARD_TYPES(BRFCASEITER);
  37. /***************************** Private Functions *****************************/
  38. /* Module Prototypes
  39. ********************/
  40. PRIVATE_CODE COMPARISONRESULT LinkInfoSortCmp(PCVOID, PCVOID);
  41. PRIVATE_CODE COMPARISONRESULT LinkInfoSearchCmp(PCVOID, PCVOID);
  42. PRIVATE_CODE TWINRESULT TranslateLRESULTToTWINRESULT(LONG);
  43. PRIVATE_CODE LONG AllocateValueDataBuffer(HKEY, PVOID *, PDWORD);
  44. PRIVATE_CODE LONG EnumBriefcases(HKEY, ENUMBRIEFCASESPROC, PCVOID, LPTSTR, PBOOL);
  45. PRIVATE_CODE LONG GetUnusedBriefcaseValueName(HKEY, LPTSTR, int);
  46. PRIVATE_CODE TWINRESULT CreateBriefcaseIterator(PBRFCASEITER *);
  47. PRIVATE_CODE TWINRESULT GetNextBriefcaseIterator(PBRFCASEITER, PBRFCASEINFO);
  48. PRIVATE_CODE void DestroyBriefcaseIterator(PBRFCASEITER);
  49. PRIVATE_CODE LONG AddBriefcaseToIteratorProc(PCLINKINFO, PCVOID, PBOOL);
  50. PRIVATE_CODE LONG CompareLinkInfoProc(PCLINKINFO, PCVOID, PBOOL);
  51. PRIVATE_CODE TWINRESULT MyAddBriefcaseToSystem(PCLINKINFO);
  52. PRIVATE_CODE TWINRESULT MyRemoveBriefcaseFromSystem(PCLINKINFO);
  53. PRIVATE_CODE TWINRESULT UpdateBriefcaseLinkInfo(PCLINKINFO, PCLINKINFO);
  54. #if defined(DEBUG) || defined(VSTF)
  55. PRIVATE_CODE BOOL IsValidPCBRFCASEITER(PCBRFCASEITER);
  56. #endif
  57. #ifdef EXPV
  58. PRIVATE_CODE BOOL IsValidHBRFCASEITER(HBRFCASEITER);
  59. #endif
  60. /*
  61. ** LinkInfoSortCmp()
  62. **
  63. **
  64. **
  65. ** Arguments:
  66. **
  67. ** Returns:
  68. **
  69. ** Side Effects: none
  70. **
  71. ** LinkInfo structures are sorted by:
  72. ** 1) LinkInfo referent
  73. ** 2) pointer
  74. */
  75. PRIVATE_CODE COMPARISONRESULT LinkInfoSortCmp(PCVOID pcli1, PCVOID pcli2)
  76. {
  77. COMPARISONRESULT cr;
  78. ASSERT(IS_VALID_STRUCT_PTR(pcli1, CLINKINFO));
  79. ASSERT(IS_VALID_STRUCT_PTR(pcli2, CLINKINFO));
  80. cr = CompareLinkInfoReferents((PCLINKINFO)pcli1, (PCLINKINFO)pcli2);
  81. if (cr == CR_EQUAL)
  82. cr = ComparePointers(pcli1, pcli2);
  83. return(cr);
  84. }
  85. /*
  86. ** LinkInfoSearchCmp()
  87. **
  88. **
  89. **
  90. ** Arguments:
  91. **
  92. ** Returns:
  93. **
  94. ** Side Effects: none
  95. **
  96. ** LinkInfo structures are searched by:
  97. ** 1) LinkInfo referent
  98. */
  99. PRIVATE_CODE COMPARISONRESULT LinkInfoSearchCmp(PCVOID pcliTarget,
  100. PCVOID pcliCurrent)
  101. {
  102. ASSERT(IS_VALID_STRUCT_PTR(pcliTarget, CLINKINFO));
  103. ASSERT(IS_VALID_STRUCT_PTR(pcliCurrent, CLINKINFO));
  104. return(CompareLinkInfoReferents(pcliTarget, pcliCurrent));
  105. }
  106. /*
  107. ** TranslateLRESULTToTWINRESULT()
  108. **
  109. **
  110. **
  111. ** Arguments:
  112. **
  113. ** Returns:
  114. **
  115. ** Side Effects: none
  116. */
  117. PRIVATE_CODE TWINRESULT TranslateLRESULTToTWINRESULT(LONG lResult)
  118. {
  119. TWINRESULT tr;
  120. switch (lResult)
  121. {
  122. LRESULTToTWINRESULT(ERROR_SUCCESS, TR_SUCCESS);
  123. default:
  124. tr = TR_OUT_OF_MEMORY;
  125. if (lResult != ERROR_OUTOFMEMORY)
  126. WARNING_OUT((TEXT("TranslateLRESULTToTWINRESULT(): Translating unlisted LRESULT %ld to TWINRESULT %s."),
  127. lResult,
  128. GetTWINRESULTString(tr)));
  129. break;
  130. }
  131. return(tr);
  132. }
  133. /*
  134. ** AllocateValueDataBuffer()
  135. **
  136. **
  137. **
  138. ** Arguments:
  139. **
  140. ** Returns:
  141. **
  142. ** Side Effects: none
  143. */
  144. LONG PRIVATE_CODE AllocateValueDataBuffer(HKEY hkey, PVOID *ppvData,
  145. PDWORD pdwcbLen)
  146. {
  147. LONG lResult;
  148. ASSERT(IS_VALID_HANDLE(hkey, KEY));
  149. ASSERT(IS_VALID_WRITE_PTR(ppvData, PVOID));
  150. ASSERT(IS_VALID_WRITE_PTR(pdwcbLen, DWORD));
  151. lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  152. NULL, pdwcbLen, NULL, NULL);
  153. if (lResult == ERROR_SUCCESS)
  154. {
  155. if (! AllocateMemory(*pdwcbLen, ppvData))
  156. lResult = ERROR_OUTOFMEMORY;
  157. }
  158. ASSERT(lResult != ERROR_SUCCESS ||
  159. IS_VALID_WRITE_BUFFER_PTR(*ppvData, VOID, *pdwcbLen));
  160. return(lResult);
  161. }
  162. /*
  163. ** EnumBriefcases()
  164. **
  165. **
  166. **
  167. ** Arguments:
  168. **
  169. ** Returns:
  170. **
  171. ** Side Effects: none
  172. */
  173. PRIVATE_CODE LONG EnumBriefcases(HKEY hkeyBriefcases, ENUMBRIEFCASESPROC ebcp,
  174. PCVOID pcvRefData, LPTSTR pszValueNameBuf,
  175. PBOOL pbAbort)
  176. {
  177. LONG lResult;
  178. DWORD dwcbMaxValueDataLen;
  179. PLINKINFO pli;
  180. /* pcvRefData may be any value. */
  181. ASSERT(IS_VALID_HANDLE(hkeyBriefcases, KEY));
  182. ASSERT(IS_VALID_CODE_PTR(ebcp, ENUMBRIEFCASESPROC));
  183. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszValueNameBuf, STR, MAX_VALUE_NAME_LEN));
  184. ASSERT(IS_VALID_WRITE_PTR(pbAbort, BOOL));
  185. /* Allocate a buffer to hold the largest value's data. */
  186. lResult = AllocateValueDataBuffer(hkeyBriefcases, &pli,
  187. &dwcbMaxValueDataLen);
  188. if (lResult == ERROR_SUCCESS)
  189. {
  190. DWORD dwiValue;
  191. /* Look through the briefcases looking for matching LinkInfo. */
  192. *pbAbort = FALSE;
  193. dwiValue = 0;
  194. do
  195. {
  196. DWORD dwcbValueNameLen;
  197. DWORD dwType;
  198. DWORD dwcbDataLen;
  199. dwcbValueNameLen = MAX_VALUE_NAME_LEN;
  200. dwcbDataLen = dwcbMaxValueDataLen;
  201. lResult = RegEnumValue(hkeyBriefcases, dwiValue, pszValueNameBuf,
  202. &dwcbValueNameLen, NULL, &dwType, (PBYTE)pli,
  203. &dwcbDataLen);
  204. switch (lResult)
  205. {
  206. case ERROR_SUCCESS:
  207. if (dwcbDataLen >= sizeof(pli->ucbSize) &&
  208. pli->ucbSize == dwcbDataLen)
  209. lResult = (*ebcp)(pli, pcvRefData, pbAbort);
  210. else
  211. WARNING_OUT((TEXT("EnumBriefcases(): Value %s under %s\\%s is not a valid LinkInfo structure."),
  212. pszValueNameBuf,
  213. HKEY_BRIEFCASE_ROOT_STRING,
  214. BRIEFCASE_SUBKEY));
  215. break;
  216. case ERROR_MORE_DATA:
  217. /*
  218. * Watch out for value names that are too long, and added
  219. * data values that are too long.
  220. */
  221. /* (+ 1) for null terminator. */
  222. if (dwcbValueNameLen >= MAX_VALUE_NAME_LEN)
  223. WARNING_OUT((TEXT("EnumBriefcases(): Value %s under %s\\%s is too long. %u bytes > %u bytes."),
  224. pszValueNameBuf,
  225. HKEY_BRIEFCASE_ROOT_STRING,
  226. BRIEFCASE_SUBKEY,
  227. dwcbValueNameLen + 1,
  228. MAX_VALUE_NAME_LEN));
  229. if (dwcbDataLen > dwcbMaxValueDataLen)
  230. WARNING_OUT((TEXT("EnumBriefcases(): Value %s's data under %s\\%s is too long. %u bytes > %u bytes."),
  231. pszValueNameBuf,
  232. HKEY_BRIEFCASE_ROOT_STRING,
  233. BRIEFCASE_SUBKEY,
  234. dwcbDataLen,
  235. dwcbMaxValueDataLen));
  236. /* Skip this value. */
  237. lResult = ERROR_SUCCESS;
  238. break;
  239. default:
  240. break;
  241. }
  242. } while (lResult == ERROR_SUCCESS &&
  243. ! *pbAbort &&
  244. dwiValue++ < DWORD_MAX);
  245. if (lResult == ERROR_NO_MORE_ITEMS)
  246. lResult = ERROR_SUCCESS;
  247. FreeMemory(pli);
  248. }
  249. return(lResult);
  250. }
  251. /*
  252. ** GetUnusedBriefcaseValueName()
  253. **
  254. **
  255. **
  256. ** Arguments:
  257. **
  258. ** Returns:
  259. **
  260. ** Side Effects: none
  261. */
  262. PRIVATE_CODE LONG GetUnusedBriefcaseValueName(HKEY hkeyBriefcases,
  263. LPTSTR pszValueNameBuf,
  264. int cchMax)
  265. {
  266. LONG lResult;
  267. DWORD dwValueNumber;
  268. BOOL bFound;
  269. ASSERT(IS_VALID_HANDLE(hkeyBriefcases, KEY));
  270. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszValueNameBuf, STR, MAX_VALUE_NAME_LEN));
  271. dwValueNumber = 0;
  272. bFound = FALSE;
  273. do
  274. {
  275. wnsprintf(pszValueNameBuf, cchMax, TEXT("%lu"), dwValueNumber);
  276. ASSERT((DWORD)lstrlen(pszValueNameBuf) < MAX_VALUE_NAME_LEN);
  277. lResult = RegQueryValueEx(hkeyBriefcases, pszValueNameBuf, NULL, NULL,
  278. NULL, NULL);
  279. switch (lResult)
  280. {
  281. case ERROR_SUCCESS:
  282. /* Used value name. Continue searching. */
  283. TRACE_OUT((TEXT("GetUnusedBriefcaseValueName(): Found used briefcase value name %s."),
  284. pszValueNameBuf));
  285. break;
  286. case ERROR_FILE_NOT_FOUND:
  287. /* Unused value name. Stop searching. */
  288. lResult = ERROR_SUCCESS;
  289. bFound = TRUE;
  290. TRACE_OUT((TEXT("GetUnusedBriefcaseValueName(): Found unused briefcase value name %s."),
  291. pszValueNameBuf));
  292. break;
  293. default:
  294. WARNING_OUT((TEXT("GetUnusedBriefcaseValueName(): RegQueryValueEx() failed, returning %ld."),
  295. lResult));
  296. break;
  297. }
  298. } while (lResult == ERROR_SUCCESS &&
  299. ! bFound &&
  300. dwValueNumber++ < DWORD_MAX);
  301. if (dwValueNumber == DWORD_MAX)
  302. {
  303. ASSERT(lResult == ERROR_SUCCESS &&
  304. ! bFound);
  305. WARNING_OUT((TEXT("GetUnusedBriefcaseValueName(): All value names in use.")));
  306. lResult = ERROR_CANTWRITE;
  307. }
  308. return(lResult);
  309. }
  310. /*
  311. ** CreateBriefcaseIterator()
  312. **
  313. **
  314. **
  315. ** Arguments:
  316. **
  317. ** Returns:
  318. **
  319. ** Side Effects: none
  320. */
  321. PRIVATE_CODE TWINRESULT CreateBriefcaseIterator(PBRFCASEITER *ppbciter)
  322. {
  323. TWINRESULT tr;
  324. LONG lResult;
  325. HKEY hkeyBriefcases;
  326. ASSERT(IS_VALID_WRITE_PTR(ppbciter, PBRFCASEITER));
  327. lResult = RegOpenKeyEx(HKEY_BRIEFCASE_ROOT, BRIEFCASE_SUBKEY, 0,
  328. (KEY_QUERY_VALUE | KEY_SET_VALUE), &hkeyBriefcases);
  329. if (lResult == ERROR_SUCCESS)
  330. {
  331. DWORD dwcBriefcases;
  332. lResult = RegQueryInfoKey(hkeyBriefcases, NULL, NULL, NULL, NULL, NULL,
  333. NULL, NULL, &dwcBriefcases, NULL, NULL, NULL);
  334. if (lResult == ERROR_SUCCESS)
  335. {
  336. if (dwcBriefcases > 0)
  337. {
  338. tr = TR_OUT_OF_MEMORY;
  339. if (AllocateMemory(sizeof(**ppbciter), ppbciter))
  340. {
  341. NEWPTRARRAY npa;
  342. npa.aicInitialPtrs = dwcBriefcases;
  343. npa.aicAllocGranularity = 1;
  344. npa.dwFlags = NPA_FL_SORTED_ADD;
  345. if (CreatePtrArray(&npa, &((*ppbciter)->hpa)))
  346. {
  347. TCHAR rgchValueName[MAX_VALUE_NAME_LEN];
  348. BOOL bAbort;
  349. (*ppbciter)->aiNext = 0;
  350. tr = TranslateLRESULTToTWINRESULT(
  351. EnumBriefcases(hkeyBriefcases,
  352. &AddBriefcaseToIteratorProc,
  353. *ppbciter, rgchValueName, &bAbort));
  354. if (tr == TR_SUCCESS)
  355. {
  356. ASSERT(! bAbort);
  357. }
  358. else
  359. {
  360. DestroyPtrArray((*ppbciter)->hpa);
  361. CREATEBRIEFCASEITERATOR_BAIL:
  362. FreeMemory(*ppbciter);
  363. }
  364. }
  365. else
  366. {
  367. goto CREATEBRIEFCASEITERATOR_BAIL;
  368. }
  369. }
  370. }
  371. else
  372. {
  373. tr = TR_NO_MORE;
  374. }
  375. }
  376. else
  377. {
  378. tr = TranslateLRESULTToTWINRESULT(lResult);
  379. }
  380. RegCloseKey(hkeyBriefcases);
  381. }
  382. else
  383. {
  384. /* ERROR_FILE_NOT_FOUND is returned for a non-existent key. */
  385. if (lResult == ERROR_FILE_NOT_FOUND)
  386. {
  387. tr = TR_NO_MORE;
  388. }
  389. else
  390. {
  391. /* RAIDRAID: (16279) We should map to other TWINRESULTs here. */
  392. tr = TR_OUT_OF_MEMORY;
  393. }
  394. }
  395. ASSERT(tr != TR_SUCCESS ||
  396. IS_VALID_STRUCT_PTR(*ppbciter, CBRFCASEITER));
  397. return(tr);
  398. }
  399. /*
  400. ** GetNextBriefcaseIterator()
  401. **
  402. **
  403. **
  404. ** Arguments:
  405. **
  406. ** Returns:
  407. **
  408. ** Side Effects: none
  409. */
  410. PRIVATE_CODE TWINRESULT GetNextBriefcaseIterator(PBRFCASEITER pbciter,
  411. PBRFCASEINFO pbcinfo)
  412. {
  413. TWINRESULT tr = TR_NO_MORE;
  414. ARRAYINDEX aicBriefcases;
  415. ASSERT(IS_VALID_STRUCT_PTR(pbciter, CBRFCASEITER));
  416. ASSERT(IS_VALID_WRITE_PTR(pbcinfo, BRFCASEINFO));
  417. ASSERT(pbcinfo->ulSize == sizeof(*pbcinfo));
  418. aicBriefcases = GetPtrCount(pbciter->hpa);
  419. while (pbciter->aiNext < aicBriefcases)
  420. {
  421. PCLINKINFO pcli;
  422. DWORD dwOutFlags;
  423. PLINKINFO pliUpdated;
  424. BOOL bRemoveBriefcase = FALSE;
  425. pcli = GetPtr(pbciter->hpa, pbciter->aiNext);
  426. if (ResolveLinkInfo(pcli, pbcinfo->rgchDatabasePath,
  427. (RLI_IFL_UPDATE | RLI_IFL_LOCAL_SEARCH), NULL, &dwOutFlags,
  428. &pliUpdated))
  429. {
  430. if (PathExists(pbcinfo->rgchDatabasePath))
  431. {
  432. /* Found an existing briefcase database. */
  433. if (IS_FLAG_SET(dwOutFlags, RLI_OFL_UPDATED))
  434. {
  435. if (UpdateBriefcaseLinkInfo(pcli, pliUpdated))
  436. TRACE_OUT((TEXT("GetNextBriefcaseIterator(): Updated LinkInfo for briefcase database %s."),
  437. pbcinfo->rgchDatabasePath));
  438. else
  439. WARNING_OUT((TEXT("GetNextBriefcaseIterator(): Failed to update LinkInfo for briefcase database %s."),
  440. pbcinfo->rgchDatabasePath));
  441. }
  442. tr = TR_SUCCESS;
  443. }
  444. else
  445. bRemoveBriefcase = TRUE;
  446. if (IS_FLAG_SET(dwOutFlags, RLI_OFL_UPDATED))
  447. DestroyLinkInfo(pliUpdated);
  448. }
  449. else
  450. {
  451. /*
  452. * GetLastError() here to differentiate an out of memory condition and
  453. * all other errors. Remove the briefcase from the system for all
  454. * errors except out of memory, e.g., unavailable volume or invalid
  455. * parameter.
  456. */
  457. if (GetLastError() != ERROR_OUTOFMEMORY)
  458. bRemoveBriefcase = TRUE;
  459. }
  460. if (bRemoveBriefcase)
  461. {
  462. if (MyRemoveBriefcaseFromSystem(pcli) == TR_SUCCESS)
  463. TRACE_OUT((TEXT("GetNextBriefcaseIterator(): Unavailable/missing briefcase removed from system.")));
  464. else
  465. WARNING_OUT((TEXT("GetNextBriefcaseIterator(): Failed to remove unavailable/missing briefcase from system.")));
  466. }
  467. ASSERT(pbciter->aiNext < ARRAYINDEX_MAX);
  468. pbciter->aiNext++;
  469. if (tr == TR_SUCCESS)
  470. break;
  471. }
  472. return(tr);
  473. }
  474. /*
  475. ** DestroyBriefcaseIterator()
  476. **
  477. **
  478. **
  479. ** Arguments:
  480. **
  481. ** Returns:
  482. **
  483. ** Side Effects: none
  484. */
  485. PRIVATE_CODE void DestroyBriefcaseIterator(PBRFCASEITER pbciter)
  486. {
  487. ARRAYINDEX ai;
  488. ARRAYINDEX aicPtrs;
  489. ASSERT(IS_VALID_STRUCT_PTR(pbciter, CBRFCASEITER));
  490. aicPtrs = GetPtrCount(pbciter->hpa);
  491. for (ai = 0; ai < aicPtrs; ai++)
  492. FreeMemory(GetPtr(pbciter->hpa, ai));
  493. DestroyPtrArray(pbciter->hpa);
  494. FreeMemory(pbciter);
  495. return;
  496. }
  497. /*
  498. ** AddBriefcaseToIteratorProc()
  499. **
  500. **
  501. **
  502. ** Arguments:
  503. **
  504. ** Returns:
  505. **
  506. ** Side Effects: none
  507. */
  508. PRIVATE_CODE LONG AddBriefcaseToIteratorProc(PCLINKINFO pcli, PCVOID pcbciter,
  509. PBOOL pbAbort)
  510. {
  511. LONG lResult;
  512. PLINKINFO pliCopy;
  513. ASSERT(IS_VALID_STRUCT_PTR(pcli, CLINKINFO));
  514. ASSERT(IS_VALID_STRUCT_PTR(pcbciter, CBRFCASEITER));
  515. ASSERT(IS_VALID_WRITE_PTR(pbAbort, BOOL));
  516. /* Add this briefcase database's LinkInfo to the iterator's list. */
  517. *pbAbort = TRUE;
  518. lResult = ERROR_OUTOFMEMORY;
  519. if (CopyLinkInfo(pcli, &pliCopy))
  520. {
  521. ARRAYINDEX ai;
  522. if (AddPtr(((PCBRFCASEITER)pcbciter)->hpa, LinkInfoSortCmp, pliCopy, &ai))
  523. {
  524. *pbAbort = FALSE;
  525. lResult = ERROR_SUCCESS;
  526. }
  527. else
  528. FreeMemory(pliCopy);
  529. }
  530. if (lResult == ERROR_SUCCESS)
  531. TRACE_OUT((TEXT("AddBriefcaseToIteratorProc(): Added LinkInfo for briefcase to briefcase iterator %#lx."),
  532. pcbciter));
  533. else
  534. WARNING_OUT((TEXT("AddBriefcaseToIteratorProc(): Failed to add LinkInfo for briefcase to briefcase iterator %#lx."),
  535. pcbciter));
  536. return(lResult);
  537. }
  538. /*
  539. ** CompareLinkInfoProc()
  540. **
  541. **
  542. **
  543. ** Arguments:
  544. **
  545. ** Returns:
  546. **
  547. ** Side Effects: none
  548. */
  549. PRIVATE_CODE LONG CompareLinkInfoProc(PCLINKINFO pcli, PCVOID pcliTarget,
  550. PBOOL pbAbort)
  551. {
  552. ASSERT(IS_VALID_STRUCT_PTR(pcli, CLINKINFO));
  553. ASSERT(IS_VALID_STRUCT_PTR(pcliTarget, CLINKINFO));
  554. ASSERT(IS_VALID_WRITE_PTR(pbAbort, BOOL));
  555. /* Does this LinkInfo match our target LinkInfo? */
  556. *pbAbort = (LinkInfoSearchCmp(pcli, pcliTarget) == CR_EQUAL);
  557. return(ERROR_SUCCESS);
  558. }
  559. /*
  560. ** MyAddBriefcaseToSystem()
  561. **
  562. **
  563. **
  564. ** Arguments:
  565. **
  566. ** Returns:
  567. **
  568. ** Side Effects: none
  569. */
  570. PRIVATE_CODE TWINRESULT MyAddBriefcaseToSystem(PCLINKINFO pcli)
  571. {
  572. LONG lResult;
  573. HKEY hkeyBriefcases;
  574. DWORD dwDisposition;
  575. ASSERT(IS_VALID_STRUCT_PTR(pcli, CLINKINFO));
  576. /* Open briefcase list registry key for common access. */
  577. lResult = RegCreateKeyEx(HKEY_BRIEFCASE_ROOT, BRIEFCASE_SUBKEY, 0, NULL,
  578. REG_OPTION_NON_VOLATILE,
  579. (KEY_QUERY_VALUE | KEY_SET_VALUE), NULL,
  580. &hkeyBriefcases, &dwDisposition);
  581. if (lResult == ERROR_SUCCESS)
  582. {
  583. TCHAR rgchValueName[MAX_VALUE_NAME_LEN];
  584. BOOL bFound;
  585. LONG lClose;
  586. lResult = EnumBriefcases(hkeyBriefcases, &CompareLinkInfoProc, pcli,
  587. rgchValueName, &bFound);
  588. if (lResult == ERROR_SUCCESS)
  589. {
  590. if (bFound)
  591. TRACE_OUT((TEXT("AddBriefcaseToSystem(): Briefcase database already in registry list as value %s under %s\\%s."),
  592. rgchValueName,
  593. HKEY_BRIEFCASE_ROOT_STRING,
  594. BRIEFCASE_SUBKEY));
  595. else
  596. {
  597. lResult = GetUnusedBriefcaseValueName(hkeyBriefcases,
  598. rgchValueName,
  599. ARRAYSIZE(rgchValueName));
  600. if (lResult == ERROR_SUCCESS)
  601. {
  602. lResult = RegSetValueEx(hkeyBriefcases, rgchValueName, 0,
  603. REG_BINARY, (PCBYTE)pcli,
  604. pcli->ucbSize);
  605. if (lResult == ERROR_SUCCESS)
  606. TRACE_OUT((TEXT("AddBriefcaseToSystem(): Briefcase database added to registry list as value %s under %s\\%s."),
  607. rgchValueName,
  608. HKEY_BRIEFCASE_ROOT_STRING,
  609. BRIEFCASE_SUBKEY));
  610. }
  611. }
  612. }
  613. lClose = RegCloseKey(hkeyBriefcases);
  614. if (lResult == ERROR_SUCCESS)
  615. lResult = lClose;
  616. }
  617. return(TranslateLRESULTToTWINRESULT(lResult));
  618. }
  619. /*
  620. ** MyRemoveBriefcaseFromSystem()
  621. **
  622. **
  623. **
  624. ** Arguments:
  625. **
  626. ** Returns:
  627. **
  628. ** Side Effects: none
  629. */
  630. PRIVATE_CODE TWINRESULT MyRemoveBriefcaseFromSystem(PCLINKINFO pcli)
  631. {
  632. LONG lResult;
  633. HKEY hkeyBriefcases;
  634. ASSERT(IS_VALID_STRUCT_PTR(pcli, CLINKINFO));
  635. /* Open briefcase list registry key for common access. */
  636. lResult = RegOpenKeyEx(HKEY_BRIEFCASE_ROOT, BRIEFCASE_SUBKEY, 0,
  637. (KEY_QUERY_VALUE | KEY_SET_VALUE), &hkeyBriefcases);
  638. if (lResult == ERROR_SUCCESS)
  639. {
  640. TCHAR rgchValueName[MAX_VALUE_NAME_LEN];
  641. BOOL bFound;
  642. LONG lClose;
  643. lResult = EnumBriefcases(hkeyBriefcases, &CompareLinkInfoProc, pcli,
  644. rgchValueName, &bFound);
  645. if (lResult == ERROR_SUCCESS)
  646. {
  647. if (bFound)
  648. {
  649. lResult = RegDeleteValue(hkeyBriefcases, rgchValueName);
  650. if (lResult == ERROR_SUCCESS)
  651. TRACE_OUT((TEXT("MyRemoveBriefcaseFromSystem(): Briefcase database removed from registry list as value %s under %s\\%s."),
  652. rgchValueName,
  653. HKEY_BRIEFCASE_ROOT_STRING,
  654. BRIEFCASE_SUBKEY));
  655. }
  656. else
  657. WARNING_OUT((TEXT("MyRemoveBriefcaseFromSystem(): Briefcase database not in registry list under %s\\%s."),
  658. HKEY_BRIEFCASE_ROOT_STRING,
  659. BRIEFCASE_SUBKEY));
  660. }
  661. lClose = RegCloseKey(hkeyBriefcases);
  662. if (lResult == ERROR_SUCCESS)
  663. lResult = lClose;
  664. }
  665. else if (lResult == ERROR_FILE_NOT_FOUND)
  666. {
  667. WARNING_OUT((TEXT("MyRemoveBriefcaseFromSystem(): Briefcase key %s\\%s does not exist."),
  668. HKEY_BRIEFCASE_ROOT_STRING,
  669. BRIEFCASE_SUBKEY));
  670. lResult = ERROR_SUCCESS;
  671. }
  672. return(TranslateLRESULTToTWINRESULT(lResult));
  673. }
  674. /*
  675. ** UpdateBriefcaseLinkInfo()
  676. **
  677. **
  678. **
  679. ** Arguments:
  680. **
  681. ** Returns:
  682. **
  683. ** Side Effects: none
  684. */
  685. PRIVATE_CODE TWINRESULT UpdateBriefcaseLinkInfo(PCLINKINFO pcliOriginal,
  686. PCLINKINFO pcliUpdated)
  687. {
  688. LONG lResult;
  689. HKEY hkeyBriefcases;
  690. DWORD dwDisposition;
  691. ASSERT(IS_VALID_STRUCT_PTR(pcliOriginal, CLINKINFO));
  692. ASSERT(IS_VALID_STRUCT_PTR(pcliUpdated, CLINKINFO));
  693. /* Open briefcase list registry key for common access. */
  694. lResult = RegCreateKeyEx(HKEY_BRIEFCASE_ROOT, BRIEFCASE_SUBKEY, 0, NULL,
  695. REG_OPTION_NON_VOLATILE,
  696. (KEY_QUERY_VALUE | KEY_SET_VALUE), NULL,
  697. &hkeyBriefcases, &dwDisposition);
  698. if (lResult == ERROR_SUCCESS)
  699. {
  700. TCHAR rgchValueName[MAX_VALUE_NAME_LEN];
  701. BOOL bFound;
  702. LONG lClose;
  703. lResult = EnumBriefcases(hkeyBriefcases, &CompareLinkInfoProc,
  704. pcliOriginal, rgchValueName, &bFound);
  705. if (lResult == ERROR_SUCCESS)
  706. {
  707. if (bFound)
  708. {
  709. lResult = RegSetValueEx(hkeyBriefcases, rgchValueName, 0,
  710. REG_BINARY, (PCBYTE)pcliUpdated,
  711. pcliUpdated->ucbSize);
  712. if (lResult == ERROR_SUCCESS)
  713. TRACE_OUT((TEXT("UpdateBriefcaseLinkInfo(): Briefcase database LinkInfo updated in registry list as value %s under %s\\%s."),
  714. rgchValueName,
  715. HKEY_BRIEFCASE_ROOT_STRING,
  716. BRIEFCASE_SUBKEY));
  717. }
  718. else
  719. WARNING_OUT((TEXT("UpdateBriefcaseLinkInfo(): Briefcase database LinkInfo not found in registry list under %s\\%s."),
  720. HKEY_BRIEFCASE_ROOT_STRING,
  721. BRIEFCASE_SUBKEY));
  722. }
  723. lClose = RegCloseKey(hkeyBriefcases);
  724. if (lResult == ERROR_SUCCESS)
  725. lResult = lClose;
  726. }
  727. return(TranslateLRESULTToTWINRESULT(lResult));
  728. }
  729. #if defined(DEBUG) || defined(VSTF)
  730. /*
  731. ** IsValidPCBRFCASEITER()
  732. **
  733. **
  734. **
  735. ** Arguments:
  736. **
  737. ** Returns:
  738. **
  739. ** Side Effects: none
  740. */
  741. PRIVATE_CODE BOOL IsValidPCBRFCASEITER(PCBRFCASEITER pcbciter)
  742. {
  743. BOOL bResult = FALSE;
  744. if (IS_VALID_READ_PTR(pcbciter, CBRFCASEITER) &&
  745. IS_VALID_HANDLE(pcbciter->hpa, PTRARRAY))
  746. {
  747. ARRAYINDEX aicPtrs;
  748. ARRAYINDEX ai;
  749. aicPtrs = GetPtrCount(pcbciter->hpa);
  750. for (ai = 0; ai < aicPtrs; ai++)
  751. {
  752. if (! IS_VALID_STRUCT_PTR(GetPtr(pcbciter->hpa, ai), CLINKINFO))
  753. break;
  754. }
  755. bResult = (ai == aicPtrs);
  756. }
  757. return(bResult);
  758. }
  759. #endif
  760. #ifdef EXPV
  761. /*
  762. ** IsValidHBRFCASEITER()
  763. **
  764. **
  765. **
  766. ** Arguments:
  767. **
  768. ** Returns:
  769. **
  770. ** Side Effects: none
  771. */
  772. PRIVATE_CODE BOOL IsValidHBRFCASEITER(HBRFCASEITER hbciter)
  773. {
  774. return(IS_VALID_STRUCT_PTR((PCBRFCASEITER)hbciter, CBRFCASEITER));
  775. }
  776. #endif
  777. /****************************** Public Functions *****************************/
  778. /*
  779. ** AddBriefcaseToSystem()
  780. **
  781. **
  782. **
  783. ** Arguments:
  784. **
  785. ** Returns:
  786. **
  787. ** Side Effects: none
  788. */
  789. PUBLIC_CODE TWINRESULT AddBriefcaseToSystem(LPCTSTR pcszBriefcaseDatabase)
  790. {
  791. TWINRESULT tr;
  792. PLINKINFO pli;
  793. ASSERT(IsFullPath(pcszBriefcaseDatabase));
  794. if (CreateLinkInfo(pcszBriefcaseDatabase, &pli))
  795. {
  796. tr = MyAddBriefcaseToSystem(pli);
  797. DestroyLinkInfo(pli);
  798. }
  799. else
  800. {
  801. /*
  802. * GetLastError() here to differentiate between TR_UNAVAILABLE_VOLUME and
  803. * TR_OUT_OF_MEMORY.
  804. */
  805. if (GetLastError() == ERROR_OUTOFMEMORY)
  806. tr = TR_OUT_OF_MEMORY;
  807. else
  808. tr = TR_UNAVAILABLE_VOLUME;
  809. }
  810. return(tr);
  811. }
  812. /*
  813. ** RemoveBriefcaseFromSystem()
  814. **
  815. **
  816. **
  817. ** Arguments:
  818. **
  819. ** Returns:
  820. **
  821. ** Side Effects: none
  822. */
  823. PUBLIC_CODE TWINRESULT RemoveBriefcaseFromSystem(LPCTSTR pcszBriefcaseDatabase)
  824. {
  825. TWINRESULT tr;
  826. PLINKINFO pli;
  827. ASSERT(IsFullPath(pcszBriefcaseDatabase));
  828. if (CreateLinkInfo(pcszBriefcaseDatabase, &pli))
  829. {
  830. tr = MyRemoveBriefcaseFromSystem(pli);
  831. DestroyLinkInfo(pli);
  832. }
  833. else
  834. {
  835. /*
  836. * GetLastError() here to differentiate between TR_UNAVAILABLE_VOLUME and
  837. * TR_OUT_OF_MEMORY.
  838. */
  839. if (GetLastError() == ERROR_OUTOFMEMORY)
  840. tr = TR_OUT_OF_MEMORY;
  841. else
  842. tr = TR_UNAVAILABLE_VOLUME;
  843. }
  844. return(tr);
  845. }
  846. /***************************** Exported Functions ****************************/
  847. /******************************************************************************
  848. @doc SYNCENGAPI
  849. @api TWINRESULT | FindFirstBriefcase | Finds the first briefcase in the current
  850. user's list of briefcases.
  851. @parm PHBRFCASEITER | phbciter | A pointer to an HBRFCASEITER to be filled in
  852. with a handle identifying the briefcase enumeration data associated with this
  853. call to FindFirstBriefcase(). This handle may be passed to FindNextBriefcase()
  854. amd FindCloseBriefcase(). This handle is only valid until FindBriefcaseClose()
  855. is called on it.
  856. @parm PBRFCASEINFO | pbcinfo | A pointer to a BRFCASEINFO to be filled in with
  857. information describing the first enumerated briefcase. The information in
  858. *pbcinfo is only valid until FindBriefcaseClose() is called on *phbciter.
  859. @rdesc If there is at least one existing briefcase in the user's list of
  860. briefcases, TR_SUCCESS is returned, *phbciter is filled in with a handle
  861. identifying the briefcase enumeration data associated with this call, and
  862. *pbcinfo contains information describing the first briefcase in the user's list
  863. of briefcases. If there are no existing briefcases in the user's list of
  864. briefcases, TR_NO_MORE is returned. Otherwise, the return value indicates the
  865. error that occurred. *phbciter and *pbcinfo are only valid if TR_SUCCESS is
  866. returned.
  867. @comm To find the next briefcase in the user's list of briefcases, call
  868. FindNextBriefcase() with *phbciter. Once the caller is finished enumerating
  869. briefcases, FindBriefcaseClose() should be called with *phbciter to free the
  870. briefcase enumeration data.
  871. @xref FindNextBriefcase() FindBriefcaseClose()
  872. ******************************************************************************/
  873. SYNCENGAPI TWINRESULT WINAPI FindFirstBriefcase(PHBRFCASEITER phbciter,
  874. PBRFCASEINFO pbcinfo)
  875. {
  876. TWINRESULT tr;
  877. if (BeginExclusiveBriefcaseAccess())
  878. {
  879. DebugEntry(FindFirstBriefcase);
  880. #ifdef EXPV
  881. /* Verify parameters. */
  882. if (IS_VALID_WRITE_PTR(phbciter, HBRFCASEITER) &&
  883. IS_VALID_WRITE_PTR(pbcinfo, BRFCASEINFO) &&
  884. EVAL(pbcinfo->ulSize == sizeof(*pbcinfo)))
  885. #endif
  886. {
  887. PBRFCASEITER pbciter;
  888. tr = CreateBriefcaseIterator(&pbciter);
  889. if (tr == TR_SUCCESS)
  890. {
  891. tr = GetNextBriefcaseIterator(pbciter, pbcinfo);
  892. if (tr == TR_SUCCESS)
  893. *phbciter = (HBRFCASEITER)pbciter;
  894. else
  895. DestroyBriefcaseIterator(pbciter);
  896. }
  897. }
  898. #ifdef EXPV
  899. else
  900. tr = TR_INVALID_PARAMETER;
  901. #endif
  902. DebugExitTWINRESULT(FindFirstBriefcase, tr);
  903. EndExclusiveBriefcaseAccess();
  904. }
  905. else
  906. tr = TR_REENTERED;
  907. return(tr);
  908. }
  909. /******************************************************************************
  910. @doc SYNCENGAPI
  911. @api TWINRESULT | FindNextBriefcase | Finds the next briefcase in the current
  912. user's list of briefcases.
  913. @parm HBRFCASEITER | hbciter | A handle identifying the briefcase enumeration
  914. data associated with a call to FindFirstBriefcase().
  915. @parm PBRFCASEINFO | pbcinfo | A pointer to a BRFCASEINFO to be filled in with
  916. information describing the next enumerated briefcase. The information in
  917. *pbcinfo is only valid until FindBriefcaseClose() is called on hbciter.
  918. @rdesc If there is at least one more existing briefcase in the user's list of
  919. briefcases, TR_SUCCESS is returned, and *pbcinfo contains information
  920. describing the next briefcase in the user's list of briefcases. If there are
  921. no more existing briefcases in the user's list of briefcases, TR_NO_MORE is
  922. returned. Otherwise, the return value indicates the error that occurred.
  923. *pbcinfo is only valid if TR_SUCCESS is returned.
  924. @xref FindFirstBriefcase() FindBriefcaseClose()
  925. ******************************************************************************/
  926. SYNCENGAPI TWINRESULT WINAPI FindNextBriefcase(HBRFCASEITER hbciter,
  927. PBRFCASEINFO pbcinfo)
  928. {
  929. TWINRESULT tr;
  930. if (BeginExclusiveBriefcaseAccess())
  931. {
  932. DebugEntry(FindNextBriefcase);
  933. #ifdef EXPV
  934. /* Verify parameters. */
  935. if (IS_VALID_HANDLE(hbciter, BRFCASEITER) &&
  936. IS_VALID_WRITE_PTR(pbcinfo, BRFCASEINFO) &&
  937. EVAL(pbcinfo->ulSize == sizeof(*pbcinfo)))
  938. #endif
  939. {
  940. tr = GetNextBriefcaseIterator((PBRFCASEITER)hbciter, pbcinfo);
  941. }
  942. #ifdef EXPV
  943. else
  944. tr = TR_INVALID_PARAMETER;
  945. #endif
  946. DebugExitTWINRESULT(FindNextBriefcase, tr);
  947. EndExclusiveBriefcaseAccess();
  948. }
  949. else
  950. tr = TR_REENTERED;
  951. return(tr);
  952. }
  953. /******************************************************************************
  954. @doc SYNCENGAPI
  955. @api TWINRESULT | FindBriefcaseClose | Terminates briefcase enumeration started
  956. by FindFirstBriefcase().
  957. @parm HBRFCASEITER | hbciter | A handle identifying the briefcase enumeration
  958. data associated with a call to FindFirstBriefcase(). This handle is invalid
  959. after calling FindBriefcaseClose().
  960. @rdesc If the briefcase enumeration was terminated successfully, TR_SUCCESS is
  961. returned. Otherwise, the return value indicates the error that occurred.
  962. @comm The information in any BRFCASEINFO structures returned by the call to
  963. FindFirstBriefcase() that returned hbciter, and by any subsequent calls to
  964. FindNextBriefcase() with hbciter, is invalid after FindBriefcaseClose() is
  965. called on hbciter.
  966. @xref FindFirstBriefcase() FindNextBriefcase()
  967. ******************************************************************************/
  968. SYNCENGAPI TWINRESULT WINAPI FindBriefcaseClose(HBRFCASEITER hbciter)
  969. {
  970. TWINRESULT tr;
  971. if (BeginExclusiveBriefcaseAccess())
  972. {
  973. DebugEntry(FindBriefcaseClose);
  974. #ifdef EXPV
  975. /* Verify parameters. */
  976. if (IS_VALID_HANDLE(hbciter, BRFCASEITER))
  977. #endif
  978. {
  979. DestroyBriefcaseIterator((PBRFCASEITER)hbciter);
  980. tr = TR_SUCCESS;
  981. }
  982. #ifdef EXPV
  983. else
  984. tr = TR_INVALID_PARAMETER;
  985. #endif
  986. DebugExitTWINRESULT(FindBriefcaseClose, tr);
  987. EndExclusiveBriefcaseAccess();
  988. }
  989. else
  990. tr = TR_REENTERED;
  991. return(tr);
  992. }