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.

1698 lines
54 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. opaque.c
  5. Abstract:
  6. Implements a basic secure server transport module
  7. Author:
  8. Jim Schmidt (jimschm) 08-Mar-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "logmsg.h"
  17. #include <compress.h>
  18. #define DBG_OPAQUE "OpaqueUnc"
  19. //
  20. // Strings
  21. //
  22. #define S_TRANSPORT_DIR TEXT("USMT2.UNC")
  23. #define S_TRANSPORT_DAT_FILE TEXT("TRANSDB.DAT")
  24. #define S_TRANSPORT_IMG_FILE TEXT("IMG%05X.DAT")
  25. #define S_TRANSPORT_STATUS_FILE TEXT("status")
  26. #define S_FILEOBJECT_NAME TEXT("File")
  27. #define S_REGOBJECT_NAME TEXT("Registry")
  28. #define S_DATABASEOBJECT_NAME TEXT("Database")
  29. #define S_DETAILS_PREFIX TEXT("details-")
  30. //
  31. // Constants
  32. //
  33. #define TRFLAG_FILE 0x01
  34. #define TRFLAG_MEMORY 0x02
  35. #define COPY_BUFFER_SIZE 32768
  36. #define OPAQUETR_OLDSIG1 0x55534D31 //USM1
  37. #define OPAQUETR_OLDSIG2 0x55534D32 //USM1
  38. #define OPAQUETR_SIG 0x55534D33 //USM2
  39. #define TRSTATUS_DIRTY 0x00000001
  40. #define TRSTATUS_READY 0x00000002
  41. #define TRSTATUS_LOCKED 0x00000003
  42. //
  43. // Macros
  44. //
  45. // None
  46. //
  47. // Types
  48. //
  49. typedef struct {
  50. TCHAR TempFile [MAX_PATH];
  51. PCVOID AllocPtr;
  52. PCVOID DetailsPtr;
  53. HANDLE FileHandle;
  54. HANDLE MapHandle;
  55. } ALLOCSTATE, *PALLOCSTATE;
  56. //
  57. // Globals
  58. //
  59. MIG_TRANSPORTSTORAGEID g_ReliableStorageId;
  60. PCTSTR g_TransportPath = NULL;
  61. PCTSTR g_TransportTempPath = NULL;
  62. PCTSTR g_TransportStatus = NULL;
  63. HANDLE g_TransportStatusHandle = NULL;
  64. BOOL g_OtCompressData = FALSE;
  65. BOOL g_OtOldFormat = FALSE;
  66. UINT g_Platform;
  67. MIG_PROGRESSSLICEID g_PersistentSlice;
  68. MIG_PROGRESSSLICEID g_DatabaseSlice;
  69. UINT g_CompressedTicks;
  70. UINT g_CompressedTicked;
  71. MIG_PROGRESSSLICEID g_CompressedSlice;
  72. UINT g_UncompressTicks;
  73. UINT g_UncompressTicked;
  74. MIG_PROGRESSSLICEID g_UncompressSlice;
  75. LONGLONG g_TotalFiles;
  76. LONGLONG g_FilesRead;
  77. //
  78. // Macro expansion list
  79. //
  80. // None
  81. //
  82. // Private function prototypes
  83. //
  84. BOOL
  85. pOtSaveAllState (
  86. IN BOOL Compressed
  87. );
  88. //
  89. // Macro expansion definition
  90. //
  91. // None
  92. //
  93. // Code
  94. //
  95. BOOL
  96. pSetOpaqueTransportStatus (
  97. IN HANDLE TrJournalHandle,
  98. IN BOOL Compressed,
  99. IN DWORD Status
  100. )
  101. {
  102. DWORD signature = OPAQUETR_SIG;
  103. BOOL result = FALSE;
  104. if (BfSetFilePointer (TrJournalHandle, 0)) {
  105. result = TRUE;
  106. result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&signature), sizeof (DWORD));
  107. result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&Compressed), sizeof (BOOL));
  108. result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&Status), sizeof (DWORD));
  109. result = result && FlushFileBuffers (TrJournalHandle);
  110. }
  111. return result;
  112. }
  113. DWORD
  114. pGetOpaqueTransportStatus (
  115. IN PCTSTR TrJournal,
  116. OUT PBOOL Compressed, OPTIONAL
  117. OUT PBOOL OldStorage, OPTIONAL
  118. IN BOOL OpenReadOnly
  119. )
  120. {
  121. HANDLE trJrnHandle;
  122. BOOL compressed = FALSE;
  123. DWORD signature = 0;
  124. DWORD fileSize = 0;
  125. DWORD result = 0;
  126. if (OldStorage) {
  127. *OldStorage = FALSE;
  128. }
  129. if (TrJournal && TrJournal [0]) {
  130. if (OpenReadOnly) {
  131. trJrnHandle = BfOpenReadFile (TrJournal);
  132. } else {
  133. trJrnHandle = BfOpenFile (TrJournal);
  134. }
  135. if (trJrnHandle) {
  136. if (BfSetFilePointer (trJrnHandle, 0)) {
  137. fileSize = GetFileSize (trJrnHandle, NULL);
  138. if (fileSize == (sizeof (BOOL) + sizeof (DWORD))) {
  139. if (OldStorage) {
  140. *OldStorage = TRUE;
  141. }
  142. if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
  143. BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
  144. }
  145. }
  146. if (fileSize == (sizeof (BOOL) + sizeof (DWORD) + sizeof (DWORD))) {
  147. if (BfReadFile (trJrnHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  148. if (signature == OPAQUETR_SIG) {
  149. if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
  150. BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
  151. }
  152. }
  153. if ((signature == OPAQUETR_OLDSIG1) ||
  154. (signature == OPAQUETR_OLDSIG2)
  155. ) {
  156. if (OldStorage) {
  157. *OldStorage = TRUE;
  158. }
  159. if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
  160. BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
  161. }
  162. }
  163. }
  164. }
  165. }
  166. CloseHandle (trJrnHandle);
  167. } else {
  168. if (GetLastError () == ERROR_ACCESS_DENIED) {
  169. result = TRSTATUS_LOCKED;
  170. }
  171. }
  172. }
  173. if (Compressed) {
  174. *Compressed = compressed;
  175. }
  176. return result;
  177. }
  178. PCTSTR
  179. pGetOpaqueImageFile (
  180. IN PCTSTR BasePath,
  181. IN UINT ImageIdx
  182. )
  183. {
  184. TCHAR imageFileName [13];
  185. PCTSTR imageFile = NULL;
  186. HANDLE imageFileHandle = NULL;
  187. wsprintf (imageFileName, S_TRANSPORT_IMG_FILE, ImageIdx);
  188. return JoinPaths (BasePath, imageFileName);
  189. }
  190. PCTSTR
  191. pGetRealTransportPath (
  192. VOID
  193. )
  194. {
  195. return g_OtCompressData?g_TransportTempPath:g_TransportPath;
  196. }
  197. BOOL
  198. WINAPI
  199. OpaqueTransportInitialize (
  200. IN PMIG_LOGCALLBACK LogCallback
  201. )
  202. {
  203. //
  204. // Initialize globals
  205. //
  206. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  207. g_ReliableStorageId = IsmRegisterTransport (S_RELIABLE_STORAGE_TRANSPORT);
  208. return TRUE;
  209. }
  210. VOID
  211. WINAPI
  212. OpaqueTransportEstimateProgressBar (
  213. MIG_PLATFORMTYPEID PlatformTypeId
  214. )
  215. {
  216. UINT ticks;
  217. PMIG_OBJECTCOUNT objectCount;
  218. if (PlatformTypeId == PLATFORM_SOURCE) {
  219. //
  220. // If saving, we know the number of ticks based on the count of the
  221. // persistent attribute.
  222. //
  223. objectCount = IsmGetObjectsStatistics (PLATFORM_SOURCE);
  224. if (objectCount) {
  225. ticks = objectCount->PersistentObjects;
  226. } else {
  227. ticks = 0;
  228. }
  229. g_PersistentSlice = IsmRegisterProgressSlice (ticks, max (1, ticks / 5));
  230. if (g_OtCompressData) {
  231. g_DatabaseSlice = IsmRegisterProgressSlice (3, 1);
  232. } else {
  233. g_DatabaseSlice = IsmRegisterProgressSlice (1, 1);
  234. }
  235. } else {
  236. if (g_OtCompressData) {
  237. g_UncompressTicked = 0;
  238. g_UncompressTicks = 1000;
  239. g_UncompressSlice = IsmRegisterProgressSlice (g_UncompressTicks, 180);
  240. } else {
  241. //
  242. // If restoring, we have almost no work to account for, since
  243. // we download from the secure server file-by-file.
  244. //
  245. DEBUGMSG ((DBG_VERBOSE, "Assuming transport download has no progress impact"));
  246. }
  247. }
  248. }
  249. BOOL
  250. WINAPI
  251. OpaqueTransportQueryCapabilities (
  252. IN MIG_TRANSPORTSTORAGEID TransportStorageId,
  253. OUT PMIG_TRANSPORTTYPE TransportType,
  254. OUT PMIG_TRANSPORTCAPABILITIES Capabilities,
  255. OUT PCTSTR *FriendlyDescription
  256. )
  257. {
  258. if (TransportStorageId != g_ReliableStorageId) {
  259. return FALSE;
  260. }
  261. *TransportType = TRANSPORTTYPE_FULL;
  262. *Capabilities = CAPABILITY_COMPRESSED;
  263. *FriendlyDescription = TEXT("Local computer or another computer on the Network");
  264. return TRUE;
  265. }
  266. VOID
  267. pOtCleanUpTempDir (
  268. VOID
  269. )
  270. {
  271. if (g_TransportTempPath) {
  272. FiRemoveAllFilesInTree (g_TransportTempPath);
  273. }
  274. }
  275. PCTSTR
  276. pOtCreateTemporaryDir (
  277. VOID
  278. )
  279. {
  280. TCHAR tempFile[MAX_PATH];
  281. if (!IsmGetTempDirectory (tempFile, ARRAYSIZE(tempFile))) {
  282. return NULL;
  283. }
  284. return DuplicatePathString (tempFile, 0);
  285. }
  286. BOOL
  287. WINAPI
  288. OpaqueTransportSetStorage (
  289. IN MIG_PLATFORMTYPEID Platform,
  290. IN MIG_TRANSPORTSTORAGEID TransportStorageId,
  291. IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities,
  292. IN PCTSTR StoragePath,
  293. OUT PBOOL Valid,
  294. OUT PBOOL ImageExists
  295. )
  296. {
  297. PCTSTR lastDirPtr = NULL;
  298. PCTSTR transportPath = NULL;
  299. PCTSTR transportStatus = NULL;
  300. HANDLE transportStatusHandle = INVALID_HANDLE_VALUE;
  301. MIG_OBJECTSTRINGHANDLE encodedPath;
  302. DWORD status;
  303. BOOL result = FALSE;
  304. if (Valid) {
  305. *Valid = FALSE;
  306. }
  307. if (ImageExists) {
  308. *ImageExists = FALSE;
  309. }
  310. if (TransportStorageId == g_ReliableStorageId) {
  311. if ((!RequiredCapabilities) || (RequiredCapabilities == CAPABILITY_COMPRESSED)) {
  312. if (RequiredCapabilities == CAPABILITY_COMPRESSED) {
  313. g_OtCompressData = TRUE;
  314. } else {
  315. g_OtCompressData = FALSE;
  316. }
  317. // If this is the destination, let's check if the user included USMT2.UNC in
  318. // the path by mistake. If he did (the StoragePath ends in USMT2.UNC and
  319. // StoragePath has our transport status) we will accept it.
  320. if (Platform == PLATFORM_DESTINATION) {
  321. lastDirPtr = _tcsrchr (StoragePath, TEXT('\\'));
  322. if (lastDirPtr) {
  323. lastDirPtr = _tcsinc (lastDirPtr);
  324. if (lastDirPtr) {
  325. if (StringIMatch (lastDirPtr, S_TRANSPORT_DIR)) {
  326. transportPath = DuplicatePathString (StoragePath, 0);
  327. transportStatus = JoinPaths (transportPath, S_TRANSPORT_STATUS_FILE);
  328. if ((!DoesFileExist (transportPath)) ||
  329. (pGetOpaqueTransportStatus (transportStatus, NULL, NULL, TRUE) != TRSTATUS_READY)
  330. ) {
  331. FreePathString (transportPath);
  332. transportPath = NULL;
  333. FreePathString (transportStatus);
  334. transportStatus = NULL;
  335. }
  336. }
  337. }
  338. }
  339. }
  340. if (!transportPath) {
  341. transportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
  342. }
  343. if (!transportStatus) {
  344. transportStatus = JoinPaths (transportPath, S_TRANSPORT_STATUS_FILE);
  345. }
  346. if (!DoesFileExist (transportPath)) {
  347. // we require UNC path or a full path (like c:\...)
  348. if (transportPath[0] == '\\' && transportPath[1] == '\\') {
  349. // this is a UNC path
  350. *Valid = TRUE;
  351. } else if (transportPath[1] == ':') {
  352. // this is a normal full path
  353. *Valid = TRUE;
  354. } else {
  355. *Valid = FALSE;
  356. }
  357. if ((*Valid) && (Platform == PLATFORM_SOURCE)) {
  358. // we need to actually try to create our transport directory and the status file
  359. // After that we will remove them but this is just the way for us to validate the
  360. // store
  361. *Valid = FALSE;
  362. if (BfCreateDirectory (transportPath)) {
  363. transportStatusHandle = BfCreateFile (transportStatus);
  364. if (transportStatusHandle) {
  365. *Valid = TRUE;
  366. CloseHandle (transportStatusHandle);
  367. }
  368. PushError ();
  369. FiRemoveAllFilesInTree (transportPath);
  370. PopError ();
  371. }
  372. }
  373. *ImageExists = FALSE;
  374. } else {
  375. // we try to open this transport status file with Read/Write. If we
  376. // fail this is either because somebody has it opened or we don't
  377. // have access rights. In both cases we should get back TRSTATUS_LOCKED
  378. status = pGetOpaqueTransportStatus (transportStatus, NULL, NULL, TRUE);
  379. switch (status) {
  380. case TRSTATUS_LOCKED:
  381. *ImageExists = TRUE;
  382. *Valid = FALSE;
  383. break;
  384. case TRSTATUS_READY:
  385. *ImageExists = TRUE;
  386. *Valid = TRUE;
  387. break;
  388. case TRSTATUS_DIRTY:
  389. *ImageExists = FALSE;
  390. *Valid = TRUE;
  391. break;
  392. default:
  393. *ImageExists = FALSE;
  394. *Valid = TRUE;
  395. }
  396. }
  397. result = TRUE;
  398. }
  399. }
  400. if (result && *Valid) {
  401. if (g_TransportPath) {
  402. FreePathString (g_TransportPath);
  403. g_TransportPath = NULL;
  404. }
  405. if (g_TransportStatus) {
  406. FreePathString (g_TransportStatus);
  407. g_TransportStatus = NULL;
  408. }
  409. if (transportPath) {
  410. g_TransportPath = transportPath;
  411. } else {
  412. g_TransportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
  413. }
  414. if (transportStatus) {
  415. g_TransportStatus = transportStatus;
  416. } else {
  417. g_TransportStatus = JoinPaths (g_TransportPath, S_TRANSPORT_STATUS_FILE);
  418. }
  419. encodedPath = IsmCreateSimpleObjectPattern (g_TransportPath, FALSE, NULL, FALSE);
  420. if (encodedPath) {
  421. IsmRegisterStaticExclusion (MIG_FILE_TYPE, encodedPath);
  422. IsmDestroyObjectHandle (encodedPath);
  423. }
  424. }
  425. return result;
  426. }
  427. BOOL
  428. WINAPI
  429. OpaqueTransportSaveState (
  430. VOID
  431. )
  432. {
  433. MIG_APPINFO appInfo;
  434. ERRUSER_EXTRADATA extraData;
  435. DWORD status;
  436. BOOL result = FALSE;
  437. BOOL allowDelete = FALSE;
  438. ZeroMemory (&extraData, sizeof (ERRUSER_EXTRADATA));
  439. extraData.Error = ERRUSER_ERROR_UNKNOWN;
  440. __try {
  441. ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
  442. appInfo.Phase = MIG_TRANSPORT_PHASE;
  443. appInfo.SubPhase = SUBPHASE_PREPARING;
  444. IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
  445. if (!g_TransportPath) {
  446. DEBUGMSG ((DBG_ERROR, "Transport Path is not selected"));
  447. extraData.Error = ERRUSER_ERROR_NOTRANSPORTPATH;
  448. __leave;
  449. }
  450. if (DoesFileExist (g_TransportPath)) {
  451. status = pGetOpaqueTransportStatus (g_TransportStatus, NULL, NULL, FALSE);
  452. switch (status) {
  453. case TRSTATUS_LOCKED:
  454. SetLastError (ERROR_ACCESS_DENIED);
  455. LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, g_TransportPath));
  456. extraData.Error = ERRUSER_ERROR_TRANSPORTPATHBUSY;
  457. __leave;
  458. case TRSTATUS_DIRTY:
  459. result = FiRemoveAllFilesInTree (g_TransportPath);
  460. if (!result) {
  461. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_EMPTY_DIR, g_TransportPath));
  462. extraData.Error = ERRUSER_ERROR_CANTEMPTYDIR;
  463. __leave;
  464. }
  465. break;
  466. case TRSTATUS_READY:
  467. default:
  468. if (IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_EXISTS, 0)) {
  469. if (!FiRemoveAllFilesInTree (g_TransportPath)) {
  470. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_EMPTY_DIR, g_TransportPath));
  471. extraData.Error = ERRUSER_ERROR_CANTEMPTYDIR;
  472. __leave;
  473. }
  474. } else {
  475. LOG ((LOG_ERROR, (PCSTR) MSG_NOT_EMPTY, g_TransportPath));
  476. SetLastError (ERROR_ALREADY_EXISTS);
  477. extraData.Error = ERRUSER_ERROR_ALREADYEXISTS;
  478. __leave;
  479. }
  480. break;
  481. }
  482. }
  483. allowDelete = TRUE;
  484. if (!BfCreateDirectory (g_TransportPath)) {
  485. PushError ();
  486. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_DIR, g_TransportPath));
  487. PopError ();
  488. extraData.Error = ERRUSER_ERROR_CANTCREATEDIR;
  489. __leave;
  490. }
  491. g_TransportStatusHandle = BfCreateFile (g_TransportStatus);
  492. if (!g_TransportStatusHandle) {
  493. PushError ();
  494. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_STATUS_FILE, g_TransportStatus));
  495. PopError ();
  496. extraData.Error = ERRUSER_ERROR_CANTCREATESTATUS;
  497. __leave;
  498. }
  499. result = pSetOpaqueTransportStatus (g_TransportStatusHandle, g_OtCompressData, TRSTATUS_DIRTY);
  500. if (!result) {
  501. PushError ();
  502. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_STATUS_FILE, g_TransportStatus));
  503. PopError ();
  504. extraData.Error = ERRUSER_ERROR_CANTCREATESTATUS;
  505. __leave;
  506. }
  507. g_Platform = PLATFORM_SOURCE;
  508. result = pOtSaveAllState (g_OtCompressData);
  509. if (result) {
  510. result = result && pSetOpaqueTransportStatus (g_TransportStatusHandle, g_OtCompressData, TRSTATUS_READY);
  511. }
  512. result = result && FlushFileBuffers (g_TransportStatusHandle);
  513. result = result && CloseHandle (g_TransportStatusHandle);
  514. if (result) {
  515. g_TransportStatusHandle = NULL;
  516. }
  517. }
  518. __finally {
  519. PushError ();
  520. if (g_TransportStatusHandle) {
  521. // if we got here there was some error. Let's just close the handle
  522. CloseHandle (g_TransportStatusHandle);
  523. }
  524. if (allowDelete && (!result)) {
  525. FiRemoveAllFilesInTree (g_TransportPath);
  526. }
  527. PopError ();
  528. }
  529. PushError ();
  530. if (!result) {
  531. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  532. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  533. }
  534. PopError ();
  535. return result;
  536. }
  537. PCTSTR
  538. pOpaqueGetNewFileName (
  539. IN PCTSTR FileName
  540. )
  541. {
  542. PCTSTR newFileName = NULL;
  543. PTSTR tempPtr1 = NULL;
  544. PCTSTR endStr1 = NULL;
  545. PCTSTR tempPtr2 = NULL;
  546. PCTSTR endStr2 = NULL;
  547. INT i;
  548. // let's modify the file to extract. The file name will
  549. // be split in 2 after the first 5 characters
  550. newFileName = DuplicatePathString (FileName, 1);
  551. if (!newFileName) {
  552. return NULL;
  553. }
  554. tempPtr1 = (PTSTR) GetFileNameFromPath (newFileName);
  555. if (!tempPtr1) {
  556. FreePathString (newFileName);
  557. return NULL;
  558. }
  559. endStr1 = GetEndOfString (newFileName);
  560. if (!endStr1) {
  561. FreePathString (newFileName);
  562. return NULL;
  563. }
  564. tempPtr2 = GetFileNameFromPath (FileName);
  565. if (!tempPtr2) {
  566. FreePathString (newFileName);
  567. return NULL;
  568. }
  569. endStr2 = GetEndOfString (FileName);
  570. if (!endStr2) {
  571. FreePathString (newFileName);
  572. return NULL;
  573. }
  574. for (i = 0; i < 5; i ++) {
  575. tempPtr1 = _tcsinc (tempPtr1);
  576. tempPtr2 = _tcsinc (tempPtr2);
  577. }
  578. if ((tempPtr1 < endStr1) &&
  579. (tempPtr2 < endStr2)
  580. ) {
  581. StringCopy (tempPtr1, TEXT("\\"));
  582. tempPtr1 = _tcsinc (tempPtr1);
  583. StringCopy (tempPtr1, tempPtr2);
  584. } else {
  585. FreePathString (newFileName);
  586. newFileName = NULL;
  587. }
  588. return newFileName;
  589. }
  590. BOOL
  591. pOpaqueCallback (
  592. IN PCTSTR FileToExtract,
  593. IN LONGLONG FileSize,
  594. OUT PBOOL ExtractFile,
  595. IN OUT PCTSTR *NewFileName
  596. )
  597. {
  598. LONGLONG numerator;
  599. LONGLONG divisor;
  600. LONGLONG tick;
  601. UINT delta;
  602. if (NewFileName) {
  603. *NewFileName = pOpaqueGetNewFileName (FileToExtract);
  604. }
  605. g_FilesRead ++;
  606. // now update the progress bar
  607. numerator = (LONGLONG) g_FilesRead * (LONGLONG) g_UncompressTicks;
  608. divisor = (LONGLONG) g_TotalFiles;
  609. if (divisor) {
  610. tick = numerator / divisor;
  611. } else {
  612. tick = 0;
  613. }
  614. delta = (UINT) tick - g_UncompressTicked;
  615. if (delta) {
  616. IsmTickProgressBar (g_UncompressSlice, delta);
  617. g_UncompressTicked += delta;
  618. }
  619. if (ExtractFile) {
  620. *ExtractFile = TRUE;
  621. }
  622. return (!IsmCheckCancel());
  623. }
  624. BOOL
  625. pOtReadAllImages (
  626. VOID
  627. )
  628. {
  629. COMPRESS_HANDLE compressedHandle;
  630. BOOL result = FALSE;
  631. if (CompressOpenHandle (g_TransportPath, S_TRANSPORT_IMG_FILE, 1, &compressedHandle)) {
  632. g_TotalFiles = compressedHandle.FilesStored;
  633. if (CompressExtractAllFiles (g_TransportTempPath, &compressedHandle, pOpaqueCallback)) {
  634. result = TRUE;
  635. }
  636. CompressCleanupHandle (&compressedHandle);
  637. }
  638. return result;
  639. }
  640. BOOL
  641. WINAPI
  642. OpaqueTransportBeginApply (
  643. VOID
  644. )
  645. {
  646. ERRUSER_EXTRADATA extraData;
  647. DWORD status = 0;
  648. PCTSTR memDbFile;
  649. INT_PTR appReply;
  650. PCTSTR newTransDbFile = NULL;
  651. BOOL result = FALSE;
  652. g_Platform = PLATFORM_DESTINATION;
  653. ZeroMemory (&extraData, sizeof (ERRUSER_EXTRADATA));
  654. extraData.Error = ERRUSER_ERROR_UNKNOWN;
  655. __try {
  656. if (!g_TransportPath) {
  657. DEBUGMSG ((DBG_ERROR, "Transport Path is not selected"));
  658. extraData.Error = ERRUSER_ERROR_NOTRANSPORTPATH;
  659. __leave;
  660. }
  661. while (status != TRSTATUS_READY) {
  662. status = pGetOpaqueTransportStatus (g_TransportStatus, &g_OtCompressData, &g_OtOldFormat, TRUE);
  663. switch (status) {
  664. case TRSTATUS_LOCKED:
  665. if (!IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_LOCKED, 0)) {
  666. SetLastError (ERROR_ACCESS_DENIED);
  667. LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, g_TransportPath));
  668. extraData.Error = ERRUSER_ERROR_TRANSPORTPATHBUSY;
  669. __leave;
  670. }
  671. break;
  672. case TRSTATUS_DIRTY:
  673. SetLastError (ERROR_INVALID_DATA);
  674. LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
  675. extraData.Error = ERRUSER_ERROR_TRANSPORTINVALIDIMAGE;
  676. __leave;
  677. case TRSTATUS_READY:
  678. break;
  679. default:
  680. SetLastError (ERROR_INVALID_DATA);
  681. LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
  682. extraData.Error = ERRUSER_ERROR_TRANSPORTINVALIDIMAGE;
  683. __leave;
  684. }
  685. }
  686. if (g_OtOldFormat) {
  687. IsmSendMessageToApp (TRANSPORTMESSAGE_OLD_STORAGE, 0);
  688. SetLastError (ERROR_INVALID_DATA);
  689. LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
  690. extraData.Error = ERRUSER_ERROR_TRANSPORTINVALIDIMAGE;
  691. __leave;
  692. }
  693. g_TransportStatusHandle = BfOpenReadFile (g_TransportStatus);
  694. if (!g_TransportStatusHandle) {
  695. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_STATUS_FILE, g_TransportStatus));
  696. extraData.Error = ERRUSER_ERROR_CANTOPENSTATUS;
  697. __leave;
  698. }
  699. if (g_OtCompressData) {
  700. g_TransportTempPath = pOtCreateTemporaryDir ();
  701. if (!g_TransportTempPath) {
  702. CloseHandle (g_TransportStatusHandle);
  703. g_TransportStatusHandle = NULL;
  704. extraData.Error = ERRUSER_ERROR_CANTCREATETEMPDIR;
  705. __leave;
  706. }
  707. if (!pOtReadAllImages ()) {
  708. CloseHandle (g_TransportStatusHandle);
  709. g_TransportStatusHandle = NULL;
  710. extraData.Error = ERRUSER_ERROR_CANTUNPACKIMAGE;
  711. __leave;
  712. }
  713. CloseHandle (g_TransportStatusHandle);
  714. g_TransportStatusHandle = NULL;
  715. }
  716. newTransDbFile = pOpaqueGetNewFileName (S_TRANSPORT_DAT_FILE);
  717. memDbFile = JoinPaths (pGetRealTransportPath (), newTransDbFile?newTransDbFile:S_TRANSPORT_DAT_FILE);
  718. if (newTransDbFile) {
  719. FreePathString (newTransDbFile);
  720. newTransDbFile = NULL;
  721. }
  722. result = MemDbLoad (memDbFile);
  723. if (!result) {
  724. extraData.Error = ERRUSER_ERROR_CANTREADIMAGE;
  725. }
  726. FreePathString (memDbFile);
  727. }
  728. __finally {
  729. }
  730. if (!result) {
  731. extraData.ErrorArea = ERRUSER_AREA_LOAD;
  732. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  733. }
  734. return result;
  735. }
  736. VOID
  737. WINAPI
  738. OpaqueTransportEndApply (
  739. VOID
  740. )
  741. {
  742. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  743. if (g_OtCompressData) {
  744. pOtCleanUpTempDir ();
  745. } else {
  746. CloseHandle (g_TransportStatusHandle);
  747. g_TransportStatusHandle = NULL;
  748. }
  749. }
  750. VOID
  751. WINAPI
  752. OpaqueTransportTerminate (
  753. VOID
  754. )
  755. {
  756. pOtCleanUpTempDir();
  757. if (g_TransportTempPath) {
  758. FreePathString (g_TransportTempPath);
  759. g_TransportTempPath = NULL;
  760. }
  761. if (g_TransportStatus) {
  762. FreePathString (g_TransportStatus);
  763. g_TransportStatus = NULL;
  764. }
  765. if (g_TransportPath) {
  766. FreePathString (g_TransportPath);
  767. g_TransportPath = NULL;
  768. }
  769. }
  770. static
  771. VOID
  772. pGetTempFileName (
  773. OUT PTSTR Buffer
  774. )
  775. {
  776. static fileIndex = 0;
  777. fileIndex ++;
  778. wsprintf (Buffer, TEXT("%08X.DAT"), fileIndex);
  779. }
  780. PCTSTR
  781. pOpaqueAllocStorageFileName (
  782. IN PCTSTR FileName OPTIONAL
  783. )
  784. {
  785. TCHAR buffer[32];
  786. if (FileName) {
  787. StringCopy (buffer, FileName);
  788. } else {
  789. pGetTempFileName (buffer);
  790. }
  791. return JoinPaths (g_TransportPath, buffer);
  792. }
  793. VOID
  794. pFreeStorageFileName (
  795. IN PCTSTR FileName
  796. )
  797. {
  798. FreePathString (FileName);
  799. }
  800. BOOL
  801. pOpaqueSaveDetails (
  802. IN PCTSTR DecoratedObject,
  803. IN PMIG_DETAILS Details
  804. )
  805. {
  806. PCTSTR key;
  807. BOOL b = FALSE;
  808. if ((!Details) || (!Details->DetailsSize)) {
  809. return TRUE;
  810. }
  811. key = JoinText (S_DETAILS_PREFIX, DecoratedObject);
  812. if (key) {
  813. b = (MemDbSetUnorderedBlob (key, 0, Details->DetailsData, Details->DetailsSize) != 0);
  814. FreeText (key);
  815. }
  816. return b;
  817. }
  818. BOOL
  819. pOtAddFileToImage (
  820. IN PCTSTR FileName,
  821. IN PCTSTR StoredName,
  822. IN OUT PCOMPRESS_HANDLE CompressedHandle
  823. )
  824. {
  825. return CompressAddFileToHandle (FileName, StoredName, CompressedHandle);
  826. }
  827. BOOL
  828. pOtSaveContentInFile (
  829. IN MIG_OBJECTTYPEID ObjectTypeId,
  830. IN PCTSTR EncodedFileName,
  831. IN PCTSTR DecoratedObject,
  832. IN PMIG_CONTENT Content,
  833. IN OUT PCOMPRESS_HANDLE CompressedHandle OPTIONAL
  834. )
  835. {
  836. BOOL result = FALSE;
  837. PCTSTR destPath = NULL;
  838. DWORD attributes = INVALID_ATTRIBUTES;
  839. MYASSERT (Content->ContentInFile);
  840. if (!Content->ContentInFile) {
  841. return FALSE;
  842. }
  843. //
  844. // Use the CopyFile API to move the file from local to storage.
  845. //
  846. __try {
  847. if (Content && (Content->Details.DetailsSize == sizeof (WIN32_FIND_DATAW)) && Content->Details.DetailsData) {
  848. attributes = ((PWIN32_FIND_DATAW)Content->Details.DetailsData)->dwFileAttributes;
  849. }
  850. if ((attributes != INVALID_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
  851. // this must be a directory, let's just write the key
  852. if (!MemDbSetValue (DecoratedObject, TRFLAG_FILE)) {
  853. __leave;
  854. }
  855. } else {
  856. //
  857. // Get a temp file, assemble the src path, copy the file
  858. //
  859. destPath = pOpaqueAllocStorageFileName (NULL);
  860. if (!destPath) {
  861. __leave;
  862. }
  863. if (CompressedHandle) {
  864. if (!pOtAddFileToImage (Content->FileContent.ContentPath, GetFileNameFromPath (destPath), CompressedHandle)) {
  865. __leave;
  866. }
  867. } else {
  868. if (!CopyFile (Content->FileContent.ContentPath, destPath, FALSE)) {
  869. __leave;
  870. }
  871. }
  872. //
  873. // Keep track of where the file went
  874. //
  875. if (!MemDbSetValue (DecoratedObject, TRFLAG_FILE)) {
  876. __leave;
  877. }
  878. if (!MemDbAddSingleLinkage (DecoratedObject, GetFileNameFromPath (destPath), 0)) {
  879. __leave;
  880. }
  881. }
  882. //
  883. // Save details
  884. //
  885. result = pOpaqueSaveDetails (DecoratedObject, &(Content->Details));
  886. }
  887. __finally {
  888. pFreeStorageFileName (destPath);
  889. INVALID_POINTER (destPath);
  890. }
  891. return result;
  892. }
  893. BOOL
  894. pOtSaveContentInMemory (
  895. IN MIG_OBJECTTYPEID ObjectTypeId,
  896. IN PCTSTR EncodedObjectName,
  897. IN PCTSTR DecoratedObject,
  898. IN PMIG_CONTENT Content
  899. )
  900. {
  901. BOOL result = FALSE;
  902. MYASSERT (!Content->ContentInFile);
  903. if (Content->ContentInFile) {
  904. return FALSE;
  905. }
  906. MemDbSetValue (DecoratedObject, TRFLAG_MEMORY);
  907. if (Content->MemoryContent.ContentBytes && Content->MemoryContent.ContentSize) {
  908. MemDbSetUnorderedBlob (
  909. DecoratedObject,
  910. 0,
  911. Content->MemoryContent.ContentBytes,
  912. Content->MemoryContent.ContentSize
  913. );
  914. }
  915. result = pOpaqueSaveDetails (DecoratedObject, &(Content->Details));
  916. return result;
  917. }
  918. PCTSTR
  919. pOpaqueBuildDecoratedObject (
  920. IN MIG_OBJECTTYPEID ObjectTypeId,
  921. IN ENCODEDSTRHANDLE ObjectName
  922. )
  923. {
  924. TCHAR prefix[32];
  925. wsprintf (prefix, TEXT("%u"), ObjectTypeId);
  926. return JoinPaths (prefix, ObjectName);
  927. }
  928. VOID
  929. pOtDestroyDecoratedObject (
  930. IN PCTSTR String
  931. )
  932. {
  933. FreePathString (String);
  934. }
  935. BOOL
  936. pOtSaveAllState (
  937. IN BOOL Compressed
  938. )
  939. {
  940. MIG_APPINFO appInfo;
  941. MIG_CONTENT value;
  942. PMIG_CONTENT convValue;
  943. ULONGLONG size;
  944. MIG_OBJECTWITHATTRIBUTE_ENUM objEnum;
  945. PCTSTR ourDbFile = NULL;
  946. PCTSTR decoratedObject = NULL;
  947. ULONGLONG bytesSaved = 0;
  948. UINT lastTick = GetTickCount();
  949. TCHAR text[64];
  950. UINT fraction;
  951. COMPRESS_HANDLE compressedHandle;
  952. INT_PTR appReply;
  953. BOOL okSave = FALSE;
  954. TRANSCOPY_ERROR transCopyError;
  955. ERRUSER_EXTRADATA extraData;
  956. BOOL result = FALSE;
  957. __try {
  958. ZeroMemory (&compressedHandle, sizeof (COMPRESS_HANDLE));
  959. if (Compressed) {
  960. g_TransportTempPath = pOtCreateTemporaryDir ();
  961. if (!g_TransportTempPath) {
  962. extraData.Error = ERRUSER_ERROR_CANTCREATETEMPDIR;
  963. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  964. extraData.ObjectTypeId = 0;
  965. extraData.ObjectName = NULL;
  966. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  967. __leave;
  968. }
  969. if (!CompressCreateHandle (g_TransportPath, S_TRANSPORT_IMG_FILE, 1, 0, &compressedHandle)) {
  970. extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
  971. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  972. extraData.ObjectTypeId = 0;
  973. extraData.ObjectName = NULL;
  974. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  975. __leave;
  976. }
  977. }
  978. //
  979. // Enumerate all objects with "save" attribute
  980. //
  981. if (IsmEnumFirstPersistentObject (&objEnum)) {
  982. do {
  983. //
  984. // For each object to be saved, do the appropriate
  985. // data copy action
  986. //
  987. okSave = FALSE;
  988. while (!okSave) {
  989. if (!IsmAcquireObjectEx (
  990. objEnum.ObjectTypeId,
  991. objEnum.ObjectName,
  992. &value,
  993. CONTENTTYPE_ANY,
  994. 0
  995. )) {
  996. transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
  997. transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
  998. transCopyError.Error = GetLastError ();
  999. if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.ObjectName)) {
  1000. appReply = APPRESPONSE_IGNORE;
  1001. } else {
  1002. appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError);
  1003. if ((appReply == APPRESPONSE_NONE) ||
  1004. (appReply == APPRESPONSE_FAIL)
  1005. ) {
  1006. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName));
  1007. IsmReleaseMemory (transCopyError.ObjectName);
  1008. extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
  1009. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1010. extraData.ObjectTypeId = objEnum.ObjectTypeId;
  1011. extraData.ObjectName = objEnum.ObjectName;
  1012. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1013. IsmAbortPersistentObjectEnum (&objEnum);
  1014. __leave;
  1015. }
  1016. }
  1017. if (appReply == APPRESPONSE_IGNORE) {
  1018. LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
  1019. IsmReleaseMemory (transCopyError.ObjectName);
  1020. extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
  1021. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1022. extraData.ObjectTypeId = objEnum.ObjectTypeId;
  1023. extraData.ObjectName = objEnum.ObjectName;
  1024. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData));
  1025. break;
  1026. }
  1027. IsmReleaseMemory (transCopyError.ObjectName);
  1028. continue;
  1029. }
  1030. okSave = TRUE;
  1031. }
  1032. if (okSave) {
  1033. #ifdef UNICODE
  1034. convValue = &value;
  1035. #else
  1036. // now let's convert this object content to UNICODE
  1037. convValue = IsmConvertObjectContentToUnicode (objEnum.ObjectTypeId, objEnum.ObjectName, &value);
  1038. if (!convValue) {
  1039. convValue = &value;
  1040. }
  1041. #endif
  1042. decoratedObject = pOpaqueBuildDecoratedObject (objEnum.ObjectTypeId, objEnum.ObjectName);
  1043. ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
  1044. appInfo.Phase = MIG_TRANSPORT_PHASE;
  1045. appInfo.SubPhase = SUBPHASE_COMPRESSING;
  1046. appInfo.ObjectTypeId = (objEnum.ObjectTypeId & (~PLATFORM_MASK));
  1047. appInfo.ObjectName = objEnum.ObjectName;
  1048. IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
  1049. if (convValue->ContentInFile) {
  1050. okSave = FALSE;
  1051. while (!okSave) {
  1052. if (!pOtSaveContentInFile (objEnum.ObjectTypeId, objEnum.ObjectName, decoratedObject, convValue, &compressedHandle)) {
  1053. if (GetLastError () == ERROR_DISK_FULL) {
  1054. // we just failed because we don't have enough space on the destination
  1055. // path. Let's tell that to the user
  1056. extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
  1057. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1058. extraData.ObjectTypeId = 0;
  1059. extraData.ObjectName = NULL;
  1060. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1061. __leave;
  1062. }
  1063. transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
  1064. transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
  1065. transCopyError.Error = GetLastError ();
  1066. if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.ObjectName)) {
  1067. appReply = APPRESPONSE_IGNORE;
  1068. } else {
  1069. appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError);
  1070. if ((appReply == APPRESPONSE_NONE) ||
  1071. (appReply == APPRESPONSE_FAIL)
  1072. ) {
  1073. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName));
  1074. IsmReleaseMemory (transCopyError.ObjectName);
  1075. extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
  1076. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1077. extraData.ObjectTypeId = objEnum.ObjectTypeId;
  1078. extraData.ObjectName = objEnum.ObjectName;
  1079. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1080. IsmAbortPersistentObjectEnum (&objEnum);
  1081. __leave;
  1082. }
  1083. }
  1084. if (appReply == APPRESPONSE_IGNORE) {
  1085. LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
  1086. IsmReleaseMemory (transCopyError.ObjectName);
  1087. extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
  1088. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1089. extraData.ObjectTypeId = objEnum.ObjectTypeId;
  1090. extraData.ObjectName = objEnum.ObjectName;
  1091. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData));
  1092. break;
  1093. }
  1094. IsmReleaseMemory (transCopyError.ObjectName);
  1095. continue;
  1096. }
  1097. okSave = TRUE;
  1098. }
  1099. size = convValue->FileContent.ContentSize;
  1100. } else {
  1101. okSave = FALSE;
  1102. while (!okSave) {
  1103. if (!pOtSaveContentInMemory (objEnum.ObjectTypeId, objEnum.ObjectName, decoratedObject, convValue)) {
  1104. if (GetLastError () == ERROR_DISK_FULL) {
  1105. // we just failed because we don't have enough space on the destination
  1106. // path. Let's tell that to the user
  1107. extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
  1108. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1109. extraData.ObjectTypeId = 0;
  1110. extraData.ObjectName = NULL;
  1111. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1112. __leave;
  1113. }
  1114. transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
  1115. transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
  1116. transCopyError.Error = GetLastError ();
  1117. if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.ObjectName)) {
  1118. appReply = APPRESPONSE_IGNORE;
  1119. } else {
  1120. appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError);
  1121. if ((appReply == APPRESPONSE_NONE) ||
  1122. (appReply == APPRESPONSE_FAIL)
  1123. ) {
  1124. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName));
  1125. IsmReleaseMemory (transCopyError.ObjectName);
  1126. extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
  1127. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1128. extraData.ObjectTypeId = objEnum.ObjectTypeId;
  1129. extraData.ObjectName = objEnum.ObjectName;
  1130. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1131. IsmAbortPersistentObjectEnum (&objEnum);
  1132. __leave;
  1133. }
  1134. }
  1135. if (appReply == APPRESPONSE_IGNORE) {
  1136. LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
  1137. IsmReleaseMemory (transCopyError.ObjectName);
  1138. extraData.Error = ERRUSER_ERROR_CANTSAVEOBJECT;
  1139. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1140. extraData.ObjectTypeId = objEnum.ObjectTypeId;
  1141. extraData.ObjectName = objEnum.ObjectName;
  1142. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYWARNING, (ULONG_PTR)(&extraData));
  1143. break;
  1144. }
  1145. IsmReleaseMemory (transCopyError.ObjectName);
  1146. continue;
  1147. }
  1148. okSave = TRUE;
  1149. }
  1150. size = convValue->MemoryContent.ContentSize;
  1151. }
  1152. #ifndef UNICODE
  1153. if (convValue != (&value)) {
  1154. IsmFreeConvertedObjectContent (objEnum.ObjectTypeId, convValue);
  1155. }
  1156. #endif
  1157. IsmReleaseObject (&value);
  1158. pOtDestroyDecoratedObject (decoratedObject);
  1159. decoratedObject = NULL;
  1160. }
  1161. IsmTickProgressBar (g_PersistentSlice, 1);
  1162. if (IsmCheckCancel()) {
  1163. __leave;
  1164. }
  1165. //
  1166. // Send bytes saved to app every 3 seconds
  1167. //
  1168. bytesSaved += size;
  1169. if (GetTickCount() - lastTick > 3000) {
  1170. if (bytesSaved < 1048576) {
  1171. wsprintf (text, TEXT("Saved: %u K"), (UINT) (bytesSaved / 1024));
  1172. } else if (bytesSaved < 8388608) {
  1173. fraction = (UINT) (bytesSaved / 10485);
  1174. wsprintf (text, TEXT("Saved: %u.%02u M"), fraction / 100, fraction % 100);
  1175. } else if (bytesSaved < 1073741824) {
  1176. wsprintf (text, TEXT("Saved: %u M"), (UINT) (bytesSaved / 1048576));
  1177. } else {
  1178. fraction = (UINT) (bytesSaved / 10737418);
  1179. wsprintf (text, TEXT("Saved: %u.%02u G"), fraction / 100, fraction % 100);
  1180. }
  1181. IsmSendMessageToApp (TRANSPORTMESSAGE_SIZE_SAVED, (ULONG_PTR) text);
  1182. lastTick = GetTickCount();
  1183. }
  1184. } while (IsmEnumNextPersistentObject (&objEnum));
  1185. }
  1186. if (IsmCheckCancel()) {
  1187. __leave;
  1188. }
  1189. ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
  1190. appInfo.Phase = MIG_TRANSPORT_PHASE;
  1191. appInfo.SubPhase = SUBPHASE_FINISHING;
  1192. IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR)(&appInfo));
  1193. if (Compressed) {
  1194. ourDbFile = JoinPaths (g_TransportTempPath, S_TRANSPORT_DAT_FILE);
  1195. } else {
  1196. ourDbFile = pOpaqueAllocStorageFileName (S_TRANSPORT_DAT_FILE);
  1197. if (!ourDbFile) {
  1198. extraData.Error = ERRUSER_ERROR_CANTSAVEINTERNALDATA;
  1199. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1200. extraData.ObjectTypeId = 0;
  1201. extraData.ObjectName = NULL;
  1202. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1203. __leave;
  1204. }
  1205. }
  1206. if (!MemDbSave (ourDbFile)) {
  1207. extraData.Error = ERRUSER_ERROR_CANTSAVEINTERNALDATA;
  1208. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1209. extraData.ObjectTypeId = 0;
  1210. extraData.ObjectName = NULL;
  1211. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1212. __leave;
  1213. }
  1214. IsmTickProgressBar (g_DatabaseSlice, 1);
  1215. if (Compressed) {
  1216. if (IsmCheckCancel()) {
  1217. __leave;
  1218. }
  1219. if (!pOtAddFileToImage (ourDbFile, S_TRANSPORT_DAT_FILE, &compressedHandle)) {
  1220. extraData.Error = ERRUSER_ERROR_CANTSAVEINTERNALDATA;
  1221. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1222. extraData.ObjectTypeId = 0;
  1223. extraData.ObjectName = NULL;
  1224. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1225. __leave;
  1226. }
  1227. IsmTickProgressBar (g_DatabaseSlice, 1);
  1228. if (IsmCheckCancel()) {
  1229. __leave;
  1230. }
  1231. if (!CompressFlushAndCloseHandle (&compressedHandle)) {
  1232. extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
  1233. extraData.ErrorArea = ERRUSER_AREA_SAVE;
  1234. extraData.ObjectTypeId = 0;
  1235. extraData.ObjectName = NULL;
  1236. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  1237. __leave;
  1238. }
  1239. IsmTickProgressBar (g_DatabaseSlice, 1);
  1240. if (IsmCheckCancel()) {
  1241. __leave;
  1242. }
  1243. }
  1244. IsmSendMessageToApp (TRANSPORTMESSAGE_SIZE_SAVED, 0);
  1245. result = TRUE;
  1246. }
  1247. __finally {
  1248. PushError ();
  1249. CompressCleanupHandle (&compressedHandle);
  1250. pFreeStorageFileName (ourDbFile);
  1251. INVALID_POINTER (ourDbFile);
  1252. pOtDestroyDecoratedObject (decoratedObject);
  1253. INVALID_POINTER (decoratedObject);
  1254. if (g_OtCompressData && g_TransportTempPath) {
  1255. pOtCleanUpTempDir ();
  1256. }
  1257. PopError ();
  1258. }
  1259. return result;
  1260. }
  1261. BOOL
  1262. WINAPI
  1263. OpaqueTransportAcquireObject (
  1264. IN MIG_OBJECTTYPEID ObjectTypeId,
  1265. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1266. OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED
  1267. IN MIG_CONTENTTYPE ContentType,
  1268. IN UINT MemoryContentLimit
  1269. )
  1270. {
  1271. UINT value;
  1272. PCBYTE memValue;
  1273. UINT memValueSize;
  1274. PCTSTR fileValue = NULL;
  1275. PCTSTR newFileValue = NULL;
  1276. BOOL valueInFile;
  1277. KEYHANDLE keyHandle;
  1278. PALLOCSTATE allocState;
  1279. PCTSTR detailsKey = NULL;
  1280. PBYTE details;
  1281. UINT detailsSize;
  1282. PCTSTR sourceFile;
  1283. PCTSTR decoratedObject = NULL;
  1284. HANDLE fileHandle;
  1285. BOOL result = FALSE;
  1286. if (!ObjectContent) {
  1287. return FALSE;
  1288. }
  1289. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  1290. MYASSERT ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE);
  1291. decoratedObject = pOpaqueBuildDecoratedObject (ObjectTypeId, ObjectName);
  1292. allocState = (PALLOCSTATE) MemAllocZeroed (sizeof (ALLOCSTATE));
  1293. if (MemDbGetValue (decoratedObject, &value)) {
  1294. if (value == TRFLAG_FILE) {
  1295. valueInFile = TRUE;
  1296. keyHandle = MemDbGetSingleLinkage (decoratedObject, 0, 0);
  1297. if (keyHandle) {
  1298. fileValue = MemDbGetKeyFromHandle (keyHandle, 0);
  1299. newFileValue = pOpaqueGetNewFileName (fileValue);
  1300. result = fileValue != NULL;
  1301. } else {
  1302. fileValue = NULL;
  1303. result = TRUE;
  1304. }
  1305. } else if (value == TRFLAG_MEMORY) {
  1306. valueInFile = FALSE;
  1307. memValueSize = 0;
  1308. memValue = MemDbGetUnorderedBlob (decoratedObject, 0, &memValueSize);
  1309. result = TRUE;
  1310. } else {
  1311. LOG ((LOG_ERROR, (PCSTR) MSG_UNSUPPORTED_DATA, value));
  1312. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  1313. }
  1314. if (result) {
  1315. result = FALSE;
  1316. if (valueInFile) {
  1317. if ((ContentType == CONTENTTYPE_ANY) ||
  1318. (ContentType == CONTENTTYPE_FILE) ||
  1319. (ContentType == CONTENTTYPE_DETAILS_ONLY)
  1320. ) {
  1321. // this is stored as a file and it's wanted as a file
  1322. ObjectContent->ObjectTypeId = ObjectTypeId;
  1323. ObjectContent->ContentInFile = TRUE;
  1324. if (fileValue) {
  1325. ObjectContent->FileContent.ContentPath = JoinPaths (pGetRealTransportPath (), newFileValue?newFileValue:fileValue);
  1326. ObjectContent->FileContent.ContentSize = BfGetFileSize (ObjectContent->FileContent.ContentPath);
  1327. } else {
  1328. ObjectContent->FileContent.ContentSize = 0;
  1329. ObjectContent->FileContent.ContentPath = NULL;
  1330. }
  1331. result = TRUE;
  1332. } else {
  1333. // this is stored as a file and it's wanted as memory
  1334. ObjectContent->ObjectTypeId = ObjectTypeId;
  1335. ObjectContent->ContentInFile = FALSE;
  1336. if (fileValue) {
  1337. sourceFile = JoinPaths (pGetRealTransportPath (), newFileValue?newFileValue:fileValue);
  1338. ObjectContent->MemoryContent.ContentSize = (UINT) BfGetFileSize (sourceFile);
  1339. ObjectContent->MemoryContent.ContentBytes = MapFileIntoMemory (
  1340. sourceFile,
  1341. &allocState->FileHandle,
  1342. &allocState->MapHandle
  1343. );
  1344. FreePathString (sourceFile);
  1345. result = (ObjectContent->MemoryContent.ContentBytes != NULL);
  1346. } else {
  1347. ObjectContent->MemoryContent.ContentSize = 0;
  1348. ObjectContent->MemoryContent.ContentBytes = NULL;
  1349. result = TRUE;
  1350. }
  1351. }
  1352. if (newFileValue) {
  1353. FreePathString (newFileValue);
  1354. newFileValue = NULL;
  1355. }
  1356. if (fileValue) {
  1357. MemDbReleaseMemory (fileValue);
  1358. fileValue = NULL;
  1359. }
  1360. } else {
  1361. if ((ContentType == CONTENTTYPE_ANY) ||
  1362. (ContentType == CONTENTTYPE_MEMORY) ||
  1363. (ContentType == CONTENTTYPE_DETAILS_ONLY)
  1364. ) {
  1365. // this is stored as memory and it's wanted as memory
  1366. ObjectContent->ObjectTypeId = ObjectTypeId;
  1367. ObjectContent->ContentInFile = FALSE;
  1368. ObjectContent->MemoryContent.ContentSize = memValueSize;
  1369. ObjectContent->MemoryContent.ContentBytes = memValue;
  1370. result = TRUE;
  1371. } else {
  1372. // this is stored as memory and it's wanted as a file
  1373. if (memValue) {
  1374. if (IsmGetTempFile (allocState->TempFile, ARRAYSIZE(allocState->TempFile))) {
  1375. fileHandle = BfCreateFile (allocState->TempFile);
  1376. if (fileHandle) {
  1377. if (BfWriteFile (fileHandle, memValue, memValueSize)) {
  1378. ObjectContent->ObjectTypeId = ObjectTypeId;
  1379. ObjectContent->ContentInFile = TRUE;
  1380. ObjectContent->FileContent.ContentSize = memValueSize;
  1381. ObjectContent->FileContent.ContentPath = DuplicatePathString (allocState->TempFile, 0);
  1382. result = TRUE;
  1383. }
  1384. CloseHandle (fileHandle);
  1385. }
  1386. }
  1387. MemDbReleaseMemory (memValue);
  1388. } else {
  1389. ObjectContent->ObjectTypeId = ObjectTypeId;
  1390. ObjectContent->ContentInFile = TRUE;
  1391. ObjectContent->FileContent.ContentSize = 0;
  1392. ObjectContent->FileContent.ContentPath = NULL;
  1393. }
  1394. }
  1395. }
  1396. }
  1397. } else {
  1398. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  1399. }
  1400. if (result) {
  1401. //
  1402. // Fill the details
  1403. //
  1404. detailsKey = JoinText (S_DETAILS_PREFIX, decoratedObject);
  1405. details = MemDbGetUnorderedBlob (detailsKey, 0, &detailsSize);
  1406. if (!details) {
  1407. detailsSize = 0;
  1408. }
  1409. allocState->DetailsPtr = details;
  1410. ObjectContent->Details.DetailsSize = detailsSize;
  1411. ObjectContent->Details.DetailsData = details;
  1412. FreeText (detailsKey);
  1413. ObjectContent->TransHandle = allocState;
  1414. }
  1415. if (!result) {
  1416. FreeAlloc (allocState);
  1417. }
  1418. FreePathString (decoratedObject);
  1419. return result;
  1420. }
  1421. BOOL
  1422. WINAPI
  1423. OpaqueTransportReleaseObject (
  1424. IN OUT PMIG_CONTENT ObjectContent
  1425. )
  1426. {
  1427. PALLOCSTATE allocState;
  1428. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  1429. allocState = (PALLOCSTATE) ObjectContent->TransHandle;
  1430. if (ObjectContent->ContentInFile) {
  1431. FreePathString (ObjectContent->FileContent.ContentPath);
  1432. if (allocState && allocState->TempFile[0]) {
  1433. DeleteFile (allocState->TempFile);
  1434. }
  1435. } else {
  1436. if (allocState && allocState->FileHandle && allocState->MapHandle) {
  1437. UnmapFile (
  1438. ObjectContent->MemoryContent.ContentBytes,
  1439. allocState->MapHandle,
  1440. allocState->FileHandle
  1441. );
  1442. } else {
  1443. MemDbReleaseMemory (ObjectContent->MemoryContent.ContentBytes);
  1444. }
  1445. }
  1446. if (allocState && allocState->DetailsPtr) {
  1447. MemDbReleaseMemory (allocState->DetailsPtr);
  1448. }
  1449. FreeAlloc (allocState);
  1450. return TRUE;
  1451. }