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.

472 lines
10 KiB

  1. /*
  2. * db.c - Twin database module.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. #include "stub.h"
  9. /* Constants
  10. ************/
  11. /* database header magic id string */
  12. #define MAGIC_HEADER "DDSH\x02\x05\x01\x14"
  13. /* length of MAGIC_HEADER (no null terminator) */
  14. #define MAGIC_HEADER_LEN (8)
  15. /* Types
  16. ********/
  17. typedef struct _dbheader
  18. {
  19. BYTE rgbyteMagic[MAGIC_HEADER_LEN];
  20. DWORD dwcbHeaderLen;
  21. DWORD dwMajorVer;
  22. DWORD dwMinorVer;
  23. }
  24. DBHEADER;
  25. DECLARE_STANDARD_TYPES(DBHEADER);
  26. /***************************** Private Functions *****************************/
  27. /* Module Prototypes
  28. ********************/
  29. PRIVATE_CODE TWINRESULT WriteDBHeader(HCACHEDFILE, PDBHEADER);
  30. PRIVATE_CODE TWINRESULT ReadDBHeader(HCACHEDFILE, PDBHEADER);
  31. PRIVATE_CODE TWINRESULT CheckDBHeader(PCDBHEADER);
  32. PRIVATE_CODE TWINRESULT WriteTwinInfo(HCACHEDFILE, HBRFCASE);
  33. PRIVATE_CODE TWINRESULT ReadTwinInfo(HCACHEDFILE, HBRFCASE, PCDBVERSION);
  34. #ifdef VSTF
  35. PRIVATE_CODE BOOL IsValidPCDBHEADER(PCDBHEADER);
  36. #endif
  37. /*
  38. ** WriteDBHeader()
  39. **
  40. **
  41. **
  42. ** Arguments:
  43. **
  44. ** Returns: TWINRESULT
  45. **
  46. ** Side Effects: none
  47. */
  48. PRIVATE_CODE TWINRESULT WriteDBHeader(HCACHEDFILE hcf, PDBHEADER pdbh)
  49. {
  50. TWINRESULT tr;
  51. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  52. ASSERT(IS_VALID_STRUCT_PTR(pdbh, CDBHEADER));
  53. if (WriteToCachedFile(hcf, (PCVOID)pdbh, sizeof(*pdbh), NULL))
  54. tr = TR_SUCCESS;
  55. else
  56. tr = TR_BRIEFCASE_WRITE_FAILED;
  57. return(tr);
  58. }
  59. /*
  60. ** ReadDBHeader()
  61. **
  62. **
  63. **
  64. ** Arguments:
  65. **
  66. ** Returns: TWINRESULT
  67. **
  68. ** Side Effects: none
  69. */
  70. PRIVATE_CODE TWINRESULT ReadDBHeader(HCACHEDFILE hcf, PDBHEADER pdbh)
  71. {
  72. TWINRESULT tr;
  73. DWORD dwcbRead;
  74. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  75. ASSERT(IS_VALID_WRITE_PTR(pdbh, DBHEADER));
  76. if (ReadFromCachedFile(hcf, pdbh, sizeof(*pdbh), &dwcbRead) &&
  77. dwcbRead == sizeof(*pdbh))
  78. tr = CheckDBHeader(pdbh);
  79. else
  80. tr = TR_CORRUPT_BRIEFCASE;
  81. return(tr);
  82. }
  83. /*
  84. ** CheckDBHeader()
  85. **
  86. **
  87. **
  88. ** Arguments:
  89. **
  90. ** Returns: TWINRESULT
  91. **
  92. ** Side Effects: none
  93. */
  94. PRIVATE_CODE TWINRESULT CheckDBHeader(PCDBHEADER pcdbh)
  95. {
  96. TWINRESULT tr = TR_CORRUPT_BRIEFCASE;
  97. ASSERT(IS_VALID_READ_PTR(pcdbh, CDBHEADER));
  98. if (MyMemComp(pcdbh->rgbyteMagic, MAGIC_HEADER, sizeof(pcdbh->rgbyteMagic)) == CR_EQUAL)
  99. {
  100. /* Treat older databases as corrupt. Support M8 databases. */
  101. if (pcdbh->dwMajorVer == HEADER_MAJOR_VER &&
  102. (pcdbh->dwMinorVer == HEADER_MINOR_VER || pcdbh->dwMinorVer == HEADER_M8_MINOR_VER))
  103. {
  104. if (pcdbh->dwcbHeaderLen == sizeof(*pcdbh))
  105. tr = TR_SUCCESS;
  106. }
  107. else if (pcdbh->dwMajorVer > HEADER_MAJOR_VER ||
  108. (pcdbh->dwMajorVer == HEADER_MAJOR_VER &&
  109. pcdbh->dwMinorVer > HEADER_MINOR_VER))
  110. {
  111. tr = TR_NEWER_BRIEFCASE;
  112. WARNING_OUT((TEXT("CheckDBHeader(): Newer database version %lu.%lu."),
  113. pcdbh->dwMajorVer,
  114. pcdbh->dwMinorVer));
  115. }
  116. else
  117. {
  118. tr = TR_CORRUPT_BRIEFCASE;
  119. WARNING_OUT((TEXT("CheckDBHeader(): Treating old database version %lu.%lu as corrupt. Current database version is %lu.%lu."),
  120. pcdbh->dwMajorVer,
  121. pcdbh->dwMinorVer,
  122. (DWORD)HEADER_MAJOR_VER,
  123. (DWORD)HEADER_MINOR_VER));
  124. }
  125. }
  126. return(tr);
  127. }
  128. /*
  129. ** WriteTwinInfo()
  130. **
  131. **
  132. **
  133. ** Arguments:
  134. **
  135. ** Returns: TWINRESULT
  136. **
  137. ** Side Effects: none
  138. */
  139. PRIVATE_CODE TWINRESULT WriteTwinInfo(HCACHEDFILE hcf, HBRFCASE hbr)
  140. {
  141. TWINRESULT tr = TR_BRIEFCASE_WRITE_FAILED;
  142. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  143. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  144. tr = WritePathList(hcf, GetBriefcasePathList(hbr));
  145. if (tr == TR_SUCCESS)
  146. {
  147. tr = WriteBriefcaseInfo(hcf, hbr);
  148. if (tr == TR_SUCCESS)
  149. {
  150. tr = WriteStringTable(hcf, GetBriefcaseNameStringTable(hbr));
  151. if (tr == TR_SUCCESS)
  152. {
  153. tr = WriteTwinFamilies(hcf, GetBriefcaseTwinFamilyPtrArray(hbr));
  154. if (tr == TR_SUCCESS)
  155. tr = WriteFolderPairList(hcf, GetBriefcaseFolderPairPtrArray(hbr));
  156. }
  157. }
  158. }
  159. return(tr);
  160. }
  161. /*
  162. ** ReadTwinInfo()
  163. **
  164. **
  165. **
  166. ** Arguments:
  167. **
  168. ** Returns: TWINRESULT
  169. **
  170. ** Side Effects: none
  171. */
  172. PRIVATE_CODE TWINRESULT ReadTwinInfo(HCACHEDFILE hcf, HBRFCASE hbr,
  173. PCDBVERSION pcdbver)
  174. {
  175. TWINRESULT tr;
  176. HHANDLETRANS hhtPathTrans;
  177. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  178. ASSERT(IS_VALID_READ_PTR(pcdbver, DBVERSION));
  179. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  180. tr = ReadPathList(hcf, GetBriefcasePathList(hbr), &hhtPathTrans);
  181. if (tr == TR_SUCCESS)
  182. {
  183. tr = ReadBriefcaseInfo(hcf, hbr, hhtPathTrans);
  184. if (tr == TR_SUCCESS)
  185. {
  186. HHANDLETRANS hhtNameTrans;
  187. tr = ReadStringTable(hcf, GetBriefcaseNameStringTable(hbr), &hhtNameTrans);
  188. if (tr == TR_SUCCESS)
  189. {
  190. tr = ReadTwinFamilies(hcf, hbr, pcdbver, hhtPathTrans, hhtNameTrans);
  191. if (tr == TR_SUCCESS)
  192. tr = ReadFolderPairList(hcf, hbr, hhtPathTrans, hhtNameTrans);
  193. DestroyHandleTranslator(hhtNameTrans);
  194. }
  195. }
  196. DestroyHandleTranslator(hhtPathTrans);
  197. }
  198. return(tr);
  199. }
  200. #ifdef VSTF
  201. /*
  202. ** IsValidPCDBHEADER()
  203. **
  204. **
  205. **
  206. ** Arguments:
  207. **
  208. ** Returns:
  209. **
  210. ** Side Effects: none
  211. */
  212. PRIVATE_CODE BOOL IsValidPCDBHEADER(PCDBHEADER pcdbh)
  213. {
  214. BOOL bResult;
  215. if (IS_VALID_READ_PTR(pcdbh, CDBHEADER) &&
  216. EVAL(MyMemComp(pcdbh->rgbyteMagic, MAGIC_HEADER, sizeof(pcbdh->rgbyteMagic)) == CR_EQUAL) &&
  217. EVAL(pcdbh->dwcbHeaderLen == sizeof(*pcdbh)) &&
  218. EVAL(pcdbh->dwMajorVer == HEADER_MAJOR_VER) &&
  219. EVAL(pcdbh->dwMinorVer == HEADER_MINOR_VER || pcdbh->dwMinorVer == HEADER_M8_MINOR_VER))
  220. bResult = TRUE;
  221. else
  222. bResult = FALSE;
  223. return(bResult);
  224. }
  225. #endif
  226. /****************************** Public Functions *****************************/
  227. /*
  228. ** WriteTwinDatabase()
  229. **
  230. **
  231. **
  232. ** Arguments:
  233. **
  234. ** Returns:
  235. **
  236. ** Side Effects: none
  237. */
  238. PUBLIC_CODE TWINRESULT WriteTwinDatabase(HCACHEDFILE hcf, HBRFCASE hbr)
  239. {
  240. TWINRESULT tr;
  241. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  242. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  243. if (! SeekInCachedFile(hcf, 0, FILE_BEGIN))
  244. {
  245. DBHEADER dbh;
  246. /* Set up database header. */
  247. CopyMemory(dbh.rgbyteMagic, MAGIC_HEADER, sizeof(dbh.rgbyteMagic));
  248. dbh.dwcbHeaderLen = sizeof(dbh);
  249. dbh.dwMajorVer = HEADER_MAJOR_VER;
  250. dbh.dwMinorVer = HEADER_MINOR_VER;
  251. tr = WriteDBHeader(hcf, &dbh);
  252. if (tr == TR_SUCCESS)
  253. {
  254. TRACE_OUT((TEXT("WriteTwinDatabase(): Wrote database header version %lu.%lu."),
  255. dbh.dwMajorVer,
  256. dbh.dwMinorVer));
  257. tr = WriteTwinInfo(hcf, hbr);
  258. if (tr == TR_SUCCESS && ! SetEndOfCachedFile(hcf))
  259. tr = TR_BRIEFCASE_WRITE_FAILED;
  260. }
  261. }
  262. else
  263. tr = TR_BRIEFCASE_WRITE_FAILED;
  264. return(tr);
  265. }
  266. /*
  267. ** ReadTwinDatabase()
  268. **
  269. **
  270. **
  271. ** Arguments:
  272. **
  273. ** Returns:
  274. **
  275. ** Side Effects: none
  276. */
  277. PUBLIC_CODE TWINRESULT ReadTwinDatabase(HBRFCASE hbr, HCACHEDFILE hcf)
  278. {
  279. TWINRESULT tr;
  280. ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
  281. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  282. if (! SeekInCachedFile(hcf, 0, FILE_BEGIN))
  283. {
  284. DBHEADER dbh;
  285. tr = ReadDBHeader(hcf, &dbh);
  286. if (tr == TR_SUCCESS)
  287. {
  288. TRACE_OUT((TEXT("ReadTwinDatabase(): Read database header version %lu.%lu."),
  289. dbh.dwMajorVer,
  290. dbh.dwMinorVer));
  291. tr = ReadTwinInfo(hcf, hbr, (PCDBVERSION)&dbh.dwMajorVer);
  292. if (tr == TR_SUCCESS)
  293. ASSERT(GetCachedFilePointerPosition(hcf) == GetCachedFileSize(hcf));
  294. }
  295. }
  296. else
  297. tr = TR_BRIEFCASE_READ_FAILED;
  298. return(tr);
  299. }
  300. /*
  301. ** WriteDBSegmentHeader()
  302. **
  303. **
  304. **
  305. ** Arguments:
  306. **
  307. ** Returns: TWINRESULT
  308. **
  309. ** Side Effects: none
  310. */
  311. PUBLIC_CODE TWINRESULT WriteDBSegmentHeader(HCACHEDFILE hcf,
  312. LONG lcbDBSegmentHeaderOffset,
  313. PCVOID pcvSegmentHeader,
  314. UINT ucbSegmentHeaderLen)
  315. {
  316. TWINRESULT tr;
  317. DWORD dwcbStartOffset;
  318. ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
  319. ASSERT(lcbDBSegmentHeaderOffset >= 0);
  320. ASSERT(ucbSegmentHeaderLen > 0);
  321. ASSERT(IS_VALID_READ_BUFFER_PTR(pcvSegmentHeader, BYTE, ucbSegmentHeaderLen));
  322. dwcbStartOffset = GetCachedFilePointerPosition(hcf);
  323. if (dwcbStartOffset != INVALID_SEEK_POSITION &&
  324. SeekInCachedFile(hcf, lcbDBSegmentHeaderOffset, SEEK_SET) != INVALID_SEEK_POSITION &&
  325. WriteToCachedFile(hcf, pcvSegmentHeader, ucbSegmentHeaderLen, NULL) &&
  326. SeekInCachedFile(hcf, dwcbStartOffset, SEEK_SET) != INVALID_SEEK_POSITION)
  327. tr = TR_SUCCESS;
  328. else
  329. tr = TR_BRIEFCASE_WRITE_FAILED;
  330. return(tr);
  331. }
  332. /*
  333. ** TranslateFCRESULTToTWINRESULT()
  334. **
  335. **
  336. **
  337. ** Arguments:
  338. **
  339. ** Returns:
  340. **
  341. ** Side Effects: none
  342. */
  343. PUBLIC_CODE TWINRESULT TranslateFCRESULTToTWINRESULT(FCRESULT fcr)
  344. {
  345. TWINRESULT tr;
  346. switch (fcr)
  347. {
  348. case FCR_SUCCESS:
  349. tr = TR_SUCCESS;
  350. break;
  351. case FCR_OUT_OF_MEMORY:
  352. tr = TR_OUT_OF_MEMORY;
  353. break;
  354. case FCR_OPEN_FAILED:
  355. tr = TR_BRIEFCASE_OPEN_FAILED;
  356. break;
  357. case FCR_CREATE_FAILED:
  358. tr = TR_BRIEFCASE_OPEN_FAILED;
  359. break;
  360. case FCR_WRITE_FAILED:
  361. tr = TR_BRIEFCASE_WRITE_FAILED;
  362. break;
  363. default:
  364. ASSERT(fcr == FCR_FILE_LOCKED);
  365. tr = TR_BRIEFCASE_LOCKED;
  366. break;
  367. }
  368. return(tr);
  369. }