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.

1805 lines
46 KiB

  1. /*
  2. * brfcase.c - Briefcase ADT module.
  3. */
  4. /*
  5. */
  6. /* Headers
  7. **********/
  8. #include "project.h"
  9. #pragma hdrstop
  10. #include "findbc.h"
  11. /* Constants
  12. ************/
  13. /* database file attributes */
  14. #define DB_FILE_ATTR (FILE_ATTRIBUTE_HIDDEN)
  15. /* database cache lengths */
  16. #define DEFAULT_DATABASE_CACHE_LEN (32)
  17. #define MAX_DATABASE_CACHE_LEN (32 * 1024)
  18. /* string table allocation constants */
  19. #define NUM_NAME_HASH_BUCKETS (67)
  20. /* Types
  21. ********/
  22. /* briefcase database description */
  23. typedef struct _brfcasedb
  24. {
  25. /*
  26. * handle to path of folder of open database (stored in briefcase path list)
  27. */
  28. HPATH hpathDBFolder;
  29. /* name of database file */
  30. LPTSTR pszDBName;
  31. /* handle to open cached database file */
  32. HCACHEDFILE hcfDB;
  33. /*
  34. * handle to path of folder that database was last saved in (stored in
  35. * briefcase's path list), only valid during OpenBriefcase() and
  36. * SaveBriefcase()
  37. */
  38. HPATH hpathLastSavedDBFolder;
  39. }
  40. BRFCASEDB;
  41. DECLARE_STANDARD_TYPES(BRFCASEDB);
  42. /*
  43. * briefcase flags
  44. *
  45. * N.b., the private BR_ flags must not collide with the public OB_ flags!
  46. */
  47. typedef enum _brfcaseflags
  48. {
  49. /* The briefcase database has been opened. */
  50. BR_FL_DATABASE_OPENED = 0x00010000,
  51. /* The pimkRoot field is valid. */
  52. BR_FL_ROOT_MONIKER_VALID = 0x00020000,
  53. #ifdef DEBUG
  54. /* Briefcase is being deleted. */
  55. BR_FL_BEING_DELETED = 0x01000000,
  56. #endif
  57. /* flag combinations */
  58. ALL_BR_FLAGS = (BR_FL_DATABASE_OPENED |
  59. BR_FL_ROOT_MONIKER_VALID
  60. #ifdef DEBUG
  61. | BR_FL_BEING_DELETED
  62. #endif
  63. ),
  64. ALL_BRFCASE_FLAGS = (ALL_OB_FLAGS |
  65. ALL_BR_FLAGS)
  66. }
  67. BRFCASEFLAGS;
  68. /* briefcase structure */
  69. typedef struct _brfcase
  70. {
  71. /* flags */
  72. DWORD dwFlags;
  73. /* handle to name string table */
  74. HSTRINGTABLE hstNames;
  75. /* handle to list of paths */
  76. HPATHLIST hpathlist;
  77. /* handle to array of pointers to twin families */
  78. HPTRARRAY hpaTwinFamilies;
  79. /* handle to array of pointers to folder pairs */
  80. HPTRARRAY hpaFolderPairs;
  81. /*
  82. * handle to parent window, only valid if OB_FL_ALLOW_UI is set in dwFlags
  83. * field
  84. */
  85. HWND hwndOwner;
  86. /* briewfcase database folder moniker */
  87. PIMoniker pimkRoot;
  88. /* database description */
  89. BRFCASEDB bcdb;
  90. }
  91. BRFCASE;
  92. DECLARE_STANDARD_TYPES(BRFCASE);
  93. /* database briefcase structure */
  94. typedef struct _dbbrfcase
  95. {
  96. /* old handle to folder that database was saved in */
  97. HPATH hpathLastSavedDBFolder;
  98. }
  99. DBBRFCASE;
  100. DECLARE_STANDARD_TYPES(DBBRFCASE);
  101. #ifdef DEBUG
  102. /* debug flags */
  103. typedef enum _dbdebugflags
  104. {
  105. BRFCASE_DFL_NO_DB_SAVE = 0x0001,
  106. BRFCASE_DFL_NO_DB_RESTORE = 0x0002,
  107. ALL_BRFCASE_DFLAGS = (BRFCASE_DFL_NO_DB_SAVE |
  108. BRFCASE_DFL_NO_DB_RESTORE)
  109. }
  110. DBDEBUGFLAGS;
  111. #endif
  112. /* Module Variables
  113. *******************/
  114. /*
  115. * RAIDRAID: (16273) The use of MnrcsBriefcase in a shared data section is
  116. * broken under NT. To run under NT, this code should be changed to use a
  117. * shared mutex.
  118. */
  119. /* critical section used for briefcase access serialization */
  120. PRIVATE_DATA NONREENTRANTCRITICALSECTION MnrcsBriefcase =
  121. {
  122. { 0 },
  123. #ifdef DEBUG
  124. INVALID_THREAD_ID,
  125. #endif /* DEBUG */
  126. FALSE
  127. };
  128. /* open briefcases */
  129. PRIVATE_DATA HLIST MhlistOpenBriefcases = NULL;
  130. /* database cache size */
  131. PRIVATE_DATA DWORD MdwcbMaxDatabaseCacheLen = MAX_DATABASE_CACHE_LEN;
  132. #ifdef DEBUG
  133. /* debug flags */
  134. PRIVATE_DATA DWORD MdwBriefcaseModuleFlags = 0;
  135. /* .ini file switch descriptions */
  136. PRIVATE_DATA CBOOLINISWITCH cbisNoDatabaseSave =
  137. {
  138. IST_BOOL,
  139. TEXT("NoDatabaseSave"),
  140. &MdwBriefcaseModuleFlags,
  141. BRFCASE_DFL_NO_DB_SAVE
  142. };
  143. PRIVATE_DATA CBOOLINISWITCH cbisNoDatabaseRestore =
  144. {
  145. IST_BOOL,
  146. TEXT("NoDatabaseRestore"),
  147. &MdwBriefcaseModuleFlags,
  148. BRFCASE_DFL_NO_DB_RESTORE
  149. };
  150. PRIVATE_DATA CUNSDECINTINISWITCH cdiisMaxDatabaseCacheLen =
  151. {
  152. IST_UNS_DEC_INT,
  153. TEXT("MaxDatabaseCacheLen"),
  154. (PUINT)&MdwcbMaxDatabaseCacheLen
  155. };
  156. PRIVATE_DATA const PCVOID MrgcpcvisBriefcaseModule[] =
  157. {
  158. &cbisNoDatabaseSave,
  159. &cbisNoDatabaseRestore,
  160. &cdiisMaxDatabaseCacheLen
  161. };
  162. #endif /* DEBUG */
  163. /***************************** Private Functions *****************************/
  164. /* Module Prototypes
  165. ********************/
  166. PRIVATE_CODE TWINRESULT OpenBriefcaseDatabase(PBRFCASE, LPCTSTR);
  167. PRIVATE_CODE TWINRESULT CloseBriefcaseDatabase(PBRFCASEDB);
  168. PRIVATE_CODE BOOL CreateBriefcase(PBRFCASE *, DWORD, HWND);
  169. PRIVATE_CODE void UnlinkBriefcase(PBRFCASE);
  170. PRIVATE_CODE TWINRESULT DestroyBriefcase(PBRFCASE);
  171. PRIVATE_CODE TWINRESULT MyWriteDatabase(PBRFCASE);
  172. PRIVATE_CODE TWINRESULT MyReadDatabase(PBRFCASE, DWORD);
  173. #ifdef DEBUG
  174. PRIVATE_CODE BOOL DestroyBriefcaseWalker(PVOID, PVOID);
  175. #endif
  176. #ifdef VSTF
  177. PRIVATE_CODE BOOL IsValidPCBRFCASE(PCBRFCASE);
  178. PRIVATE_CODE BOOL IsValidPCBRFCASEDB(PCBRFCASEDB);
  179. PRIVATE_CODE BOOL IsValidPCOPENBRFCASEINFO(PCOPENBRFCASEINFO);
  180. #endif
  181. /*
  182. ** OpenBriefcaseDatabase()
  183. **
  184. **
  185. **
  186. ** Arguments:
  187. **
  188. ** Returns:
  189. **
  190. ** Side Effects: none
  191. */
  192. PRIVATE_CODE TWINRESULT OpenBriefcaseDatabase(PBRFCASE pbr, LPCTSTR pcszPath)
  193. {
  194. TWINRESULT tr;
  195. TCHAR rgchCanonicalPath[MAX_SEPARATED_PATH_LEN];
  196. DWORD dwOutFlags;
  197. TCHAR rgchNetResource[MAX_PATH_LEN];
  198. LPTSTR pszRootPathSuffix;
  199. ASSERT(IS_VALID_STRUCT_PTR(pbr, CBRFCASE));
  200. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  201. if (GetCanonicalPathInfo(pcszPath, rgchCanonicalPath, &dwOutFlags,
  202. rgchNetResource, &pszRootPathSuffix))
  203. {
  204. LPTSTR pszDBName;
  205. pszDBName = (LPTSTR)ExtractFileName(pszRootPathSuffix);
  206. ASSERT(IS_SLASH(*(pszDBName - 1)));
  207. if (StringCopy(pszDBName, &(pbr->bcdb.pszDBName)))
  208. {
  209. if (pszDBName == pszRootPathSuffix)
  210. {
  211. /* Database in root. */
  212. *pszDBName = TEXT('\0');
  213. ASSERT(IsRootPath(rgchCanonicalPath));
  214. }
  215. else
  216. {
  217. ASSERT(pszDBName > pszRootPathSuffix);
  218. *(pszDBName - 1) = TEXT('\0');
  219. }
  220. tr = TranslatePATHRESULTToTWINRESULT(
  221. AddPath(pbr->hpathlist, rgchCanonicalPath,
  222. &(pbr->bcdb.hpathDBFolder)));
  223. if (tr == TR_SUCCESS)
  224. {
  225. if (IsPathVolumeAvailable(pbr->bcdb.hpathDBFolder))
  226. {
  227. TCHAR rgchDBPath[MAX_PATH_LEN];
  228. CACHEDFILE cfDB;
  229. GetPathString(pbr->bcdb.hpathDBFolder, rgchDBPath, ARRAYSIZE(rgchDBPath));
  230. CatPath(rgchDBPath, pbr->bcdb.pszDBName, ARRAYSIZE(rgchDBPath));
  231. /* Assume sequential reads and writes. */
  232. /* Share read access, but not write access. */
  233. cfDB.pcszPath = rgchDBPath;
  234. cfDB.dwOpenMode = (GENERIC_READ | GENERIC_WRITE);
  235. cfDB.dwSharingMode = FILE_SHARE_READ;
  236. cfDB.psa = NULL;
  237. cfDB.dwCreateMode = OPEN_ALWAYS;
  238. cfDB.dwAttrsAndFlags = (DB_FILE_ATTR | FILE_FLAG_SEQUENTIAL_SCAN);
  239. cfDB.hTemplateFile = NULL;
  240. cfDB.dwcbDefaultCacheSize = DEFAULT_DATABASE_CACHE_LEN;
  241. tr = TranslateFCRESULTToTWINRESULT(
  242. CreateCachedFile(&cfDB, &(pbr->bcdb.hcfDB)));
  243. if (tr == TR_SUCCESS)
  244. {
  245. pbr->bcdb.hpathLastSavedDBFolder = NULL;
  246. ASSERT(IS_FLAG_CLEAR(pbr->dwFlags, BR_FL_DATABASE_OPENED));
  247. SET_FLAG(pbr->dwFlags, BR_FL_DATABASE_OPENED);
  248. }
  249. else
  250. {
  251. DeletePath(pbr->bcdb.hpathDBFolder);
  252. OPENBRIEFCASEDATABASE_BAIL:
  253. FreeMemory(pbr->bcdb.pszDBName);
  254. }
  255. }
  256. else
  257. {
  258. tr = TR_UNAVAILABLE_VOLUME;
  259. goto OPENBRIEFCASEDATABASE_BAIL;
  260. }
  261. }
  262. }
  263. else
  264. tr = TR_OUT_OF_MEMORY;
  265. }
  266. else
  267. tr = TWINRESULTFromLastError(TR_INVALID_PARAMETER);
  268. return(tr);
  269. }
  270. /*
  271. ** CloseBriefcaseDatabase()
  272. **
  273. **
  274. **
  275. ** Arguments:
  276. **
  277. ** Returns:
  278. **
  279. ** Side Effects: none
  280. */
  281. PRIVATE_CODE TWINRESULT CloseBriefcaseDatabase(PBRFCASEDB pbcdb)
  282. {
  283. TWINRESULT tr;
  284. TCHAR rgchDBPath[MAX_PATH_LEN];
  285. FILESTAMP fsDB;
  286. tr = CloseCachedFile(pbcdb->hcfDB) ? TR_SUCCESS : TR_BRIEFCASE_WRITE_FAILED;
  287. if (tr == TR_SUCCESS)
  288. TRACE_OUT((TEXT("CloseBriefcaseDatabase(): Closed cached briefcase database file %s\\%s."),
  289. DebugGetPathString(pbcdb->hpathDBFolder),
  290. pbcdb->pszDBName));
  291. else
  292. WARNING_OUT((TEXT("CloseBriefcaseDatabase(): Failed to close cached briefcase database file %s\\%s."),
  293. DebugGetPathString(pbcdb->hpathDBFolder),
  294. pbcdb->pszDBName));
  295. /* Try not to leave a 0-length database laying around. */
  296. GetPathString(pbcdb->hpathDBFolder, rgchDBPath, ARRAYSIZE(rgchDBPath));
  297. CatPath(rgchDBPath, pbcdb->pszDBName, ARRAYSIZE(rgchDBPath));
  298. MyGetFileStamp(rgchDBPath, &fsDB);
  299. if (fsDB.fscond == FS_COND_EXISTS &&
  300. (! fsDB.dwcbLowLength && ! fsDB.dwcbHighLength))
  301. {
  302. if (DeleteFile(rgchDBPath))
  303. WARNING_OUT((TEXT("CloseBriefcaseDatabase(): Deleted 0 length database %s\\%s."),
  304. DebugGetPathString(pbcdb->hpathDBFolder),
  305. pbcdb->pszDBName));
  306. }
  307. FreeMemory(pbcdb->pszDBName);
  308. DeletePath(pbcdb->hpathDBFolder);
  309. return(tr);
  310. }
  311. /*
  312. ** CreateBriefcase()
  313. **
  314. **
  315. **
  316. ** Arguments:
  317. **
  318. ** Returns:
  319. **
  320. ** Side Effects: none
  321. */
  322. PRIVATE_CODE BOOL CreateBriefcase(PBRFCASE *ppbr, DWORD dwInFlags,
  323. HWND hwndOwner)
  324. {
  325. BOOL bResult = FALSE;
  326. ASSERT(IS_VALID_WRITE_PTR(ppbr, PBRFCASE));
  327. ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_BRFCASE_FLAGS));
  328. ASSERT(IS_FLAG_CLEAR(dwInFlags, OB_FL_ALLOW_UI) ||
  329. IS_VALID_HANDLE(hwndOwner, WND));
  330. if (AllocateMemory(sizeof(**ppbr), ppbr))
  331. {
  332. DWORD dwCPLFlags;
  333. dwCPLFlags = (RLI_IFL_CONNECT |
  334. RLI_IFL_UPDATE |
  335. RLI_IFL_LOCAL_SEARCH);
  336. if (IS_FLAG_SET(dwInFlags, OB_FL_ALLOW_UI))
  337. SET_FLAG(dwCPLFlags, RLI_IFL_ALLOW_UI);
  338. if (CreatePathList(dwCPLFlags, hwndOwner, &((*ppbr)->hpathlist)))
  339. {
  340. NEWSTRINGTABLE nszt;
  341. nszt.hbc = NUM_NAME_HASH_BUCKETS;
  342. if (CreateStringTable(&nszt, &((*ppbr)->hstNames)))
  343. {
  344. if (CreateTwinFamilyPtrArray(&((*ppbr)->hpaTwinFamilies)))
  345. {
  346. if (CreateFolderPairPtrArray(&((*ppbr)->hpaFolderPairs)))
  347. {
  348. HNODE hnode;
  349. if (InsertNodeAtFront(MhlistOpenBriefcases, NULL, (*ppbr), &hnode))
  350. {
  351. (*ppbr)->dwFlags = dwInFlags;
  352. (*ppbr)->hwndOwner = hwndOwner;
  353. bResult = TRUE;
  354. }
  355. else
  356. {
  357. DestroyFolderPairPtrArray((*ppbr)->hpaFolderPairs);
  358. CREATEBRIEFCASE_BAIL1:
  359. DestroyTwinFamilyPtrArray((*ppbr)->hpaTwinFamilies);
  360. CREATEBRIEFCASE_BAIL2:
  361. DestroyStringTable((*ppbr)->hstNames);
  362. CREATEBRIEFCASE_BAIL3:
  363. DestroyPathList((*ppbr)->hpathlist);
  364. CREATEBRIEFCASE_BAIL4:
  365. FreeMemory((*ppbr));
  366. }
  367. }
  368. else
  369. goto CREATEBRIEFCASE_BAIL1;
  370. }
  371. else
  372. goto CREATEBRIEFCASE_BAIL2;
  373. }
  374. else
  375. goto CREATEBRIEFCASE_BAIL3;
  376. }
  377. else
  378. goto CREATEBRIEFCASE_BAIL4;
  379. }
  380. ASSERT(! bResult ||
  381. IS_VALID_STRUCT_PTR(*ppbr, CBRFCASE));
  382. return(bResult);
  383. }
  384. /*
  385. ** UnlinkBriefcase()
  386. **
  387. **
  388. **
  389. ** Arguments:
  390. **
  391. ** Returns:
  392. **
  393. ** Side Effects: none
  394. */
  395. PRIVATE_CODE void UnlinkBriefcase(PBRFCASE pbr)
  396. {
  397. BOOL bContinue;
  398. HNODE hnode;
  399. ASSERT(IS_VALID_STRUCT_PTR(pbr, CBRFCASE));
  400. for (bContinue = GetFirstNode(MhlistOpenBriefcases, &hnode);
  401. bContinue;
  402. bContinue = GetNextNode(hnode, &hnode))
  403. {
  404. PBRFCASE pbrTest;
  405. pbrTest = GetNodeData(hnode);
  406. ASSERT(IS_VALID_STRUCT_PTR(pbrTest, CBRFCASE));
  407. if (pbrTest == pbr)
  408. {
  409. DeleteNode(hnode);
  410. break;
  411. }
  412. }
  413. ASSERT(bContinue);
  414. return;
  415. }
  416. /*
  417. ** DestroyBriefcase()
  418. **
  419. **
  420. **
  421. ** Arguments:
  422. **
  423. ** Returns:
  424. **
  425. ** Side Effects: none
  426. */
  427. PRIVATE_CODE TWINRESULT DestroyBriefcase(PBRFCASE pbr)
  428. {
  429. TWINRESULT tr;
  430. ASSERT(IS_VALID_STRUCT_PTR(pbr, CBRFCASE));
  431. #ifdef DEBUG
  432. SET_FLAG(pbr->dwFlags, BR_FL_BEING_DELETED);
  433. #endif
  434. if (IS_FLAG_SET(pbr->dwFlags, BR_FL_DATABASE_OPENED))
  435. tr = CloseBriefcaseDatabase(&(pbr->bcdb));
  436. else
  437. tr = TR_SUCCESS;
  438. if (IS_FLAG_SET(pbr->dwFlags, BR_FL_ROOT_MONIKER_VALID))
  439. pbr->pimkRoot->lpVtbl->Release(pbr->pimkRoot);
  440. DestroyFolderPairPtrArray(pbr->hpaFolderPairs);
  441. DestroyTwinFamilyPtrArray(pbr->hpaTwinFamilies);
  442. ASSERT(! GetStringCount(pbr->hstNames));
  443. DestroyStringTable(pbr->hstNames);
  444. ASSERT(! GetPathCount(pbr->hpathlist));
  445. DestroyPathList(pbr->hpathlist);
  446. FreeMemory(pbr);
  447. return(tr);
  448. }
  449. /*
  450. ** MyWriteDatabase()
  451. **
  452. **
  453. **
  454. ** Arguments:
  455. **
  456. ** Returns:
  457. **
  458. ** Side Effects: none
  459. */
  460. PRIVATE_CODE TWINRESULT MyWriteDatabase(PBRFCASE pbr)
  461. {
  462. TWINRESULT tr;
  463. ASSERT(IS_VALID_STRUCT_PTR(pbr, CBRFCASE));
  464. ASSERT(IS_FLAG_SET(pbr->dwFlags, BR_FL_DATABASE_OPENED));
  465. #ifdef DEBUG
  466. if (IS_FLAG_CLEAR(MdwBriefcaseModuleFlags, BRFCASE_DFL_NO_DB_SAVE))
  467. #endif
  468. {
  469. /* Grow the database cache in preparation for writing. */
  470. ASSERT(MdwcbMaxDatabaseCacheLen > 0);
  471. if (SetCachedFileCacheSize(pbr->bcdb.hcfDB, MdwcbMaxDatabaseCacheLen)
  472. != FCR_SUCCESS)
  473. WARNING_OUT((TEXT("MyWriteDatabase(): Unable to grow database cache to %lu bytes. Using default database write cache of %lu bytes."),
  474. MdwcbMaxDatabaseCacheLen,
  475. (DWORD)DEFAULT_DATABASE_CACHE_LEN));
  476. /* Write the database. */
  477. tr = WriteTwinDatabase(pbr->bcdb.hcfDB, (HBRFCASE)pbr);
  478. if (tr == TR_SUCCESS)
  479. {
  480. if (CommitCachedFile(pbr->bcdb.hcfDB))
  481. {
  482. /* Shrink the database cache back down to its default size. */
  483. EVAL(SetCachedFileCacheSize(pbr->bcdb.hcfDB,
  484. DEFAULT_DATABASE_CACHE_LEN)
  485. == FCR_SUCCESS);
  486. TRACE_OUT((TEXT("MyWriteDatabase(): Wrote database %s\\%s."),
  487. DebugGetPathString(pbr->bcdb.hpathDBFolder),
  488. pbr->bcdb.pszDBName));
  489. }
  490. else
  491. tr = TR_BRIEFCASE_WRITE_FAILED;
  492. }
  493. }
  494. #ifdef DEBUG
  495. else
  496. {
  497. WARNING_OUT((TEXT("MyWriteDatabase(): Twin database %s\\%s not saved, by request."),
  498. DebugGetPathString(pbr->bcdb.hpathDBFolder),
  499. pbr->bcdb.pszDBName));
  500. tr = TR_SUCCESS;
  501. }
  502. #endif
  503. return(tr);
  504. }
  505. /*
  506. ** MyReadDatabase()
  507. **
  508. **
  509. **
  510. ** Arguments:
  511. **
  512. ** Returns:
  513. **
  514. ** Side Effects: none
  515. */
  516. PRIVATE_CODE TWINRESULT MyReadDatabase(PBRFCASE pbr, DWORD dwInFlags)
  517. {
  518. TWINRESULT tr;
  519. ASSERT(IS_VALID_STRUCT_PTR(pbr, CBRFCASE));
  520. ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_OB_FLAGS));
  521. #ifdef DEBUG
  522. if (IS_FLAG_CLEAR(MdwBriefcaseModuleFlags, BRFCASE_DFL_NO_DB_RESTORE))
  523. #endif
  524. {
  525. DWORD dwcbDatabaseSize;
  526. /* Is there an exising database to read? */
  527. dwcbDatabaseSize = GetCachedFileSize(pbr->bcdb.hcfDB);
  528. if (dwcbDatabaseSize > 0)
  529. {
  530. DWORD dwcbMaxCacheSize;
  531. /* Yes. Grow the database cache in preparation for reading. */
  532. /*
  533. * Use file length instead of MdwcbMaxDatabaseCacheLen if file length
  534. * is smaller.
  535. */
  536. ASSERT(MdwcbMaxDatabaseCacheLen > 0);
  537. if (dwcbDatabaseSize < MdwcbMaxDatabaseCacheLen)
  538. {
  539. dwcbMaxCacheSize = dwcbDatabaseSize;
  540. WARNING_OUT((TEXT("MyReadDatabase(): Using file size %lu bytes as read cache size for database %s\\%s."),
  541. dwcbDatabaseSize,
  542. DebugGetPathString(pbr->bcdb.hpathDBFolder),
  543. pbr->bcdb.pszDBName));
  544. }
  545. else
  546. dwcbMaxCacheSize = MdwcbMaxDatabaseCacheLen;
  547. if (TranslateFCRESULTToTWINRESULT(SetCachedFileCacheSize(
  548. pbr->bcdb.hcfDB,
  549. dwcbMaxCacheSize))
  550. != TR_SUCCESS)
  551. WARNING_OUT((TEXT("MyReadDatabase(): Unable to grow database cache to %lu bytes. Using default database read cache of %lu bytes."),
  552. dwcbMaxCacheSize,
  553. (DWORD)DEFAULT_DATABASE_CACHE_LEN));
  554. tr = ReadTwinDatabase((HBRFCASE)pbr, pbr->bcdb.hcfDB);
  555. if (tr == TR_SUCCESS)
  556. {
  557. ASSERT(! pbr->bcdb.hpathLastSavedDBFolder ||
  558. IS_VALID_HANDLE(pbr->bcdb.hpathLastSavedDBFolder, PATH));
  559. if (pbr->bcdb.hpathLastSavedDBFolder)
  560. {
  561. if (IS_FLAG_SET(dwInFlags, OB_FL_TRANSLATE_DB_FOLDER) &&
  562. ComparePaths(pbr->bcdb.hpathLastSavedDBFolder,
  563. pbr->bcdb.hpathDBFolder) != CR_EQUAL)
  564. tr = MyTranslateFolder((HBRFCASE)pbr,
  565. pbr->bcdb.hpathLastSavedDBFolder,
  566. pbr->bcdb.hpathDBFolder);
  567. DeletePath(pbr->bcdb.hpathLastSavedDBFolder);
  568. pbr->bcdb.hpathLastSavedDBFolder = NULL;
  569. }
  570. if (tr == TR_SUCCESS)
  571. TRACE_OUT((TEXT("MyReadDatabase(): Read database %s\\%s."),
  572. DebugGetPathString(pbr->bcdb.hpathDBFolder),
  573. pbr->bcdb.pszDBName));
  574. }
  575. /* Shrink the database cache back down to its default size. */
  576. EVAL(TranslateFCRESULTToTWINRESULT(SetCachedFileCacheSize(
  577. pbr->bcdb.hcfDB,
  578. DEFAULT_DATABASE_CACHE_LEN))
  579. == TR_SUCCESS);
  580. }
  581. else
  582. {
  583. tr = TR_SUCCESS;
  584. WARNING_OUT((TEXT("MyReadDatabase(): Database %s\\%s not found."),
  585. DebugGetPathString(pbr->bcdb.hpathDBFolder),
  586. pbr->bcdb.pszDBName));
  587. }
  588. }
  589. #ifdef DEBUG
  590. else
  591. {
  592. WARNING_OUT((TEXT("MyReadDatabase(): Twin database %s\\%s not read, by request."),
  593. DebugGetPathString(pbr->bcdb.hpathDBFolder),
  594. pbr->bcdb.pszDBName));
  595. tr = TR_SUCCESS;
  596. }
  597. #endif
  598. return(tr);
  599. }
  600. #ifdef DEBUG
  601. /*
  602. ** DestroyBriefcaseWalker()
  603. **
  604. **
  605. **
  606. ** Arguments:
  607. **
  608. ** Returns:
  609. **
  610. ** Side Effects: none
  611. */
  612. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  613. PRIVATE_CODE BOOL DestroyBriefcaseWalker(PVOID pbr, PVOID pvUnused)
  614. {
  615. ASSERT(IS_VALID_STRUCT_PTR(pbr, CBRFCASE));
  616. ASSERT(! pvUnused);
  617. EVAL(DestroyBriefcase(pbr) == TR_SUCCESS);
  618. return(TRUE);
  619. }
  620. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  621. #endif
  622. #ifdef VSTF
  623. /*
  624. ** IsValidPCBRFCASE()
  625. **
  626. **
  627. **
  628. ** Arguments:
  629. **
  630. ** Returns:
  631. **
  632. ** Side Effects: none
  633. */
  634. PRIVATE_CODE BOOL IsValidPCBRFCASE(PCBRFCASE pcbr)
  635. {
  636. BOOL bResult = FALSE;
  637. if (IS_VALID_READ_PTR(pcbr, CBRFCASE))
  638. {
  639. if (FLAGS_ARE_VALID(pcbr->dwFlags, ALL_BRFCASE_FLAGS))
  640. {
  641. #ifdef DEBUG
  642. if (IS_FLAG_SET(pcbr->dwFlags, BR_FL_BEING_DELETED))
  643. bResult = TRUE;
  644. else
  645. #endif
  646. bResult = (IS_VALID_HANDLE(pcbr->hstNames, STRINGTABLE) &&
  647. IS_VALID_HANDLE(pcbr->hpathlist, PATHLIST) &&
  648. IS_VALID_HANDLE(pcbr->hpaTwinFamilies, PTRARRAY) &&
  649. IS_VALID_HANDLE(pcbr->hpaFolderPairs, PTRARRAY) &&
  650. (IS_FLAG_CLEAR(pcbr->dwFlags, OB_FL_ALLOW_UI) ||
  651. IS_VALID_HANDLE(pcbr->hwndOwner, WND)) &&
  652. (IS_FLAG_CLEAR(pcbr->dwFlags, BR_FL_ROOT_MONIKER_VALID) ||
  653. IS_VALID_STRUCT_PTR(pcbr->pimkRoot, CIMoniker)) &&
  654. (IS_FLAG_CLEAR(pcbr->dwFlags, BR_FL_DATABASE_OPENED) ||
  655. (IS_FLAG_SET(pcbr->dwFlags, OB_FL_OPEN_DATABASE) &&
  656. IS_VALID_STRUCT_PTR(&(pcbr->bcdb), CBRFCASEDB))));
  657. }
  658. }
  659. return(bResult);
  660. }
  661. /*
  662. ** IsValidPCBRFCASEDB()
  663. **
  664. **
  665. **
  666. ** Arguments:
  667. **
  668. ** Returns:
  669. **
  670. ** Side Effects: none
  671. */
  672. PRIVATE_CODE BOOL IsValidPCBRFCASEDB(PCBRFCASEDB pcbcdb)
  673. {
  674. return(IS_VALID_READ_PTR(pcbcdb, CBRFCASEDB) &&
  675. IS_VALID_HANDLE(pcbcdb->hpathDBFolder, PATH) &&
  676. IS_VALID_STRING_PTR(pcbcdb->pszDBName, STR) &&
  677. IS_VALID_HANDLE(pcbcdb->hcfDB, CACHEDFILE) &&
  678. (! pcbcdb->hpathLastSavedDBFolder ||
  679. IS_VALID_HANDLE(pcbcdb->hpathLastSavedDBFolder, PATH)));
  680. }
  681. /*
  682. ** IsValidPCOPENBRFCASEINFO()
  683. **
  684. **
  685. **
  686. ** Arguments:
  687. **
  688. ** Returns:
  689. **
  690. ** Side Effects: none
  691. */
  692. PRIVATE_CODE BOOL IsValidPCOPENBRFCASEINFO(PCOPENBRFCASEINFO pcobri)
  693. {
  694. return(IS_VALID_READ_PTR(pcobri, COPENBRFCASEINFO) &&
  695. EVAL(pcobri->ulSize == sizeof(*pcobri)) &&
  696. FLAGS_ARE_VALID(pcobri->dwFlags, ALL_OB_FLAGS) &&
  697. ((IS_FLAG_CLEAR(pcobri->dwFlags, OB_FL_ALLOW_UI) &&
  698. ! pcobri->hwndOwner) ||
  699. (IS_FLAG_SET(pcobri->dwFlags, OB_FL_ALLOW_UI) &&
  700. IS_VALID_HANDLE(pcobri->hwndOwner, WND))) &&
  701. ((IS_FLAG_CLEAR(pcobri->dwFlags, OB_FL_OPEN_DATABASE) &&
  702. ! pcobri->hvid &&
  703. ! (pcobri->rgchDatabasePath[0]))) ||
  704. ((IS_FLAG_SET(pcobri->dwFlags, OB_FL_OPEN_DATABASE) &&
  705. IS_VALID_HANDLE(pcobri->hvid, VOLUMEID) &&
  706. IS_VALID_STRING_PTR(pcobri->rgchDatabasePath, CSTR))));
  707. }
  708. #endif
  709. /****************************** Public Functions *****************************/
  710. #ifdef DEBUG
  711. /*
  712. ** SetBriefcaseModuleIniSwitches()
  713. **
  714. **
  715. **
  716. ** Arguments:
  717. **
  718. ** Returns:
  719. **
  720. ** Side Effects: none
  721. */
  722. PUBLIC_CODE BOOL SetBriefcaseModuleIniSwitches(void)
  723. {
  724. BOOL bResult;
  725. bResult = SetIniSwitches(MrgcpcvisBriefcaseModule,
  726. ARRAY_ELEMENTS(MrgcpcvisBriefcaseModule));
  727. if (! EVAL(MdwcbMaxDatabaseCacheLen > 0))
  728. {
  729. MdwcbMaxDatabaseCacheLen = 1;
  730. WARNING_OUT((TEXT("SetBriefcaseModuleIniSwitches(): Using maximum database cache length of %lu."),
  731. MdwcbMaxDatabaseCacheLen));
  732. }
  733. ASSERT(FLAGS_ARE_VALID(MdwBriefcaseModuleFlags, ALL_BRFCASE_DFLAGS));
  734. return(bResult);
  735. }
  736. #endif
  737. /*
  738. ** InitBriefcaseModule()
  739. **
  740. **
  741. **
  742. ** Arguments:
  743. **
  744. ** Returns:
  745. **
  746. ** Side Effects: none
  747. */
  748. PUBLIC_CODE BOOL InitBriefcaseModule(void)
  749. {
  750. NEWLIST nl;
  751. ASSERT(! MhlistOpenBriefcases);
  752. /* Create the module list of open briefcases. */
  753. ReinitializeNonReentrantCriticalSection(&MnrcsBriefcase);
  754. nl.dwFlags = 0;
  755. return(CreateList(&nl, &MhlistOpenBriefcases));
  756. }
  757. /*
  758. ** ExitBriefcaseModule()
  759. **
  760. **
  761. **
  762. ** Arguments:
  763. **
  764. ** Returns:
  765. **
  766. ** Side Effects: none
  767. */
  768. PUBLIC_CODE void ExitBriefcaseModule(void)
  769. {
  770. #ifdef DEBUG
  771. if (MhlistOpenBriefcases)
  772. {
  773. /* Destroy all open briefcases. */
  774. /*
  775. * Don't destroy the list of open briefcases in the retail build. Assume
  776. * that callers will have closed all open briefcases, so that there are
  777. * no remaining connections to shut down.
  778. */
  779. EVAL(WalkList(MhlistOpenBriefcases, &DestroyBriefcaseWalker, NULL));
  780. /* Now wipe out the list. */
  781. DestroyList(MhlistOpenBriefcases);
  782. MhlistOpenBriefcases = NULL;
  783. }
  784. else
  785. WARNING_OUT((TEXT("ExitBriefcaseModule() called when MhlistOpenBriefcases is NULL.")));
  786. #endif
  787. DeleteCriticalSection(&MnrcsBriefcase.critsec);
  788. return;
  789. }
  790. /*
  791. ** GetBriefcaseNameStringTable()
  792. **
  793. **
  794. **
  795. ** Arguments:
  796. **
  797. ** Returns:
  798. **
  799. ** Side Effects: none
  800. */
  801. PUBLIC_CODE HSTRINGTABLE GetBriefcaseNameStringTable(HBRFCASE hbr)
  802. {
  803. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  804. return(((PCBRFCASE)hbr)->hstNames);
  805. }
  806. /*
  807. ** GetBriefcaseTwinFamilyPtrArray()
  808. **
  809. **
  810. **
  811. ** Arguments:
  812. **
  813. ** Returns:
  814. **
  815. ** Side Effects: none
  816. */
  817. PUBLIC_CODE HPTRARRAY GetBriefcaseTwinFamilyPtrArray(HBRFCASE hbr)
  818. {
  819. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  820. return(((PCBRFCASE)hbr)->hpaTwinFamilies);
  821. }
  822. /*
  823. ** GetBriefcaseFolderPairPtrArray()
  824. **
  825. **
  826. **
  827. ** Arguments:
  828. **
  829. ** Returns:
  830. **
  831. ** Side Effects: none
  832. */
  833. PUBLIC_CODE HPTRARRAY GetBriefcaseFolderPairPtrArray(HBRFCASE hbr)
  834. {
  835. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  836. return(((PCBRFCASE)hbr)->hpaFolderPairs);
  837. }
  838. /*
  839. ** GetBriefcasePathList()
  840. **
  841. **
  842. **
  843. ** Arguments:
  844. **
  845. ** Returns:
  846. **
  847. ** Side Effects: none
  848. */
  849. PUBLIC_CODE HPATHLIST GetBriefcasePathList(HBRFCASE hbr)
  850. {
  851. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  852. return(((PCBRFCASE)hbr)->hpathlist);
  853. }
  854. /*
  855. ** GetBriefcaseRootMoniker()
  856. **
  857. **
  858. **
  859. ** Arguments:
  860. **
  861. ** Returns:
  862. **
  863. ** Side Effects: none
  864. */
  865. PUBLIC_CODE HRESULT GetBriefcaseRootMoniker(HBRFCASE hbr, PIMoniker *pimk)
  866. {
  867. HRESULT hr;
  868. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  869. ASSERT(IS_VALID_WRITE_PTR(pimk, CIMoniker));
  870. if (IS_FLAG_CLEAR(((PCBRFCASE)hbr)->dwFlags, BR_FL_ROOT_MONIKER_VALID))
  871. {
  872. if (IS_FLAG_SET(((PCBRFCASE)hbr)->dwFlags, BR_FL_DATABASE_OPENED))
  873. {
  874. TCHAR rgchRoot[MAX_PATH_LEN];
  875. WCHAR rgwchUnicodeRoot[MAX_PATH_LEN];
  876. PIMoniker pimkRoot;
  877. rgchRoot[0] = TEXT('\0');
  878. GetPathString(((PCBRFCASE)hbr)->bcdb.hpathDBFolder, rgchRoot, ARRAYSIZE(rgchRoot));
  879. #ifdef UNICODE
  880. hr = CreateFileMoniker(rgchRoot, &pimkRoot);
  881. #else
  882. /* Translate ANSI string into Unicode for OLE. */
  883. if (0 == MultiByteToWideChar(CP_ACP, 0, rgchRoot, -1, rgwchUnicodeRoot,
  884. ARRAY_ELEMENTS(rgwchUnicodeRoot)))
  885. {
  886. hr = MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
  887. }
  888. else
  889. {
  890. hr = CreateFileMoniker(rgwchUnicodeRoot, &pimkRoot);
  891. }
  892. #endif
  893. if (SUCCEEDED(hr))
  894. {
  895. ((PBRFCASE)hbr)->pimkRoot = pimkRoot;
  896. SET_FLAG(((PBRFCASE)hbr)->dwFlags, BR_FL_ROOT_MONIKER_VALID);
  897. TRACE_OUT((TEXT("GetBriefcaseRootMoniker(): Created briefcase root moniker %s."),
  898. rgchRoot));
  899. }
  900. }
  901. else
  902. hr = MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, ERROR_PATH_NOT_FOUND);
  903. }
  904. else
  905. hr = S_OK;
  906. if (SUCCEEDED(hr))
  907. *pimk = ((PCBRFCASE)hbr)->pimkRoot;
  908. ASSERT(FAILED(hr) ||
  909. IS_VALID_STRUCT_PTR(*pimk, CIMoniker));
  910. return(hr);
  911. }
  912. /*
  913. ** BeginExclusiveBriefcaseAccess()
  914. **
  915. **
  916. **
  917. ** Arguments:
  918. **
  919. ** Returns:
  920. **
  921. ** Side Effects: none
  922. */
  923. PUBLIC_CODE BOOL BeginExclusiveBriefcaseAccess(void)
  924. {
  925. return(EnterNonReentrantCriticalSection(&MnrcsBriefcase));
  926. }
  927. /*
  928. ** EndExclusiveBriefcaseAccess()
  929. **
  930. **
  931. **
  932. ** Arguments:
  933. **
  934. ** Returns:
  935. **
  936. ** Side Effects: none
  937. */
  938. PUBLIC_CODE void EndExclusiveBriefcaseAccess(void)
  939. {
  940. LeaveNonReentrantCriticalSection(&MnrcsBriefcase);
  941. return;
  942. }
  943. #ifdef DEBUG
  944. /*
  945. ** BriefcaseAccessIsExclusive()
  946. **
  947. **
  948. **
  949. ** Arguments:
  950. **
  951. ** Returns:
  952. **
  953. ** Side Effects: none
  954. */
  955. PUBLIC_CODE BOOL BriefcaseAccessIsExclusive(void)
  956. {
  957. return(NonReentrantCriticalSectionIsOwned(&MnrcsBriefcase));
  958. }
  959. #endif /* DEBUG */
  960. /*
  961. ** IsValidHBRFCASE()
  962. **
  963. **
  964. **
  965. ** Arguments:
  966. **
  967. ** Returns:
  968. **
  969. ** Side Effects: none
  970. */
  971. PUBLIC_CODE BOOL IsValidHBRFCASE(HBRFCASE hbr)
  972. {
  973. return(IS_VALID_STRUCT_PTR((PCBRFCASE)hbr, CBRFCASE));
  974. }
  975. /*
  976. ** WriteBriefcaseInfo()
  977. **
  978. **
  979. **
  980. ** Arguments:
  981. **
  982. ** Returns:
  983. **
  984. ** Side Effects: none
  985. */
  986. PUBLIC_CODE TWINRESULT WriteBriefcaseInfo(HCACHEDFILE hcf, HBRFCASE hbr)
  987. {
  988. TWINRESULT tr;
  989. DBBRFCASE dbbr;
  990. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  991. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  992. /* Set up briefcase database structure. */
  993. ASSERT(IS_VALID_HANDLE(((PCBRFCASE)hbr)->bcdb.hpathLastSavedDBFolder, PATH));
  994. dbbr.hpathLastSavedDBFolder = ((PCBRFCASE)hbr)->bcdb.hpathLastSavedDBFolder;
  995. /* Save briefcase database structure. */
  996. if (WriteToCachedFile(hcf, (PCVOID)&dbbr, sizeof(dbbr), NULL))
  997. {
  998. tr = TR_SUCCESS;
  999. TRACE_OUT((TEXT("WriteBriefcaseInfo(): Wrote last saved database folder %s."),
  1000. DebugGetPathString(dbbr.hpathLastSavedDBFolder)));
  1001. }
  1002. else
  1003. tr = TR_BRIEFCASE_WRITE_FAILED;
  1004. return(tr);
  1005. }
  1006. /*
  1007. ** ReadBriefcaseInfo()
  1008. **
  1009. **
  1010. **
  1011. ** Arguments:
  1012. **
  1013. ** Returns:
  1014. **
  1015. ** Side Effects: none
  1016. */
  1017. PUBLIC_CODE TWINRESULT ReadBriefcaseInfo(HCACHEDFILE hcf, HBRFCASE hbr,
  1018. HHANDLETRANS hhtFolderTrans)
  1019. {
  1020. TWINRESULT tr;
  1021. DBBRFCASE dbbr;
  1022. DWORD dwcbRead;
  1023. HPATH hpath;
  1024. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  1025. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  1026. ASSERT(IS_VALID_HANDLE(hhtFolderTrans, HANDLETRANS));
  1027. /* Read briefcase database structure. */
  1028. if ((ReadFromCachedFile(hcf, &dbbr, sizeof(dbbr), &dwcbRead) &&
  1029. dwcbRead == sizeof(dbbr)) &&
  1030. TranslateHandle(hhtFolderTrans, (HGENERIC)(dbbr.hpathLastSavedDBFolder),
  1031. (PHGENERIC)&hpath))
  1032. {
  1033. HPATH hpathLastSavedDBFolder;
  1034. /*
  1035. * Bump last saved database folder path's lock count in the briefcase's
  1036. * path list.
  1037. */
  1038. if (CopyPath(hpath, ((PCBRFCASE)hbr)->hpathlist, &hpathLastSavedDBFolder))
  1039. {
  1040. ((PBRFCASE)hbr)->bcdb.hpathLastSavedDBFolder = hpathLastSavedDBFolder;
  1041. tr = TR_SUCCESS;
  1042. TRACE_OUT((TEXT("ReadBriefcaseInfo(): Read last saved database folder %s."),
  1043. DebugGetPathString(((PBRFCASE)hbr)->bcdb.hpathLastSavedDBFolder)));
  1044. }
  1045. else
  1046. tr = TR_OUT_OF_MEMORY;
  1047. }
  1048. else
  1049. tr = TR_CORRUPT_BRIEFCASE;
  1050. return(tr);
  1051. }
  1052. /***************************** Exported Functions ****************************/
  1053. /******************************************************************************
  1054. @doc SYNCENGAPI
  1055. @api TWINRESULT | OpenBriefcase | Opens an existing briefcase database, or
  1056. creates a new briefcase.
  1057. @parm PCSTR | pcszPath | A pointer to a path string indicating the briefcase
  1058. database to be opened or created. This parameter is ignored unless the
  1059. OB_FL_OPEN_DATABASE flag is set in dwFlags.
  1060. @parm DWORD | dwInFlags | A bit mask of flags. This parameter may be any
  1061. combination of the following values:
  1062. OB_FL_OPEN_DATABASE - Open the briefcase database specified by pcszPath.
  1063. OB_FL_TRANSLATE_DB_FOLDER - Translate the folder where the briefcase
  1064. database was last saved to the folder where the briefcase database was
  1065. opened.
  1066. OB_FL_ALLOW_UI - Allow interaction with the user during briefcase
  1067. operations.
  1068. @parm HWND | hwndOwner | A handle to the parent window to be used when
  1069. requesting user interaction. This parameter is ignored if the OB_FL_ALLOW_UI
  1070. flag is clear.
  1071. @parm PHBRFCASE | phbr | A pointer to an HBRFCASE to be filled in with a
  1072. handle to the open briefcase. *phbr is only valid if TR_SUCCESS is returned.
  1073. @rdesc If the briefcase was opened or created successfully, TR_SUCCESS is
  1074. returned, and *phbr contains a handle to the open briefcase. Otherwise, the
  1075. briefcase was not opened or created successfully, the return value indicates
  1076. the error that occurred, and *phbr is undefined.
  1077. @comm If the OB_FL_OPEN_DATABASE flag is set in dwFlags, the database specified
  1078. by pcszPath is associated with the briefcase. If the database specified does
  1079. not exist, the database is created.<nl>
  1080. If the OB_FL_OPEN_DATABASE flag is clear in dwFlags, no persistent database is
  1081. associated with the briefcase. SaveBriefcase() will fail if called on a
  1082. briefcase with no associated database.<nl>
  1083. Once the caller is finished with the briefcase handle returned by
  1084. OpenBriefcase(), CloseBriefcase() should be called to release the briefcase.
  1085. SaveBriefcase() may be called before CloseBriefcase() to save the current
  1086. contents of the briefcase.
  1087. @xref SaveBriefcase CloseBriefcase
  1088. ******************************************************************************/
  1089. SYNCENGAPI TWINRESULT WINAPI OpenBriefcase(LPCTSTR pcszPath, DWORD dwInFlags,
  1090. HWND hwndOwner, PHBRFCASE phbr)
  1091. {
  1092. TWINRESULT tr;
  1093. if (BeginExclusiveBriefcaseAccess())
  1094. {
  1095. DebugEntry(OpenBriefcase);
  1096. #ifdef EXPV
  1097. /* Verify parameters. */
  1098. if (FLAGS_ARE_VALID(dwInFlags, ALL_OB_FLAGS) &&
  1099. IS_VALID_WRITE_PTR(phbr, HBRFCASE) &&
  1100. (IS_FLAG_CLEAR(dwInFlags, OB_FL_OPEN_DATABASE) ||
  1101. IS_VALID_STRING_PTR(pcszPath, CSTR)) &&
  1102. (IS_FLAG_CLEAR(dwInFlags, OB_FL_ALLOW_UI) ||
  1103. IS_VALID_HANDLE(hwndOwner, WND)))
  1104. #endif
  1105. {
  1106. PBRFCASE pbr;
  1107. if (CreateBriefcase(&pbr, dwInFlags, hwndOwner))
  1108. {
  1109. if (IS_FLAG_SET(dwInFlags, OB_FL_OPEN_DATABASE))
  1110. {
  1111. tr = OpenBriefcaseDatabase(pbr, pcszPath);
  1112. if (tr == TR_SUCCESS)
  1113. {
  1114. tr = MyReadDatabase(pbr, dwInFlags);
  1115. if (tr == TR_SUCCESS)
  1116. {
  1117. if (IS_FLAG_SET(dwInFlags, OB_FL_LIST_DATABASE))
  1118. EVAL(AddBriefcaseToSystem(pcszPath) == TR_SUCCESS);
  1119. *phbr = (HBRFCASE)pbr;
  1120. }
  1121. else
  1122. {
  1123. OPENBRIEFCASE_BAIL:
  1124. UnlinkBriefcase(pbr);
  1125. EVAL(DestroyBriefcase(pbr) == TR_SUCCESS);
  1126. }
  1127. }
  1128. else
  1129. goto OPENBRIEFCASE_BAIL;
  1130. }
  1131. else
  1132. {
  1133. *phbr = (HBRFCASE)pbr;
  1134. tr = TR_SUCCESS;
  1135. TRACE_OUT((TEXT("OpenBriefcase(): Opened briefcase %#lx with no associated database, by request."),
  1136. *phbr));
  1137. }
  1138. }
  1139. else
  1140. tr = TR_OUT_OF_MEMORY;
  1141. }
  1142. #ifdef EXPV
  1143. else
  1144. tr = TR_INVALID_PARAMETER;
  1145. #endif
  1146. DebugExitTWINRESULT(OpenBriefcase, tr);
  1147. EndExclusiveBriefcaseAccess();
  1148. }
  1149. else
  1150. tr = TR_REENTERED;
  1151. return(tr);
  1152. }
  1153. /******************************************************************************
  1154. @doc SYNCENGAPI
  1155. @api TWINRESULT | SaveBriefcase | Saves the contents of an open briefcase to a
  1156. briefcase database.
  1157. @parm HBRFCASE | hbr | A handle to the briefcase to be saved. This handle may
  1158. be obtained by calling OpenBriefcase() with a briefcase database path and with
  1159. the OB_FL_OPEN_DATABASE flag set. SaveBriefcase() will return
  1160. TR_INVALID_PARAMETER if called on a briefcase with no associated briefcase
  1161. database.
  1162. @rdesc If the contents of the briefcase was saved to the briefcase database
  1163. successfully, TR_SUCCESS is returned. Otherwise, the contents of the briefcase
  1164. was not saved to the briefcase database successfully, and the return value
  1165. indicates the error that occurred.
  1166. @xref OpenBriefcase CloseBriefcase
  1167. ******************************************************************************/
  1168. SYNCENGAPI TWINRESULT WINAPI SaveBriefcase(HBRFCASE hbr)
  1169. {
  1170. TWINRESULT tr;
  1171. if (BeginExclusiveBriefcaseAccess())
  1172. {
  1173. DebugEntry(SaveBriefcase);
  1174. #ifdef EXPV
  1175. /* Verify parameters. */
  1176. if (IS_VALID_HANDLE(hbr, BRFCASE) &&
  1177. IS_FLAG_SET(((PBRFCASE)hbr)->dwFlags, BR_FL_DATABASE_OPENED))
  1178. #endif
  1179. {
  1180. ((PBRFCASE)hbr)->bcdb.hpathLastSavedDBFolder = ((PCBRFCASE)hbr)->bcdb.hpathDBFolder;
  1181. tr = MyWriteDatabase((PBRFCASE)hbr);
  1182. ((PBRFCASE)hbr)->bcdb.hpathLastSavedDBFolder = NULL;
  1183. }
  1184. #ifdef EXPV
  1185. else
  1186. tr = TR_INVALID_PARAMETER;
  1187. #endif
  1188. DebugExitTWINRESULT(SaveBriefcase, tr);
  1189. EndExclusiveBriefcaseAccess();
  1190. }
  1191. else
  1192. tr = TR_REENTERED;
  1193. return(tr);
  1194. }
  1195. /******************************************************************************
  1196. @doc SYNCENGAPI
  1197. @api TWINRESULT | CloseBriefcase | Closes an open briefcase.
  1198. @parm HBRFCASE | hbr | A handle to the briefcase to be closed. This handle may
  1199. be obtained by calling OpenBriefcase().
  1200. @rdesc If the briefcase was closed successfully, TR_SUCCESS is returned.
  1201. Otherwise, the briefcase was not closed successfully, and the return value
  1202. indicates the error that occurred.
  1203. @xref OpenBriefcase SaveBriefcase
  1204. ******************************************************************************/
  1205. SYNCENGAPI TWINRESULT WINAPI CloseBriefcase(HBRFCASE hbr)
  1206. {
  1207. TWINRESULT tr;
  1208. if (BeginExclusiveBriefcaseAccess())
  1209. {
  1210. DebugEntry(CloseBriefcase);
  1211. #ifdef EXPV
  1212. /* Verify parameters. */
  1213. if (IS_VALID_HANDLE(hbr, BRFCASE))
  1214. #endif
  1215. {
  1216. UnlinkBriefcase((PBRFCASE)hbr);
  1217. tr = DestroyBriefcase((PBRFCASE)hbr);
  1218. }
  1219. #ifdef EXPV
  1220. else
  1221. tr = TR_INVALID_PARAMETER;
  1222. #endif
  1223. DebugExitTWINRESULT(CloseBriefcase, tr);
  1224. EndExclusiveBriefcaseAccess();
  1225. }
  1226. else
  1227. tr = TR_REENTERED;
  1228. return(tr);
  1229. }
  1230. /******************************************************************************
  1231. @doc SYNCENGAPI
  1232. @api TWINRESULT | DeleteBriefcase | Deletes a closed briefcase's database file.
  1233. @parm PCSTR | pcszPath | A pointer to a path string indicating the briefcase
  1234. database that is to be deleted.
  1235. @rdesc If the briefcase database was deleted successfully, TR_SUCCESS is
  1236. returned. Otherwise, the briefcase database was not deleted successfully, and
  1237. the return value indicates the error that occurred.
  1238. @comm Clients should call DeleteBriefcase() instead of DeleteFile() to delete
  1239. an unwanted briefcase database so that the the synchronization engine may
  1240. verify that the given briefcase database is not in use before deleting it.
  1241. @xref OpenBriefcase SaveBriefcase CloseBriefcase
  1242. ******************************************************************************/
  1243. SYNCENGAPI TWINRESULT WINAPI DeleteBriefcase(LPCTSTR pcszPath)
  1244. {
  1245. TWINRESULT tr;
  1246. if (BeginExclusiveBriefcaseAccess())
  1247. {
  1248. DebugEntry(DeleteBriefcase);
  1249. #ifdef EXPV
  1250. /* Verify parameters. */
  1251. if (IS_VALID_STRING_PTR(pcszPath, CSTR))
  1252. #endif
  1253. {
  1254. /*
  1255. * RAIDRAID: (16275) Check database header here to verify that the
  1256. * file is a briefcase database file.
  1257. */
  1258. if (DeleteFile(pcszPath))
  1259. {
  1260. EVAL(RemoveBriefcaseFromSystem(pcszPath) == TR_SUCCESS);
  1261. tr = TR_SUCCESS;
  1262. }
  1263. else
  1264. {
  1265. switch (GetLastError())
  1266. {
  1267. /* Returned when file opened by local machine. */
  1268. case ERROR_SHARING_VIOLATION:
  1269. tr = TR_BRIEFCASE_LOCKED;
  1270. break;
  1271. default:
  1272. tr = TR_BRIEFCASE_OPEN_FAILED;
  1273. break;
  1274. }
  1275. }
  1276. }
  1277. #ifdef EXPV
  1278. else
  1279. tr = TR_INVALID_PARAMETER;
  1280. #endif
  1281. DebugExitTWINRESULT(DeleteBriefcase, tr);
  1282. EndExclusiveBriefcaseAccess();
  1283. }
  1284. else
  1285. tr = TR_REENTERED;
  1286. return(tr);
  1287. }
  1288. /******************************************************************************
  1289. @doc SYNCENGAPI
  1290. @api TWINRESULT | GetOpenBriefcaseInfo | Describes an open briefcase.
  1291. @parm HBRFCASE | hbr | A handle to the open briefcase to be described.
  1292. @parm POPENBRFCASEINFO | pobri | A pointer to an OPENBRFCASEINFO to be filled
  1293. in with information describing the open briefcase. The ulSize field of the
  1294. OPENBRFCASEINFO structure should be filled in with sizeof(OPENBRFCASEINFO)
  1295. before calling GetOpenBriefcaseInfo().
  1296. @rdesc If the open briefcase was described successfully, TR_SUCCESS is
  1297. returned. Otherwise, the open briefcase was not described successfully, and
  1298. the return value indicates the error that occurred.
  1299. ******************************************************************************/
  1300. SYNCENGAPI TWINRESULT WINAPI GetOpenBriefcaseInfo(HBRFCASE hbr,
  1301. POPENBRFCASEINFO pobri)
  1302. {
  1303. TWINRESULT tr;
  1304. if (BeginExclusiveBriefcaseAccess())
  1305. {
  1306. DebugEntry(GetBriefcaseInfo);
  1307. #ifdef EXPV
  1308. /* Verify parameters. */
  1309. if (IS_VALID_HANDLE(hbr, BRFCASE) &&
  1310. IS_VALID_WRITE_PTR(pobri, OPENBRFCASEINFO) &&
  1311. EVAL(pobri->ulSize == sizeof(*pobri)))
  1312. #endif
  1313. {
  1314. pobri->dwFlags = (((PBRFCASE)hbr)->dwFlags & ~ALL_BR_FLAGS);
  1315. if (IS_FLAG_SET(((PBRFCASE)hbr)->dwFlags, OB_FL_ALLOW_UI))
  1316. pobri->hwndOwner = ((PBRFCASE)hbr)->hwndOwner;
  1317. else
  1318. {
  1319. pobri->hwndOwner = NULL;
  1320. WARNING_OUT((TEXT("GetBriefcaseInfo(): Briefcase %#lx has no associated parent window."),
  1321. hbr));
  1322. }
  1323. if (IS_FLAG_SET(((PBRFCASE)hbr)->dwFlags, BR_FL_DATABASE_OPENED))
  1324. {
  1325. pobri->hvid = (HVOLUMEID)(((PCBRFCASE)hbr)->bcdb.hpathDBFolder);
  1326. GetPathString(((PCBRFCASE)hbr)->bcdb.hpathDBFolder,
  1327. pobri->rgchDatabasePath, ARRAYSIZE(pobri->rgchDatabasePath));
  1328. CatPath(pobri->rgchDatabasePath, ((PCBRFCASE)hbr)->bcdb.pszDBName,
  1329. ARRAYSIZE(pobri->rgchDatabasePath));
  1330. }
  1331. else
  1332. {
  1333. pobri->hvid = NULL;
  1334. pobri->rgchDatabasePath[0] = TEXT('\0');
  1335. WARNING_OUT((TEXT("GetBriefcaseInfo(): Briefcase %#lx has no associated database."),
  1336. hbr));
  1337. }
  1338. tr = TR_SUCCESS;
  1339. }
  1340. #ifdef EXPV
  1341. else
  1342. tr = TR_INVALID_PARAMETER;
  1343. #endif
  1344. ASSERT(tr != TR_SUCCESS ||
  1345. IS_VALID_STRUCT_PTR(pobri, COPENBRFCASEINFO));
  1346. DebugExitTWINRESULT(GetBriefcaseInfo, tr);
  1347. EndExclusiveBriefcaseAccess();
  1348. }
  1349. else
  1350. tr = TR_REENTERED;
  1351. return(tr);
  1352. }
  1353. /******************************************************************************
  1354. @doc SYNCENGAPI
  1355. @api TWINRESULT | ClearBriefcaseCache | Wipes out cached information in an open
  1356. briefcase.
  1357. @parm HBRFCASE | hbr | A handle to the open briefcase whose cached information
  1358. is to be cleared.
  1359. @rdesc If the open briefcase's cached information was cleared successfully,
  1360. TR_SUCCESS is returned. Otherwise, the briefcase's cached information was not
  1361. cleared successfully, and the return value indicates the error that occurred.
  1362. ******************************************************************************/
  1363. SYNCENGAPI TWINRESULT WINAPI ClearBriefcaseCache(HBRFCASE hbr)
  1364. {
  1365. TWINRESULT tr;
  1366. if (BeginExclusiveBriefcaseAccess())
  1367. {
  1368. DebugEntry(ClearBriefcaseCache);
  1369. #ifdef EXPV
  1370. /* Verify parameters. */
  1371. if (IS_VALID_HANDLE(hbr, BRFCASE))
  1372. #endif
  1373. {
  1374. ClearPathListInfo(((PBRFCASE)hbr)->hpathlist);
  1375. tr = TR_SUCCESS;
  1376. }
  1377. #ifdef EXPV
  1378. else
  1379. tr = TR_INVALID_PARAMETER;
  1380. #endif
  1381. DebugExitTWINRESULT(ClearBriefcaseCache, tr);
  1382. EndExclusiveBriefcaseAccess();
  1383. }
  1384. else
  1385. tr = TR_REENTERED;
  1386. return(tr);
  1387. }