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.

1006 lines
34 KiB

  1. /*++
  2. Copyright (C) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. RepositoryPackager.CPP
  5. Abstract:
  6. Recursively packages the contents of the repository directory into a single file,
  7. and unpackages it.
  8. History:
  9. paulall 07-26-00 Created.
  10. a-shawnb 07-27-00 Finished.
  11. --*/
  12. #include "precomp.h"
  13. #include <wbemcli.h>
  14. #include "RepositoryPackager.h"
  15. #include <arrtempl.h> // for CReleaseMe
  16. #include <algorithm>
  17. #include <functional>
  18. #include <cstring>
  19. #include "a51tools.h"
  20. //#include <autoptr.h>
  21. wchar_t * CRepositoryPackager::backupFiles_[] = {L"$WinMgmt.CFG",L"INDEX.BTR",L"OBJECTS.DATA",L"Mapping1.map",L"Mapping2.map", L"Mapping.Ver"};
  22. wchar_t * CRepositoryPackager::repDirectory_ = L"FS";
  23. int __cdecl _adap_wbem_wcsicmp(const unsigned short * a,const unsigned short * b)
  24. {
  25. return wbem_wcsicmp(a,b);
  26. }
  27. bool CRepositoryPackager::needBackup(const wchar_t * fileName) const
  28. {
  29. const int maxSize = sizeof(backupFiles_)/sizeof(backupFiles_[0]);
  30. return (std::find_if(&backupFiles_[0], &backupFiles_[maxSize], std::not1(std::bind1st(std::ptr_fun(_adap_wbem_wcsicmp),fileName))) != backupFiles_+maxSize);
  31. };
  32. /******************************************************************************
  33. *
  34. * CRepositoryPackager::PackageRepository
  35. *
  36. * Description:
  37. * Iterates deeply through the repository directly and packages it up
  38. * into the given file specified by the given parameter.
  39. * Repository directory is the one retrieved from the registry.
  40. *
  41. * Parameters:
  42. * wszFilename: Filename we package everything up into
  43. *
  44. * Return:
  45. * HRESULT: WBEM_S_NO_ERROR If successful
  46. * WBEM_E_OUT_OF_MEMORY If out of memory
  47. * WBEM_E_FAILED If anything else failed
  48. *
  49. ******************************************************************************
  50. */
  51. HRESULT CRepositoryPackager::PackageRepository(const wchar_t *wszFilename)
  52. {
  53. HRESULT hres = WBEM_S_NO_ERROR;
  54. CFileName wszRepositoryDirectory;
  55. HANDLE hFile = INVALID_HANDLE_VALUE;
  56. int lBackupFileNameLen = 0;
  57. bool bBackupFileExists = false;
  58. CFileName wszBackupFileName;
  59. if ((wszBackupFileName == NULL) || (wszRepositoryDirectory == NULL))
  60. hres = WBEM_E_OUT_OF_MEMORY;
  61. //Get the root directory of the repository
  62. if (SUCCEEDED(hres))
  63. hres = GetRepositoryDirectory(wszRepositoryDirectory);
  64. //Create a new file to package contents up to...
  65. if (SUCCEEDED(hres))
  66. {
  67. hFile = CreateFileW(wszFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
  68. if (hFile == INVALID_HANDLE_VALUE)
  69. {
  70. if ((GetLastError() != ERROR_FILE_EXISTS) && (GetLastError() != ERROR_ALREADY_EXISTS ))
  71. {
  72. hres = WBEM_E_INVALID_PARAMETER;
  73. }
  74. else
  75. {
  76. //We need to back up the existing file in case we fail and need to restore it
  77. StringCchCopyW(wszBackupFileName, wszBackupFileName.Length(), wszFilename);
  78. StringCchCatW(wszBackupFileName, wszBackupFileName.Length(), L".");
  79. lBackupFileNameLen = wcslen(wszBackupFileName);
  80. for (int i = 0; i != 100; i++)
  81. {
  82. _itow(i, wszBackupFileName+lBackupFileNameLen, 10);
  83. if (MoveFileW(wszFilename, wszBackupFileName))
  84. {
  85. //We Succeeded!
  86. bBackupFileExists = true;
  87. //Now we need to open the file again!
  88. hFile = CreateFileW(wszFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
  89. if (hFile == INVALID_HANDLE_VALUE)
  90. {
  91. hres = WBEM_E_INVALID_PARAMETER;
  92. }
  93. break;
  94. }
  95. }
  96. //If we failed with all them we may as well just give up here!
  97. if (!bBackupFileExists)
  98. hres = WBEM_E_INVALID_PARAMETER;
  99. }
  100. }
  101. }
  102. //Write the package header...
  103. if (SUCCEEDED(hres))
  104. {
  105. hres = PackageHeader(hFile);
  106. }
  107. if (SUCCEEDED(hres))
  108. {
  109. hres = PackageAllFiles(hFile, wszRepositoryDirectory);
  110. }
  111. //Write the end of package marker
  112. if (SUCCEEDED(hres))
  113. hres = PackageTrailer(hFile);
  114. if (hFile != INVALID_HANDLE_VALUE)
  115. CloseHandle(hFile);
  116. //If things failed we should delete the file...
  117. if (FAILED(hres))
  118. DeleteFileW(wszFilename);
  119. //If there is a backup file, rename it back in failure case
  120. //or delete in other cases
  121. if (FAILED(hres) && bBackupFileExists && wszBackupFileName)
  122. MoveFileW(wszBackupFileName, wszFilename);
  123. else if (bBackupFileExists && wszBackupFileName)
  124. DeleteFileW(wszBackupFileName);
  125. return hres;
  126. }
  127. /******************************************************************************
  128. *
  129. * CRepositoryPackager::UnpackageRepository
  130. *
  131. * Description:
  132. * Given the filename of a packaged up repository we unpack everything
  133. * into the repository directory specified in the registry. The
  134. * directory should have no files in it before doing this.
  135. *
  136. * Parameters:
  137. * wszFilename: Filename we unpackage everything from
  138. *
  139. * Return:
  140. * HRESULT: WBEM_S_NO_ERROR If successful
  141. * WBEM_E_OUT_OF_MEMORY If out of memory
  142. * WBEM_E_FAILED If anything else failed
  143. *
  144. ******************************************************************************
  145. */
  146. HRESULT CRepositoryPackager::UnpackageRepository(const wchar_t *wszFilename)
  147. {
  148. HRESULT hres = WBEM_S_NO_ERROR;
  149. wchar_t wszRepositoryDirectory[MAX_PATH+1];
  150. HANDLE hFile = INVALID_HANDLE_VALUE;
  151. //Get the root directory of the repository
  152. hres = GetRepositoryDirectory(wszRepositoryDirectory);
  153. //open the file for unpacking...
  154. if (SUCCEEDED(hres))
  155. {
  156. hFile = CreateFileW(wszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  157. if (hFile == INVALID_HANDLE_VALUE)
  158. hres = WBEM_E_INVALID_PARAMETER;
  159. }
  160. //unpack the package header...
  161. if (SUCCEEDED(hres))
  162. {
  163. hres = UnPackageHeader(hFile);
  164. }
  165. //unpack the file...
  166. if (SUCCEEDED(hres))
  167. {
  168. hres = UnPackageContentsOfDirectory(hFile, wszRepositoryDirectory);
  169. }
  170. if (hFile != INVALID_HANDLE_VALUE)
  171. CloseHandle(hFile);
  172. //If things failed we should delete the partially unpacked repository...
  173. if (FAILED(hres))
  174. DeleteRepository();
  175. return hres;
  176. }
  177. /******************************************************************************
  178. *
  179. * CRepositoryPackager::DeleteRepository
  180. *
  181. * Description:
  182. * Delete all files and directories under the repository directory.
  183. * The repository directory location is retrieved from the registry.
  184. *
  185. * Parameters:
  186. * <none>
  187. *
  188. * Return:
  189. * HRESULT: WBEM_S_NO_ERROR If successful
  190. * WBEM_E_OUT_OF_MEMORY If out of memory
  191. * WBEM_E_FAILED If anything else failed
  192. *
  193. ******************************************************************************
  194. */
  195. HRESULT CRepositoryPackager::DeleteRepository()
  196. {
  197. HRESULT hr = WBEM_S_NO_ERROR;
  198. wchar_t *wszRepositoryOrg = new wchar_t[MAX_PATH+1];
  199. CVectorDeleteMe<wchar_t> vdm1(wszRepositoryOrg);
  200. if (!wszRepositoryOrg)
  201. hr = WBEM_E_OUT_OF_MEMORY;
  202. if (SUCCEEDED(hr))
  203. hr = GetRepositoryDirectory(wszRepositoryOrg);
  204. //MOVE EACH OF THE FILES, ONE BY ONE
  205. for (int i = 0; SUCCEEDED(hr) && (i != 6); i++)
  206. {
  207. static wchar_t *filename[] = {L"$WinMgmt.CFG",L"INDEX.BTR",L"OBJECTS.DATA",L"Mapping1.map",L"Mapping2.map", L"Mapping.Ver"};
  208. CFileName wszDestinationFile;
  209. if (!wszDestinationFile)
  210. hr = WBEM_E_OUT_OF_MEMORY;
  211. else
  212. {
  213. StringCchCopyW(wszDestinationFile, wszDestinationFile.Length(), wszRepositoryOrg);
  214. if (i != 0)
  215. {
  216. StringCchCatW(wszDestinationFile, wszDestinationFile.Length(), L"\\fs");
  217. }
  218. StringCchCatW(wszDestinationFile, wszDestinationFile.Length(), filename[i]);
  219. if (!DeleteFileW(wszDestinationFile))
  220. {
  221. if ((GetLastError() != ERROR_FILE_NOT_FOUND) && (GetLastError() != ERROR_PATH_NOT_FOUND))
  222. {
  223. hr = WBEM_E_FAILED;
  224. break;
  225. }
  226. }
  227. }
  228. }
  229. return hr;
  230. }
  231. HRESULT CRepositoryPackager::PackageAllFiles(HANDLE hFile, const wchar_t *wszRepositoryDirectory)
  232. {
  233. //
  234. // internally PackageFile check for existence
  235. // this is a matter only when $WinMgMt.CFG is packeged, since it cannot be there
  236. // if PackeageFile is called from within the FindFirst/FindNext loop, then the
  237. // existence of the file is ensured by the context
  238. //
  239. HRESULT hres = PackageFile(hFile, wszRepositoryDirectory, backupFiles_[0]);
  240. if (FAILED(hres))
  241. return hres;
  242. hres = PackageDirectory(hFile, wszRepositoryDirectory, repDirectory_);
  243. return hres;
  244. }
  245. /******************************************************************************
  246. *
  247. * CRepositoryPackager::PackageContentsOfDirectory
  248. *
  249. * Description:
  250. * Given a directory, iterates through all files and directories and
  251. * calls into the function to package it into the file specified by the
  252. * file handle passed to the method.
  253. *
  254. * Parameters:
  255. * hFile: Handle to the destination file.
  256. * wszRepositoryDirectory: Directory to process
  257. *
  258. * Return:
  259. * HRESULT: WBEM_S_NO_ERROR If successful
  260. * WBEM_E_OUT_OF_MEMORY If out of memory
  261. * WBEM_E_FAILED If anything else failed
  262. *
  263. ******************************************************************************
  264. */
  265. HRESULT CRepositoryPackager::PackageContentsOfDirectory(HANDLE hFile, const wchar_t *wszRepositoryDirectory)
  266. {
  267. HRESULT hres = WBEM_S_NO_ERROR;
  268. WIN32_FIND_DATAW findFileData;
  269. HANDLE hff = INVALID_HANDLE_VALUE;
  270. //create file search pattern...
  271. CFileName wszSearchPattern;
  272. if (wszSearchPattern == NULL)
  273. hres = WBEM_E_OUT_OF_MEMORY;
  274. else
  275. {
  276. StringCchCopyW(wszSearchPattern, wszSearchPattern.Length(), wszRepositoryDirectory);
  277. StringCchCatW(wszSearchPattern, wszSearchPattern.Length(), L"\\*");
  278. }
  279. //Start the file iteration in this directory...
  280. if (SUCCEEDED(hres))
  281. {
  282. hff = FindFirstFileW(wszSearchPattern, &findFileData);
  283. if (hff == INVALID_HANDLE_VALUE)
  284. {
  285. hres = WBEM_E_FAILED;
  286. }
  287. }
  288. if (SUCCEEDED(hres))
  289. {
  290. do
  291. {
  292. //If we have a filename of '.' or '..' we ignore it...
  293. if ((wcscmp(findFileData.cFileName, L".") == 0) ||
  294. (wcscmp(findFileData.cFileName, L"..") == 0))
  295. {
  296. //Do nothing with these...
  297. }
  298. else
  299. {
  300. //This is a file, so we need to deal with that...
  301. hres = PackageFile(hFile, wszRepositoryDirectory, findFileData.cFileName);
  302. if (FAILED(hres))
  303. break;
  304. }
  305. } while (FindNextFileW(hff, &findFileData));
  306. }
  307. if (hff != INVALID_HANDLE_VALUE)
  308. FindClose(hff);
  309. return hres;
  310. }
  311. /******************************************************************************
  312. *
  313. * CRepositoryPackager::GetRepositoryDirectory
  314. *
  315. * Description:
  316. * Retrieves the location of the repository directory from the registry.
  317. *
  318. * Parameters:
  319. * wszRepositoryDirectory: Array to store location in.
  320. *
  321. * Return:
  322. * HRESULT: WBEM_S_NO_ERROR If successful
  323. * WBEM_E_OUT_OF_MEMORY If out of memory
  324. * WBEM_E_FAILED If anything else failed
  325. *
  326. ******************************************************************************
  327. */
  328. HRESULT CRepositoryPackager::GetRepositoryDirectory(wchar_t wszRepositoryDirectory[MAX_PATH+1])
  329. {
  330. HKEY hKey;
  331. long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  332. L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
  333. 0, KEY_READ, &hKey);
  334. if(lRes)
  335. return WBEM_E_FAILED;
  336. wchar_t wszTmp[MAX_PATH + 1];
  337. DWORD dwLen = (MAX_PATH + 1)*sizeof(wchar_t);
  338. lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL,
  339. (LPBYTE)wszTmp, &dwLen);
  340. RegCloseKey(hKey);
  341. if(lRes)
  342. return WBEM_E_FAILED;
  343. if (ExpandEnvironmentStringsW(wszTmp,wszRepositoryDirectory, MAX_PATH + 1) == 0)
  344. return WBEM_E_FAILED;
  345. return WBEM_S_NO_ERROR;
  346. }
  347. /******************************************************************************
  348. *
  349. * CRepositoryPackager::PackageHeader
  350. *
  351. * Description:
  352. * Stores the header package in the given file. This is a footprint
  353. * so we can recognise if this really is one of our files when
  354. * we try to decode it. Also it allows us to version it.
  355. *
  356. * Parameters:
  357. * hFile: File handle to store header in.
  358. *
  359. * Return:
  360. * HRESULT: WBEM_S_NO_ERROR If successful
  361. * WBEM_E_OUT_OF_MEMORY If out of memory
  362. * WBEM_E_FAILED If anything else failed
  363. *
  364. ******************************************************************************
  365. */
  366. HRESULT CRepositoryPackager::PackageHeader(HANDLE hFile)
  367. {
  368. HRESULT hres = WBEM_S_NO_ERROR;
  369. PACKAGE_HEADER header;
  370. StringCchCopyA(header.szSignature, 10, "FS PKG1.1"); //NOTE! MAXIMUM OF 10 CHARACTERS (INCLUDING TERMINATOR!)
  371. DWORD dwSize = 0;
  372. if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
  373. hres = WBEM_E_FAILED;
  374. return hres;
  375. }
  376. /******************************************************************************
  377. *
  378. * CRepositoryPackager::PackageDirectory
  379. *
  380. * Description:
  381. * This is the code which processes a directory. It stores the namespace
  382. * header and footer marker in the file, and also iterates through
  383. * all files and directories in that directory.
  384. *
  385. * Parameters:
  386. * hFile: File handle to store directory information in.
  387. * wszParentDirectory: Full path of parent directory
  388. * eszSubDirectory: Name of sub-directory to process
  389. *
  390. * Return:
  391. * HRESULT: WBEM_S_NO_ERROR If successful
  392. * WBEM_E_OUT_OF_MEMORY If out of memory
  393. * WBEM_E_FAILED If anything else failed
  394. *
  395. ******************************************************************************
  396. */
  397. HRESULT CRepositoryPackager::PackageDirectory(HANDLE hFile, const wchar_t *wszParentDirectory, wchar_t *wszSubDirectory)
  398. {
  399. HRESULT hres = WBEM_S_NO_ERROR;
  400. {
  401. PACKAGE_SPACER_NAMESPACE header;
  402. header.dwSpacerType = PACKAGE_TYPE_NAMESPACE_START;
  403. StringCchCopyW(header.wszNamespaceName, MAX_PATH+1, wszSubDirectory);
  404. DWORD dwSize = 0;
  405. if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
  406. hres = WBEM_E_FAILED;
  407. }
  408. //Get full path of new directory...
  409. CFileName wszFullDirectoryName;
  410. if (wszFullDirectoryName == NULL) hres = WBEM_E_OUT_OF_MEMORY;
  411. if (SUCCEEDED(hres))
  412. {
  413. StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory);
  414. StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\");
  415. StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszSubDirectory);
  416. }
  417. //Package the contents of that directory...
  418. if (SUCCEEDED(hres))
  419. {
  420. hres = PackageContentsOfDirectory(hFile, wszFullDirectoryName);
  421. }
  422. //Now need to write the end of package marker...
  423. if (SUCCEEDED(hres))
  424. {
  425. PACKAGE_SPACER header2;
  426. header2.dwSpacerType = PACKAGE_TYPE_NAMESPACE_END;
  427. DWORD dwSize = 0;
  428. if ((WriteFile(hFile, &header2, sizeof(header2), &dwSize, NULL) == 0) || (dwSize != sizeof(header2)))
  429. hres = WBEM_E_FAILED;
  430. }
  431. return hres;
  432. }
  433. /******************************************************************************
  434. *
  435. * CRepositoryPackager::PackageFile
  436. *
  437. * Description:
  438. * This is the code which processes a file. It stores the file header
  439. * and the contents of the file into the destination file whose handle
  440. * is passed in. The file directory and name is passed in.
  441. *
  442. * Parameters:
  443. * hFile: File handle to store directory information in.
  444. * wszParentDirectory: Full path of parent directory
  445. * wszFilename: Name of file to process
  446. *
  447. * Return:
  448. * HRESULT: WBEM_S_NO_ERROR If successful
  449. * WBEM_E_OUT_OF_MEMORY If out of memory
  450. * WBEM_E_FAILED If anything else failed
  451. *
  452. ******************************************************************************
  453. */
  454. HRESULT CRepositoryPackager::PackageFile(HANDLE hFile, const wchar_t *wszParentDirectory, wchar_t *wszFilename)
  455. {
  456. if (needBackup(wszFilename) == false) return WBEM_S_NO_ERROR;
  457. HRESULT hres = WBEM_S_NO_ERROR;
  458. PACKAGE_SPACER_FILE header;
  459. header.dwSpacerType = PACKAGE_TYPE_FILE;
  460. StringCchCopyW(header.wszFileName, MAX_PATH+1, wszFilename);
  461. WIN32_FILE_ATTRIBUTE_DATA fileAttribs;
  462. CFileName wszFullFileName;
  463. if (wszFullFileName == NULL)
  464. hres = WBEM_E_OUT_OF_MEMORY;
  465. if (SUCCEEDED(hres))
  466. {
  467. StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszParentDirectory);
  468. StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\");
  469. StringCchCatW(wszFullFileName, wszFullFileName.Length(), wszFilename);
  470. if (GetFileAttributesExW(wszFullFileName, GetFileExInfoStandard, &fileAttribs) == 0)
  471. {
  472. if (ERROR_FILE_NOT_FOUND == GetLastError())
  473. return WBEM_S_NO_ERROR;
  474. else
  475. hres = WBEM_E_FAILED;
  476. }
  477. else
  478. {
  479. header.dwFileSize = fileAttribs.nFileSizeLow;
  480. }
  481. }
  482. //Write header...
  483. if (SUCCEEDED(hres))
  484. {
  485. DWORD dwSize = 0;
  486. if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
  487. hres = WBEM_E_FAILED;
  488. }
  489. //Now need to write actual contents of file to current one... but only if the file is not 0 bytes long...
  490. if (SUCCEEDED(hres) && (header.dwFileSize != 0))
  491. {
  492. HANDLE hFromFile = CreateFileW(wszFullFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  493. if (hFromFile == INVALID_HANDLE_VALUE)
  494. hres = WBEM_E_FAILED;
  495. BYTE *pFileBlob = NULL;
  496. if (SUCCEEDED(hres))
  497. {
  498. pFileBlob = new BYTE[header.dwFileSize];
  499. if (pFileBlob == NULL)
  500. hres = WBEM_E_OUT_OF_MEMORY;
  501. }
  502. if (SUCCEEDED(hres))
  503. {
  504. DWORD dwSize = 0;
  505. if ((ReadFile(hFromFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
  506. hres = WBEM_E_FAILED;
  507. }
  508. if (SUCCEEDED(hres))
  509. {
  510. DWORD dwSize = 0;
  511. if ((WriteFile(hFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
  512. hres = WBEM_E_FAILED;
  513. }
  514. delete pFileBlob;
  515. if (hFromFile != INVALID_HANDLE_VALUE)
  516. CloseHandle(hFromFile);
  517. }
  518. return hres;
  519. }
  520. /******************************************************************************
  521. *
  522. * CRepositoryPackager::PackageTrailer
  523. *
  524. * Description:
  525. * Writes the end of file marker to the file.
  526. *
  527. * Parameters:
  528. * hFile: File handle to store directory information in.
  529. *
  530. * Return:
  531. * HRESULT: WBEM_S_NO_ERROR If successful
  532. * WBEM_E_OUT_OF_MEMORY If out of memory
  533. * WBEM_E_FAILED If anything else failed
  534. *
  535. ******************************************************************************
  536. */
  537. HRESULT CRepositoryPackager::PackageTrailer(HANDLE hFile)
  538. {
  539. HRESULT hres = WBEM_S_NO_ERROR;
  540. PACKAGE_SPACER trailer;
  541. trailer.dwSpacerType = PACKAGE_TYPE_END_OF_FILE;
  542. DWORD dwSize = 0;
  543. if ((WriteFile(hFile, &trailer, sizeof(trailer), &dwSize, NULL) == 0) || (dwSize != sizeof(trailer)))
  544. hres = WBEM_E_FAILED;
  545. return hres;
  546. }
  547. /******************************************************************************
  548. *
  549. * CRepositoryPackager::UnPackageHeader
  550. *
  551. * Description:
  552. * Unpacks the header package in the given file. This allows us to recognise
  553. * if this really is one of our files. Also it allows us to version it.
  554. *
  555. * Parameters:
  556. * hFile: File handle to unpack header from.
  557. *
  558. * Return:
  559. * HRESULT: WBEM_S_NO_ERROR If successful
  560. * WBEM_E_OUT_OF_MEMORY If out of memory
  561. * WBEM_E_FAILED If anything else failed
  562. *
  563. ******************************************************************************
  564. */
  565. HRESULT CRepositoryPackager::UnPackageHeader(HANDLE hFile)
  566. {
  567. HRESULT hres = WBEM_S_NO_ERROR;
  568. PACKAGE_HEADER header;
  569. DWORD dwSize = 0;
  570. if ((ReadFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
  571. {
  572. hres = WBEM_E_FAILED;
  573. }
  574. else if (strncmp(header.szSignature,"FS PKG1.1", 9) != 0)
  575. {
  576. hres = WBEM_E_FAILED;
  577. }
  578. return hres;
  579. }
  580. /******************************************************************************
  581. *
  582. * CRepositoryPackager::UnPackageContentsOfDirectory
  583. *
  584. * Description:
  585. * Unpack the contents of a namespace/directory.
  586. * If a subdirectory is encountered, then it calls UnPackageDirectory to handle it.
  587. * If a file is encountered, then it calls UnPackageFile to handle it.
  588. * If no errors occur, then it will enventually encounter the end of the namespace,
  589. * which will terminate the loop and return control to the calling function.
  590. *
  591. * Parameters:
  592. * hFile: Handle to the file to unpack from
  593. * wszRepositoryDirectory: Directory to write to.
  594. *
  595. * Return:
  596. * HRESULT: WBEM_S_NO_ERROR If successful
  597. * WBEM_E_OUT_OF_MEMORY If out of memory
  598. * WBEM_E_FAILED If anything else failed
  599. *
  600. ******************************************************************************
  601. */
  602. HRESULT CRepositoryPackager::UnPackageContentsOfDirectory(HANDLE hFile, const wchar_t *wszRepositoryDirectory)
  603. {
  604. HRESULT hres = WBEM_S_NO_ERROR;
  605. PACKAGE_SPACER header;
  606. DWORD dwSize;
  607. while (hres == WBEM_S_NO_ERROR)
  608. {
  609. // this loop will be exited when we either
  610. // - successfully process a complete directory/namespace
  611. // - encounter an error
  612. dwSize = 0;
  613. if ((ReadFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header)))
  614. {
  615. hres = WBEM_E_FAILED;
  616. }
  617. else if (header.dwSpacerType == PACKAGE_TYPE_NAMESPACE_START)
  618. {
  619. hres = UnPackageDirectory(hFile, wszRepositoryDirectory);
  620. }
  621. else if (header.dwSpacerType == PACKAGE_TYPE_NAMESPACE_END)
  622. {
  623. // done with this directory
  624. break;
  625. }
  626. else if (header.dwSpacerType == PACKAGE_TYPE_FILE)
  627. {
  628. hres = UnPackageFile(hFile, wszRepositoryDirectory);
  629. }
  630. else if (header.dwSpacerType == PACKAGE_TYPE_END_OF_FILE)
  631. {
  632. // done unpacking
  633. break;
  634. }
  635. else
  636. {
  637. hres = WBEM_E_FAILED;
  638. }
  639. }
  640. return hres;
  641. }
  642. /******************************************************************************
  643. *
  644. * CRepositoryPackager::UnPackageDirectory
  645. *
  646. * Description:
  647. * Unpack the start of a namespace, then call UnPackageContentsOfDirectory
  648. * to handle everything within it.
  649. *
  650. * Parameters:
  651. * hFile: File handle to unpack directory information from.
  652. * wszParentDirectory: Full path of parent directory
  653. *
  654. * Return:
  655. * HRESULT: WBEM_S_NO_ERROR If successful
  656. * WBEM_E_OUT_OF_MEMORY If out of memory
  657. * WBEM_E_FAILED If anything else failed
  658. *
  659. ******************************************************************************
  660. */
  661. HRESULT CRepositoryPackager::UnPackageDirectory(HANDLE hFile, const wchar_t *wszParentDirectory)
  662. {
  663. PACKAGE_SPACER_NAMESPACE header;
  664. // read namespace/directory name
  665. DWORD dwSize = 0;
  666. DWORD dwSizeToRead = sizeof(header)-sizeof(PACKAGE_SPACER);
  667. if ((ReadFile(hFile, ((LPBYTE)&header)+sizeof(PACKAGE_SPACER), dwSizeToRead, &dwSize, NULL) == 0) || (dwSize != dwSizeToRead))
  668. {
  669. return WBEM_E_FAILED;
  670. }
  671. //Get full path of new directory...
  672. CFileName wszFullDirectoryName;
  673. if (NULL == (wchar_t *)wszFullDirectoryName) return WBEM_E_OUT_OF_MEMORY;
  674. StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory);
  675. StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\");
  676. StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), header.wszNamespaceName);
  677. // create directory
  678. if (!CreateDirectoryW(wszFullDirectoryName, NULL))
  679. {
  680. if (GetLastError() != ERROR_ALREADY_EXISTS) return WBEM_E_FAILED;
  681. }
  682. // UnPackage the contents into the new directory...
  683. return UnPackageContentsOfDirectory(hFile, wszFullDirectoryName);
  684. }
  685. /******************************************************************************
  686. *
  687. * CRepositoryPackager::UnPackageFile
  688. *
  689. * Description:
  690. * Unpack a file.
  691. *
  692. * Parameters:
  693. * hFile: File handle to unpack file information from.
  694. * wszParentDirectory: Full path of parent directory
  695. *
  696. * Return:
  697. * HRESULT: WBEM_S_NO_ERROR If successful
  698. * WBEM_E_OUT_OF_MEMORY If out of memory
  699. * WBEM_E_FAILED If anything else failed
  700. *
  701. ******************************************************************************
  702. */
  703. HRESULT CRepositoryPackager::UnPackageFile(HANDLE hFile, const wchar_t *wszParentDirectory)
  704. {
  705. HRESULT hres = WBEM_S_NO_ERROR;
  706. PACKAGE_SPACER_FILE header;
  707. // read file name and size
  708. DWORD dwSize = 0;
  709. DWORD dwSizeToRead = sizeof(header)-sizeof(PACKAGE_SPACER);
  710. if ((ReadFile(hFile, ((LPBYTE)&header)+sizeof(PACKAGE_SPACER), dwSizeToRead, &dwSize, NULL) == 0) || (dwSize != dwSizeToRead))
  711. {
  712. hres = WBEM_E_FAILED;
  713. }
  714. //Get full path of new file...
  715. CFileName wszFullFileName;
  716. if (NULL == (wchar_t *)wszFullFileName) hres = WBEM_E_OUT_OF_MEMORY;
  717. if (SUCCEEDED(hres))
  718. {
  719. StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszParentDirectory);
  720. StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\");
  721. StringCchCatW(wszFullFileName, wszFullFileName.Length(), header.wszFileName);
  722. }
  723. // create the file
  724. HANDLE hNewFile = INVALID_HANDLE_VALUE;
  725. if (SUCCEEDED(hres))
  726. {
  727. hNewFile = CreateFileW(wszFullFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  728. if (hNewFile == INVALID_HANDLE_VALUE)
  729. hres = WBEM_E_FAILED;
  730. }
  731. // read file blob and write to file if size is greater than zero
  732. if (SUCCEEDED(hres))
  733. {
  734. if (header.dwFileSize > 0)
  735. {
  736. BYTE* pFileBlob = new BYTE[header.dwFileSize];
  737. if (pFileBlob == NULL)
  738. hres = WBEM_E_OUT_OF_MEMORY;
  739. if (SUCCEEDED(hres))
  740. {
  741. dwSize = 0;
  742. if ((ReadFile(hFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
  743. {
  744. hres = WBEM_E_FAILED;
  745. }
  746. }
  747. // write file
  748. if (SUCCEEDED(hres))
  749. {
  750. dwSize = 0;
  751. if ((WriteFile(hNewFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize))
  752. hres = WBEM_E_FAILED;
  753. }
  754. if (pFileBlob)
  755. delete pFileBlob;
  756. }
  757. }
  758. if (hNewFile != INVALID_HANDLE_VALUE)
  759. CloseHandle(hNewFile);
  760. return hres;
  761. }
  762. /******************************************************************************
  763. *
  764. * CRepositoryPackager::DeleteContentsOfDirectory
  765. *
  766. * Description:
  767. * Given a directory, iterates through all files and directories and
  768. * calls into the function to delete it.
  769. *
  770. * Parameters:
  771. * wszRepositoryDirectory: Directory to process
  772. *
  773. * Return:
  774. * HRESULT: WBEM_S_NO_ERROR If successful
  775. * WBEM_E_OUT_OF_MEMORY If out of memory
  776. * WBEM_E_FAILED If anything else failed
  777. *
  778. ******************************************************************************
  779. */
  780. HRESULT CRepositoryPackager::DeleteContentsOfDirectory(const wchar_t *wszRepositoryDirectory)
  781. {
  782. HRESULT hres = WBEM_S_NO_ERROR;
  783. CFileName wszFullFileName;
  784. if (wszFullFileName == NULL)
  785. return WBEM_E_OUT_OF_MEMORY;
  786. WIN32_FIND_DATAW findFileData;
  787. HANDLE hff = INVALID_HANDLE_VALUE;
  788. //create file search pattern...
  789. CFileName wszSearchPattern;
  790. if (wszSearchPattern == NULL)
  791. hres = WBEM_E_OUT_OF_MEMORY;
  792. else
  793. {
  794. StringCchCopyW(wszSearchPattern, wszSearchPattern.Length(), wszRepositoryDirectory);
  795. StringCchCatW(wszSearchPattern, wszSearchPattern.Length(), L"\\*");
  796. }
  797. //Start the file iteration in this directory...
  798. if (SUCCEEDED(hres))
  799. {
  800. hff = FindFirstFileW(wszSearchPattern, &findFileData);
  801. if (hff == INVALID_HANDLE_VALUE)
  802. {
  803. hres = WBEM_E_FAILED;
  804. }
  805. }
  806. if (SUCCEEDED(hres))
  807. {
  808. do
  809. {
  810. //If we have a filename of '.' or '..' we ignore it...
  811. if ((wcscmp(findFileData.cFileName, L".") == 0) ||
  812. (wcscmp(findFileData.cFileName, L"..") == 0))
  813. {
  814. //Do nothing with these...
  815. }
  816. else if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  817. {
  818. //This is a directory, so we need to deal with that...
  819. hres = PackageDeleteDirectory(wszRepositoryDirectory, findFileData.cFileName);
  820. if (FAILED(hres))
  821. break;
  822. }
  823. else
  824. {
  825. //This is a file, so we need to deal with that...
  826. StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszRepositoryDirectory);
  827. StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\");
  828. StringCchCatW(wszFullFileName, wszFullFileName.Length(), findFileData.cFileName);
  829. if (!DeleteFileW(wszFullFileName))
  830. {
  831. hres = WBEM_E_FAILED;
  832. break;
  833. }
  834. }
  835. } while (FindNextFileW(hff, &findFileData));
  836. }
  837. if (hff != INVALID_HANDLE_VALUE)
  838. FindClose(hff);
  839. return hres;
  840. }
  841. /******************************************************************************
  842. *
  843. * CRepositoryPackager::PackageDeleteDirectory
  844. *
  845. * Description:
  846. * This is the code which processes a directory. It iterates through
  847. * all files and directories in that directory.
  848. *
  849. * Parameters:
  850. * wszParentDirectory: Full path of parent directory
  851. * eszSubDirectory: Name of sub-directory to process
  852. *
  853. * Return:
  854. * HRESULT: WBEM_S_NO_ERROR If successful
  855. * WBEM_E_OUT_OF_MEMORY If out of memory
  856. * WBEM_E_FAILED If anything else failed
  857. *
  858. ******************************************************************************
  859. */
  860. HRESULT CRepositoryPackager::PackageDeleteDirectory(const wchar_t *wszParentDirectory, wchar_t *wszSubDirectory)
  861. {
  862. HRESULT hres = WBEM_S_NO_ERROR;
  863. //Get full path of new directory...
  864. CFileName wszFullDirectoryName;
  865. if (wszFullDirectoryName == NULL) return WBEM_E_OUT_OF_MEMORY;
  866. if (SUCCEEDED(hres))
  867. {
  868. StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory);
  869. StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\");
  870. StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszSubDirectory);
  871. }
  872. //Package the contents of that directory...
  873. if (SUCCEEDED(hres))
  874. {
  875. hres = DeleteContentsOfDirectory(wszFullDirectoryName);
  876. }
  877. // now that the directory is empty, remove it
  878. if (!RemoveDirectoryW(wszFullDirectoryName))
  879. hres = WBEM_E_FAILED;
  880. return hres;
  881. }