Source code of Windows XP (NT5)
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.

352 lines
9.5 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <wbemcomn.h>
  4. #include <filecach.h>
  5. #define A51_REPOSITORY_TEMPDIR_NAME L"A51Temp"
  6. long FlushOldCache(LPCWSTR wszRepDir);
  7. long GetRepositoryDirectory(LPWSTR wszRepDir);
  8. long ConvertA51ToRoswell();
  9. long CopyA51ToRoswell(LPCWSTR wszOldRepDir, LPCWSTR wszRepDir);
  10. long CopyA51FromDirectoryToRoswell(LPCWSTR wszOldDir, DWORD dwOldBaseLen,
  11. CFileCache& NewCache, LPCWSTR wszNewBase,
  12. bool bIgnoreFiles);
  13. class CFindCloseMe
  14. {
  15. HANDLE m_h;
  16. public:
  17. CFindCloseMe(HANDLE h) : m_h(h){}
  18. ~CFindCloseMe() {FindClose(m_h);}
  19. };
  20. long GetRepositoryDirectory(LPWSTR wszRepDir)
  21. {
  22. HKEY hKey;
  23. long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  24. L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
  25. 0, KEY_READ, &hKey);
  26. if(lRes)
  27. return lRes;
  28. CFileName wszTmp;
  29. if (wszTmp == NULL)
  30. return ERROR_OUTOFMEMORY;
  31. DWORD dwLen = wszTmp.Length();
  32. lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL,
  33. (LPBYTE)(wchar_t*)wszTmp, &dwLen);
  34. RegCloseKey(hKey);
  35. if(lRes)
  36. {
  37. ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to get the repository "
  38. "directory from the registry: %d\n", lRes));
  39. return lRes;
  40. }
  41. if (ExpandEnvironmentStringsW(wszTmp,wszRepDir,wszTmp.Length()) == 0)
  42. return GetLastError();
  43. //
  44. // Append standard postfix --- that is our root
  45. //
  46. wcscat(wszRepDir, L"\\FS");
  47. return ERROR_SUCCESS;
  48. }
  49. long ConvertA51ToRoswell()
  50. {
  51. long lRes;
  52. //
  53. // Figure out the repository directory
  54. //
  55. CFileName wszRepDir;
  56. if(wszRepDir == NULL)
  57. return ERROR_OUTOFMEMORY;
  58. lRes = GetRepositoryDirectory(wszRepDir);
  59. if(lRes != ERROR_SUCCESS)
  60. return lRes;
  61. //
  62. // Construct a name for the backup
  63. //
  64. CFileName wszOldRepDir;
  65. if(wszRepDir == NULL)
  66. return ERROR_OUTOFMEMORY;
  67. wcscpy(wszOldRepDir, wszRepDir);
  68. WCHAR* pwcLastSlash = wcsrchr(wszOldRepDir, L'\\');
  69. if(pwcLastSlash == NULL)
  70. return ERROR_INVALID_PARAMETER;
  71. wcscpy(pwcLastSlash+1, A51_REPOSITORY_TEMPDIR_NAME);
  72. //
  73. // Remove the backup, if already there. Disregard failure --- this is not
  74. // our real operations, we are just trying to get MoveFile to succeed
  75. //
  76. long lRemoveRes = A51RemoveDirectory(wszOldRepDir, false);
  77. //
  78. // Rename it
  79. //
  80. if(!MoveFileW(wszRepDir, wszOldRepDir))
  81. {
  82. lRes = GetLastError();
  83. ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to rename the repository "
  84. "directory \nfrom '%S' to \n'%S' even after attempting to delete "
  85. "the destination. Deletion returned %d, rename returned %d\n",
  86. (LPCWSTR)wszRepDir, (LPCWSTR)wszOldRepDir, lRemoveRes, lRes));
  87. return lRes;
  88. }
  89. lRes = EnsureDirectory(wszRepDir);
  90. if(lRes != ERROR_SUCCESS)
  91. {
  92. ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to create repository "
  93. "directory '%S'. Error code %d\n", (LPCWSTR)wszRepDir, lRes));
  94. return lRes;
  95. }
  96. //
  97. // Do the real work --- attempting to move everything from the old directory
  98. // to the new one
  99. //
  100. try
  101. {
  102. lRes = CopyA51ToRoswell(wszOldRepDir, wszRepDir);
  103. }
  104. catch(...)
  105. {
  106. ERRORTRACE((LOG_WBEMCORE, "Upgrade attempt threw an exception\n"));
  107. lRes = ERROR_INTERNAL_ERROR;
  108. }
  109. //
  110. // If a failure occurred, try to reinstate old repository
  111. //
  112. if(lRes != ERROR_SUCCESS)
  113. {
  114. long lMainRes = lRes;
  115. ERRORTRACE((LOG_WBEMCORE, "Upgrade failed to convert the repository, "
  116. "error code %d\n", lMainRes));
  117. lRemoveRes = A51RemoveDirectory(wszRepDir, false);
  118. if(!MoveFileW(wszOldRepDir, wszRepDir))
  119. {
  120. lRes = GetLastError();
  121. ERRORTRACE((LOG_WBEMCORE, "Upgrade failed to rename the repository "
  122. "back from '%S' to '%S' with error code %d, even after "
  123. "attempting to delete the destination (with error code %d).\n"
  124. "WMI is now unusable!\n", (LPCWSTR)wszOldRepDir,
  125. (LPCWSTR)wszRepDir, lRes, lRemoveRes));
  126. }
  127. else
  128. {
  129. ERRORTRACE((LOG_WBEMCORE, "Upgrade restored the old repository "
  130. "back. The old version is now functional\n"));
  131. }
  132. return lMainRes;
  133. }
  134. //
  135. // Time to delete the backup
  136. //
  137. lRes = A51RemoveDirectory(wszOldRepDir, false);
  138. if(lRes != ERROR_SUCCESS)
  139. {
  140. ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to remote the backup of "
  141. "the repository in directory '%S', error code %d. This "
  142. "will not affect operations, except inasmuch as disk space "
  143. "is being wasted\n", (LPCWSTR)wszOldRepDir, lRes));
  144. }
  145. return ERROR_SUCCESS;
  146. }
  147. long CopyA51ToRoswell(LPCWSTR wszOldRepDir, LPCWSTR wszRepDir)
  148. {
  149. long lRes;
  150. lRes = FlushOldCache(wszOldRepDir);
  151. if(lRes != ERROR_SUCCESS)
  152. return lRes;
  153. //
  154. // Instantiate the new file cache
  155. //
  156. CFileCache NewCache;
  157. lRes = NewCache.Initialize(wszRepDir);
  158. if(lRes != ERROR_SUCCESS)
  159. return lRes;
  160. //
  161. // Copy all files recursively, but not the files in this directory
  162. //
  163. lRes = CopyA51FromDirectoryToRoswell(wszOldRepDir, wcslen(wszOldRepDir),
  164. NewCache, wszRepDir, true);
  165. if(lRes != ERROR_SUCCESS)
  166. return lRes;
  167. return ERROR_SUCCESS;
  168. }
  169. long CopyA51FromDirectoryToRoswell(LPCWSTR wszOldDir, DWORD dwOldBaseLen,
  170. CFileCache& NewCache, LPCWSTR wszNewBase,
  171. bool bIgnoreFiles)
  172. {
  173. long lRes;
  174. //
  175. // Commence enumeration of everything in this directory
  176. //
  177. CFileName wszMask;
  178. if(wszMask == NULL)
  179. return ERROR_OUTOFMEMORY;
  180. wcscpy(wszMask, wszOldDir);
  181. wcscat(wszMask, L"\\*");
  182. WIN32_FIND_DATAW wfd;
  183. HANDLE hSearch = FindFirstFileW(wszMask, &wfd);
  184. if(hSearch == INVALID_HANDLE_VALUE)
  185. {
  186. lRes = GetLastError();
  187. ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to enumerate files in "
  188. "directory '%S': error code %d\n", (LPCWSTR)wszOldDir, lRes));
  189. return lRes;
  190. }
  191. CFindCloseMe fcm(hSearch);
  192. do
  193. {
  194. if(wfd.cFileName[0] == L'.')
  195. continue;
  196. //
  197. // Construct full name
  198. //
  199. CFileName wszChildName;
  200. if(wszChildName == NULL)
  201. return ERROR_OUTOFMEMORY;
  202. wcscpy(wszChildName, wszOldDir);
  203. wcscat(wszChildName, L"\\");
  204. wcscat(wszChildName, wfd.cFileName);
  205. //
  206. // Recurse on directories
  207. //
  208. if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  209. {
  210. lRes = CopyA51FromDirectoryToRoswell(wszChildName, dwOldBaseLen,
  211. NewCache, wszNewBase, false);
  212. if(lRes != ERROR_SUCCESS)
  213. return lRes;
  214. }
  215. else
  216. {
  217. //
  218. // Check if we are skipping files
  219. //
  220. if(bIgnoreFiles)
  221. continue;
  222. //
  223. // Read it in
  224. //
  225. HANDLE hFile = CreateFileW(wszChildName, GENERIC_READ,
  226. FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  227. NULL);
  228. if(hFile == INVALID_HANDLE_VALUE)
  229. {
  230. lRes = GetLastError();
  231. ERRORTRACE((LOG_WBEMCORE, "Update cannot open file '%S', "
  232. "error code %d\n", (LPCWSTR)wszChildName, lRes));
  233. return lRes;
  234. }
  235. CCloseMe cm(hFile);
  236. BY_HANDLE_FILE_INFORMATION fi;
  237. if(!GetFileInformationByHandle(hFile, &fi))
  238. {
  239. lRes = GetLastError();
  240. ERRORTRACE((LOG_WBEMCORE, "Update cannot open file '%S', "
  241. "error code %d\n", (LPCWSTR)wszChildName, lRes));
  242. return lRes;
  243. }
  244. DWORD dwLen = fi.nFileSizeLow;
  245. BYTE* pBuffer = (BYTE*)TempAlloc(dwLen);
  246. if(pBuffer == NULL)
  247. return E_OUTOFMEMORY;
  248. CTempFreeMe tfm(pBuffer);
  249. DWORD dwRead;
  250. if(!::ReadFile(hFile, pBuffer, dwLen, &dwRead, NULL))
  251. {
  252. lRes = GetLastError();
  253. ERRORTRACE((LOG_WBEMCORE, "Update unable to read %d bytes "
  254. "from file '%S' with error %d\n",
  255. dwLen, (LPCWSTR)wszChildName, lRes));
  256. return lRes;
  257. }
  258. //
  259. // Convert the name to the new directory name
  260. //
  261. CFileName wszNewChildName;
  262. if(wszNewChildName == NULL)
  263. return ERROR_OUTOFMEMORY;
  264. wcscpy(wszNewChildName, wszNewBase);
  265. wcscat(wszNewChildName, wszChildName + dwOldBaseLen);
  266. //
  267. // Write it out
  268. //
  269. lRes = NewCache.WriteFile(wszNewChildName, dwLen, pBuffer);
  270. if(lRes != ERROR_SUCCESS)
  271. return lRes;
  272. }
  273. }
  274. while(FindNextFile(hSearch, &wfd));
  275. lRes = GetLastError();
  276. if(lRes != ERROR_NO_MORE_FILES)
  277. {
  278. ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to enumerate files in "
  279. "directory '%S': error code %d\n", (LPCWSTR)wszOldDir, lRes));
  280. return lRes;
  281. }
  282. return ERROR_SUCCESS;
  283. }