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.

309 lines
9.5 KiB

  1. // --------------------------------------------------------------------------------
  2. // oe5beta1.cpp
  3. // --------------------------------------------------------------------------------
  4. #include "pch.hxx"
  5. #include "utility.h"
  6. #include "migrate.h"
  7. #include "migerror.h"
  8. #include "structs.h"
  9. #include "resource.h"
  10. // --------------------------------------------------------------------------------
  11. // DowngradeProcessFileListV5B1
  12. // --------------------------------------------------------------------------------
  13. HRESULT DowngradeProcessFileListV5B1(LPFILEINFO pHead, LPDWORD pcMax, LPDWORD pcbNeeded)
  14. {
  15. // Locals
  16. HRESULT hr=S_OK;
  17. MEMORYFILE File={0};
  18. LPFILEINFO pCurrent;
  19. LPTABLEHEADERV5B1 pHeader;
  20. // Trace
  21. TraceCall("DowngradeProcessFileListV5B1");
  22. // Invalid Arg
  23. Assert(pHead);
  24. // Init
  25. *pcMax = 0;
  26. *pcbNeeded = 0;
  27. // Loop
  28. for (pCurrent=pHead; pCurrent!=NULL; pCurrent=pCurrent->pNext)
  29. {
  30. // Get the File Header
  31. hr = OpenMemoryFile(pCurrent->szFilePath, &File);
  32. // Failure ?
  33. if (FAILED(hr))
  34. {
  35. // Don't Migrate
  36. pCurrent->fMigrate = FALSE;
  37. // Set hrMigrate
  38. pCurrent->hrMigrate = hr;
  39. // Reset hr
  40. hr = S_OK;
  41. // Get the LastError
  42. pCurrent->dwLastError = GetLastError();
  43. // Goto Next
  44. goto NextFile;
  45. }
  46. // Don't need to migrate the file
  47. if (FILE_IS_NEWS_MESSAGES != pCurrent->tyFile && FILE_IS_IMAP_MESSAGES != pCurrent->tyFile)
  48. {
  49. // Not a file that should be migrate
  50. pCurrent->fMigrate = FALSE;
  51. // Set hrMigrate
  52. pCurrent->hrMigrate = S_OK;
  53. // Goto Next
  54. goto NextFile;
  55. }
  56. // De-Ref the header
  57. pHeader = (LPTABLEHEADERV5B1)File.pView;
  58. // Check the Signature...
  59. if (File.cbSize < sizeof(TABLEHEADERV5B1) || OBJECTDB_SIGNATURE != pHeader->dwSignature || OBJECTDB_VERSION_PRE_V5 != pHeader->wMajorVersion)
  60. {
  61. // Not a file that should be migrate
  62. pCurrent->fMigrate = FALSE;
  63. // Set hrMigrate
  64. pCurrent->hrMigrate = MIGRATE_E_BADVERSION;
  65. // Goto Next
  66. goto NextFile;
  67. }
  68. // Save the Number of record
  69. pCurrent->cRecords = pHeader->cRecords;
  70. // Initialize counters
  71. InitializeCounters(&File, pCurrent, pcMax, pcbNeeded, FALSE);
  72. // Yes, Migrate
  73. pCurrent->fMigrate = TRUE;
  74. NextFile:
  75. // Close the File
  76. CloseMemoryFile(&File);
  77. }
  78. // Done
  79. return hr;
  80. }
  81. //--------------------------------------------------------------------------
  82. // DowngradeRecordV5B1
  83. //--------------------------------------------------------------------------
  84. HRESULT DowngradeRecordV5B1(MIGRATETOTYPE tyMigrate, LPMEMORYFILE pFile,
  85. LPCHAINNODEV5B1 pNode)
  86. {
  87. // Locals
  88. HRESULT hr=S_OK;
  89. DWORD cbRecord=0;
  90. LPBYTE pbData;
  91. LPRECORDBLOCKV5B1 pRecord;
  92. // Trace
  93. TraceCall("DowngradeRecordV5B1");
  94. // Invalid
  95. if (pNode->faRecord + sizeof(RECORDBLOCKV5B1) + pNode->cbRecord > pFile->cbSize || 0 == pNode->cbRecord)
  96. return TraceResult(MIGRATE_E_OUTOFRANGEADDRESS);
  97. // Access the Record
  98. pRecord = (LPRECORDBLOCKV5B1((LPBYTE)pFile->pView + pNode->faRecord));
  99. // Cast the datablock
  100. pbData = ((LPBYTE)pRecord + sizeof(RECORDBLOCKV5B1));
  101. // Lets read the fields so that I can re-compute the records V2 length...
  102. cbRecord += sizeof(DWORD); // dwMsgId
  103. cbRecord += sizeof(DWORD); // dwFlags
  104. cbRecord += sizeof(FILETIME); // ftSent
  105. cbRecord += sizeof(DWORD); // cLines
  106. cbRecord += sizeof(DWORD); // faStream
  107. cbRecord += sizeof(DWORD); // cbArticle
  108. cbRecord += sizeof(FILETIME); // ftDownloaded
  109. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszMessageId
  110. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszSubject;
  111. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszFromHeader;
  112. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszReferences;
  113. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszXref;
  114. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszServer;
  115. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszDisplayFrom;
  116. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszEmailFrom;
  117. // Going to V4 ?
  118. if (DOWNGRADE_V5B1_TO_V4 == tyMigrate && cbRecord < pNode->cbRecord)
  119. {
  120. cbRecord += sizeof(WORD); // wLanguage
  121. cbRecord += sizeof(WORD); // wReserved
  122. cbRecord += sizeof(DWORD); // cbMessage
  123. cbRecord += sizeof(FILETIME); // ftReceived
  124. cbRecord += (lstrlen((LPSTR)(pbData + cbRecord)) + 1); // pszDisplayTo;
  125. }
  126. // Add on Reserved
  127. cbRecord += (40 + sizeof(RECORDBLOCKV5B1));
  128. // Store the Size
  129. pRecord->cbRecord = cbRecord;
  130. // Update the Node
  131. pNode->cbRecord = cbRecord;
  132. // Done
  133. return hr;
  134. }
  135. //--------------------------------------------------------------------------
  136. // DowngradeIndexV5B1
  137. //--------------------------------------------------------------------------
  138. HRESULT DowngradeIndexV5B1(MIGRATETOTYPE tyMigrate, LPMEMORYFILE pFile,
  139. LPFILEINFO pInfo, LPPROGRESSINFO pProgress, DWORD faChain)
  140. {
  141. // Locals
  142. HRESULT hr=S_OK;
  143. LONG i;
  144. LPCHAINBLOCKV5B1 pChain;
  145. LPTABLEHEADERV5B1 pHeader;
  146. // Trace
  147. TraceCall("DowngradeIndexV5B1");
  148. // De-Ref the header
  149. pHeader = (LPTABLEHEADERV5B1)pFile->pView;
  150. // Nothing to validate
  151. if (0 == faChain)
  152. return S_OK;
  153. // Out-of-bounds
  154. if (faChain + CB_CHAIN_BLOCKV5B1 > pFile->cbSize)
  155. return TraceResult(MIGRATE_E_OUTOFRANGEADDRESS);
  156. // De-ref the block
  157. pChain = (LPCHAINBLOCKV5B1)((LPBYTE)pFile->pView + faChain);
  158. // Out-of-Bounds
  159. if (pChain->faStart != faChain)
  160. return TraceResult(MIGRATE_E_BADCHAINSIGNATURE);
  161. // Too many nodes
  162. if (pChain->cNodes > BTREE_ORDER)
  163. return TraceResult(MIGRATE_E_TOOMANYCHAINNODES);
  164. // Validate Minimum Filled Constraint
  165. if (pChain->cNodes < BTREE_MIN_CAP && pChain->faStart != pHeader->faRootChain)
  166. return TraceResult(MIGRATE_E_BADMINCAPACITY);
  167. // Go to the left
  168. IF_FAILEXIT(hr = DowngradeIndexV5B1(tyMigrate, pFile, pInfo, pProgress, pChain->faLeftChain));
  169. // Loop throug right chains
  170. for (i=0; i<pChain->cNodes; i++)
  171. {
  172. // Bump Progress
  173. IncrementProgress(pProgress, pInfo);
  174. /// Downgrad this record
  175. IF_FAILEXIT(hr = DowngradeRecordV5B1(tyMigrate, pFile, &pChain->rgNode[i]));
  176. // Validate the Right Chain
  177. IF_FAILEXIT(hr = DowngradeIndexV5B1(tyMigrate, pFile, pInfo, pProgress, pChain->rgNode[i].faRightChain));
  178. }
  179. exit:
  180. // Done
  181. return hr;
  182. }
  183. // --------------------------------------------------------------------------------
  184. // DowngradeFileV5B1
  185. // --------------------------------------------------------------------------------
  186. HRESULT DowngradeFileV5B1(MIGRATETOTYPE tyMigrate, LPFILEINFO pInfo,
  187. LPPROGRESSINFO pProgress)
  188. {
  189. // Locals
  190. HRESULT hr=S_OK;
  191. MEMORYFILE File={0};
  192. LPTABLEHEADERV5B1 pHeader;
  193. // Trace
  194. TraceCall("DowngradeFileV5B1");
  195. // Get the File Header
  196. IF_FAILEXIT(hr = OpenMemoryFile(pInfo->szFilePath, &File));
  197. // De-Ref the header
  198. pHeader = (LPTABLEHEADERV5B1)File.pView;
  199. // Recurse Through the Index
  200. IF_FAILEXIT(hr = DowngradeIndexV5B1(tyMigrate, &File, pInfo, pProgress, pHeader->faRootChain));
  201. exit:
  202. // Done
  203. return hr;
  204. }
  205. // --------------------------------------------------------------------------------
  206. // DowngradeV5B1
  207. // --------------------------------------------------------------------------------
  208. HRESULT DowngradeV5B1(MIGRATETOTYPE tyMigrate, LPCSTR pszStoreRoot,
  209. LPPROGRESSINFO pProgress, LPFILEINFO *ppHeadFile)
  210. {
  211. // Locals
  212. HRESULT hr=S_OK;
  213. ENUMFILEINFO EnumInfo={0};
  214. LPFILEINFO pCurrent;
  215. DWORD cbNeeded;
  216. // Trace
  217. TraceCall("DowngradeV5B1");
  218. // Setup the EnumFile Info
  219. EnumInfo.pszExt = ".nch";
  220. EnumInfo.pszFoldFile = "folders.nch";
  221. EnumInfo.pszUidlFile = "pop3uidl.dat";
  222. // Initialize
  223. *ppHeadFile = NULL;
  224. // Enumerate All ODB files in szStoreRoot...
  225. IF_FAILEXIT(hr = EnumerateStoreFiles(pszStoreRoot, DIR_IS_ROOT, NULL, &EnumInfo, ppHeadFile));
  226. // Compute some Counts, and validate that the files are valid to migrate...
  227. IF_FAILEXIT(hr = DowngradeProcessFileListV5B1(*ppHeadFile, &pProgress->cMax, &cbNeeded));
  228. // Loop through the files and migrate each one
  229. for (pCurrent=*ppHeadFile; pCurrent!=NULL; pCurrent=pCurrent->pNext)
  230. {
  231. // Migrate this file ?
  232. if (pCurrent->fMigrate)
  233. {
  234. // Set Progress File
  235. SetProgressFile(pProgress, pCurrent);
  236. // Downgrade the file
  237. pCurrent->hrMigrate = DowngradeFileV5B1(tyMigrate, pCurrent, pProgress);
  238. // Failure ?
  239. if (FAILED(pCurrent->hrMigrate))
  240. pCurrent->dwLastError = GetLastError();
  241. }
  242. }
  243. exit:
  244. // Done
  245. return hr;
  246. }