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.

1309 lines
37 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. #define DBG_OPAQUE "OpaqueUnc"
  18. //
  19. // Strings
  20. //
  21. #define S_TRANSPORT_DIR TEXT("USMT2.UNC")
  22. #define S_TRANSPORT_DAT_FILE TEXT("TRANSDB.DAT")
  23. #define S_TRANSPORT_IMG_FILE TEXT("IMG%05X.DAT")
  24. #define S_TRANSPORT_DSK_FILE TEXT("DSK%05X")
  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 OPAQUETR_SIG 0x55534D32 //USM2
  36. #define TRSTATUS_DIRTY 0x00000001
  37. #define TRSTATUS_READY 0x00000002
  38. #define TRSTATUS_LOCKED 0x00000003
  39. //
  40. // Macros
  41. //
  42. // None
  43. //
  44. // Types
  45. //
  46. typedef struct {
  47. TCHAR TempFile [MAX_PATH];
  48. PCVOID AllocPtr;
  49. PCVOID DetailsPtr;
  50. HANDLE FileHandle;
  51. HANDLE MapHandle;
  52. } ALLOCSTATE, *PALLOCSTATE;
  53. //
  54. // Globals
  55. //
  56. MIG_TRANSPORTSTORAGEID g_ReliableStorageId;
  57. PCTSTR g_TransportPath = NULL;
  58. PCTSTR g_TransportTempPath = NULL;
  59. PCTSTR g_TransportStatus = NULL;
  60. HANDLE g_TransportStatusHandle = NULL;
  61. BOOL g_OtCompressData = FALSE;
  62. UINT g_Platform;
  63. MIG_PROGRESSSLICEID g_DatabaseSlice;
  64. MIG_PROGRESSSLICEID g_PersistentSlice;
  65. //
  66. // Macro expansion list
  67. //
  68. // None
  69. //
  70. // Private function prototypes
  71. //
  72. BOOL
  73. pOtSaveAllState (
  74. IN BOOL Compressed
  75. );
  76. //
  77. // Macro expansion definition
  78. //
  79. // None
  80. //
  81. // Code
  82. //
  83. BOOL
  84. pSetOpaqueTransportStatus (
  85. IN HANDLE TrJournalHandle,
  86. IN BOOL Compressed,
  87. IN DWORD Status
  88. )
  89. {
  90. DWORD signature = OPAQUETR_SIG;
  91. BOOL result = FALSE;
  92. if (BfSetFilePointer (TrJournalHandle, 0)) {
  93. result = TRUE;
  94. result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&signature), sizeof (DWORD));
  95. result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&Compressed), sizeof (BOOL));
  96. result = result && BfWriteFile (TrJournalHandle, (PBYTE)(&Status), sizeof (DWORD));
  97. result = result && FlushFileBuffers (TrJournalHandle);
  98. }
  99. return result;
  100. }
  101. DWORD
  102. pGetOpaqueTransportStatus (
  103. IN PCTSTR TrJournal,
  104. OUT PBOOL Compressed OPTIONAL
  105. )
  106. {
  107. HANDLE trJrnHandle;
  108. BOOL compressed = FALSE;
  109. DWORD signature = 0;
  110. DWORD result = 0;
  111. if (TrJournal && TrJournal [0]) {
  112. trJrnHandle = BfOpenReadFile (TrJournal);
  113. if (trJrnHandle) {
  114. if (BfSetFilePointer (trJrnHandle, 0)) {
  115. if (BfReadFile (trJrnHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  116. if (signature == OPAQUETR_SIG) {
  117. if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
  118. BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
  119. }
  120. }
  121. }
  122. }
  123. CloseHandle (trJrnHandle);
  124. } else {
  125. if (GetLastError () == ERROR_ACCESS_DENIED) {
  126. result = TRSTATUS_LOCKED;
  127. }
  128. }
  129. }
  130. if (Compressed) {
  131. *Compressed = compressed;
  132. }
  133. return result;
  134. }
  135. PCTSTR
  136. pGetOpaqueImageFile (
  137. IN PCTSTR BasePath,
  138. IN UINT ImageIdx
  139. )
  140. {
  141. TCHAR imageFileName [13];
  142. PCTSTR imageFile = NULL;
  143. HANDLE imageFileHandle = NULL;
  144. wsprintf (imageFileName, S_TRANSPORT_IMG_FILE, ImageIdx);
  145. return JoinPaths (BasePath, imageFileName);
  146. }
  147. PCTSTR
  148. pGetRealTransportPath (
  149. VOID
  150. )
  151. {
  152. return g_OtCompressData?g_TransportTempPath:g_TransportPath;
  153. }
  154. BOOL
  155. WINAPI
  156. OpaqueTransportInitialize (
  157. IN PMIG_LOGCALLBACK LogCallback
  158. )
  159. {
  160. //
  161. // Initialize globals
  162. //
  163. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  164. g_ReliableStorageId = IsmRegisterTransport (S_RELIABLE_STORAGE_TRANSPORT);
  165. return TRUE;
  166. }
  167. VOID
  168. WINAPI
  169. OpaqueTransportEstimateProgressBar (
  170. MIG_PLATFORMTYPEID PlatformTypeId
  171. )
  172. {
  173. UINT ticks;
  174. MIG_OBJECTSTRINGHANDLE pattern;
  175. PMIG_OBJECTCOUNT objectCount;
  176. if (PlatformTypeId == PLATFORM_SOURCE) {
  177. //
  178. // If saving, we know the number of ticks based on
  179. // the count of the persistent attribute.
  180. //
  181. objectCount = IsmGetObjectsStatistics (PLATFORM_SOURCE);
  182. if (objectCount) {
  183. ticks = objectCount->PersistentObjects;
  184. } else {
  185. ticks = 0;
  186. }
  187. g_PersistentSlice = IsmRegisterProgressSlice (ticks, max (1, ticks / 5));
  188. ticks = 0;
  189. pattern = IsmCreateObjectPattern (ALL_PATTERN, 0, ALL_PATTERN, 0);
  190. IsmDestroyObjectHandle (pattern);
  191. g_DatabaseSlice = IsmRegisterProgressSlice (ticks, ticks * 3);
  192. } else {
  193. //
  194. // If restoring, we have almost no work to account for, since
  195. // we download from the secure server file-by-file.
  196. //
  197. DEBUGMSG ((DBG_VERBOSE, "Assuming transport download has no progress impact"));
  198. }
  199. }
  200. BOOL
  201. WINAPI
  202. OpaqueTransportQueryCapabilities (
  203. IN MIG_TRANSPORTSTORAGEID TransportStorageId,
  204. OUT PMIG_TRANSPORTTYPE TransportType,
  205. OUT PMIG_TRANSPORTCAPABILITIES Capabilities,
  206. OUT PCTSTR *FriendlyDescription
  207. )
  208. {
  209. if (TransportStorageId != g_ReliableStorageId) {
  210. return FALSE;
  211. }
  212. *TransportType = TRANSPORTTYPE_FULL;
  213. *Capabilities = CAPABILITY_COMPRESSED;
  214. *FriendlyDescription = TEXT("Local computer or another computer on the Network");
  215. return TRUE;
  216. }
  217. VOID
  218. pOtCleanUpTempDir (
  219. VOID
  220. )
  221. {
  222. if (g_TransportTempPath) {
  223. FiRemoveAllFilesInTree (g_TransportTempPath);
  224. }
  225. }
  226. PCTSTR
  227. pOtCreateTemporaryDir (
  228. VOID
  229. )
  230. {
  231. TCHAR tempFile[MAX_PATH];
  232. if (!IsmGetTempDirectory (tempFile, ARRAYSIZE(tempFile))) {
  233. return NULL;
  234. }
  235. return DuplicatePathString (tempFile, 0);
  236. }
  237. BOOL
  238. WINAPI
  239. OpaqueTransportSetStorage (
  240. IN MIG_PLATFORMTYPEID Platform,
  241. IN MIG_TRANSPORTSTORAGEID TransportStorageId,
  242. IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities,
  243. IN PCTSTR StoragePath,
  244. OUT PBOOL Valid,
  245. OUT PBOOL ImageExists
  246. )
  247. {
  248. PCTSTR transportPath;
  249. PCTSTR transportStatus;
  250. MIG_OBJECTSTRINGHANDLE encodedPath;
  251. DWORD status;
  252. BOOL result = FALSE;
  253. if (Valid) {
  254. *Valid = FALSE;
  255. }
  256. if (ImageExists) {
  257. *ImageExists = FALSE;
  258. }
  259. if (TransportStorageId == g_ReliableStorageId) {
  260. if ((!RequiredCapabilities) || (RequiredCapabilities == CAPABILITY_COMPRESSED)) {
  261. if (RequiredCapabilities == CAPABILITY_COMPRESSED) {
  262. g_OtCompressData = TRUE;
  263. } else {
  264. g_OtCompressData = FALSE;
  265. }
  266. transportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
  267. transportStatus = JoinPaths (transportPath, S_TRANSPORT_STATUS_FILE);
  268. if (!DoesFileExist (transportPath)) {
  269. // we require UNC path or a full path (like c:\...)
  270. if (transportPath[0] == '\\' && transportPath[1] == '\\') {
  271. // this is a UNC path
  272. *Valid = TRUE;
  273. } else if (transportPath[1] == ':') {
  274. // this is a normal full path
  275. *Valid = TRUE;
  276. } else {
  277. *Valid = FALSE;
  278. }
  279. *ImageExists = FALSE;
  280. } else {
  281. status = pGetOpaqueTransportStatus (transportStatus, NULL);
  282. switch (status) {
  283. case TRSTATUS_LOCKED:
  284. *ImageExists = TRUE;
  285. *Valid = FALSE;
  286. break;
  287. case TRSTATUS_READY:
  288. *ImageExists = TRUE;
  289. *Valid = TRUE;
  290. break;
  291. case TRSTATUS_DIRTY:
  292. *ImageExists = FALSE;
  293. *Valid = TRUE;
  294. break;
  295. default:
  296. *ImageExists = FALSE;
  297. *Valid = TRUE;
  298. }
  299. }
  300. FreePathString (transportStatus);
  301. FreePathString (transportPath);
  302. result = TRUE;
  303. }
  304. }
  305. if (result && *Valid) {
  306. if (g_TransportPath) {
  307. FreePathString (g_TransportPath);
  308. g_TransportPath = NULL;
  309. }
  310. g_TransportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
  311. g_TransportStatus = JoinPaths (g_TransportPath, S_TRANSPORT_STATUS_FILE);
  312. encodedPath = IsmCreateSimpleObjectPattern (g_TransportPath, FALSE, NULL, FALSE);
  313. if (encodedPath) {
  314. IsmRegisterStaticExclusion (MIG_FILE_TYPE, encodedPath);
  315. IsmDestroyObjectHandle (encodedPath);
  316. }
  317. }
  318. return result;
  319. }
  320. BOOL
  321. WINAPI
  322. OpaqueTransportSaveState (
  323. VOID
  324. )
  325. {
  326. DWORD status;
  327. BOOL result = FALSE;
  328. BOOL allowDelete = FALSE;
  329. if (!g_TransportPath) {
  330. DEBUGMSG ((DBG_ERROR, "Transport Path is not selected"));
  331. return FALSE;
  332. }
  333. if (DoesFileExist (g_TransportPath)) {
  334. status = pGetOpaqueTransportStatus (g_TransportStatus, NULL);
  335. switch (status) {
  336. case TRSTATUS_LOCKED:
  337. SetLastError (ERROR_ACCESS_DENIED);
  338. LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, g_TransportPath));
  339. return FALSE;
  340. case TRSTATUS_DIRTY:
  341. result = FiRemoveAllFilesInTree (g_TransportPath);
  342. if (!result) {
  343. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_EMPTY_DIR, g_TransportPath));
  344. return FALSE;
  345. }
  346. break;
  347. case TRSTATUS_READY:
  348. default:
  349. if (IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_EXISTS, 0)) {
  350. if (!FiRemoveAllFilesInTree (g_TransportPath)) {
  351. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_EMPTY_DIR, g_TransportPath));
  352. return FALSE;
  353. }
  354. } else {
  355. LOG ((LOG_ERROR, (PCSTR) MSG_NOT_EMPTY, g_TransportPath));
  356. SetLastError (ERROR_ALREADY_EXISTS);
  357. return FALSE;
  358. }
  359. break;
  360. }
  361. }
  362. allowDelete = TRUE;
  363. if (!BfCreateDirectory (g_TransportPath)) {
  364. PushError ();
  365. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_DIR, g_TransportPath));
  366. PopError ();
  367. return FALSE;
  368. }
  369. g_TransportStatusHandle = BfCreateFile (g_TransportStatus);
  370. if (!g_TransportStatusHandle) {
  371. PushError ();
  372. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CREATE_STATUS_FILE, g_TransportStatus));
  373. PopError ();
  374. return FALSE;
  375. }
  376. pSetOpaqueTransportStatus (g_TransportStatusHandle, g_OtCompressData, TRSTATUS_DIRTY);
  377. g_Platform = PLATFORM_SOURCE;
  378. result = pOtSaveAllState (g_OtCompressData);
  379. if (result) {
  380. pSetOpaqueTransportStatus (g_TransportStatusHandle, g_OtCompressData, TRSTATUS_READY);
  381. }
  382. CloseHandle (g_TransportStatusHandle);
  383. g_TransportStatusHandle = NULL;
  384. if (allowDelete && (!result)) {
  385. FiRemoveAllFilesInTree (g_TransportPath);
  386. }
  387. return result;
  388. }
  389. BOOL
  390. pOtReadAllImages (
  391. VOID
  392. )
  393. {
  394. PCTSTR imageFile = NULL;
  395. UINT imageIdx = 1;
  396. OCABHANDLE cabHandle;
  397. BOOL result = TRUE;
  398. while (result) {
  399. imageFile = pGetOpaqueImageFile (g_TransportPath, imageIdx);
  400. if (!DoesFileExist (imageFile)) {
  401. FreePathString (imageFile);
  402. return TRUE;
  403. }
  404. cabHandle = CabOpenCabinet (imageFile);
  405. if (cabHandle) {
  406. if (!CabExtractAllFiles (cabHandle, g_TransportTempPath)) {
  407. result = FALSE;
  408. }
  409. CabCloseCabinet (cabHandle);
  410. }
  411. FreePathString (imageFile);
  412. imageIdx ++;
  413. }
  414. return result;
  415. }
  416. BOOL
  417. WINAPI
  418. OpaqueTransportBeginApply (
  419. VOID
  420. )
  421. {
  422. DWORD status = 0;
  423. PCTSTR memDbFile;
  424. BOOL b;
  425. g_Platform = PLATFORM_DESTINATION;
  426. if (!g_TransportPath) {
  427. DEBUGMSG ((DBG_ERROR, "Transport Path is not selected"));
  428. return FALSE;
  429. }
  430. while (status != TRSTATUS_READY) {
  431. status = pGetOpaqueTransportStatus (g_TransportStatus, &g_OtCompressData);
  432. switch (status) {
  433. case TRSTATUS_LOCKED:
  434. if (!IsmSendMessageToApp (TRANSPORTMESSAGE_IMAGE_LOCKED, 0)) {
  435. SetLastError (ERROR_ACCESS_DENIED);
  436. LOG ((LOG_ERROR, (PCSTR) MSG_TRANSPORT_DIR_BUSY, g_TransportPath));
  437. return FALSE;
  438. }
  439. break;
  440. case TRSTATUS_DIRTY:
  441. SetLastError (ERROR_INVALID_DATA);
  442. LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
  443. return FALSE;
  444. case TRSTATUS_READY:
  445. break;
  446. default:
  447. SetLastError (ERROR_INVALID_DATA);
  448. LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_IMAGE, g_TransportPath));
  449. return FALSE;
  450. }
  451. }
  452. g_TransportStatusHandle = BfOpenReadFile (g_TransportStatus);
  453. if (!g_TransportStatusHandle) {
  454. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_STATUS_FILE, g_TransportStatus));
  455. return FALSE;
  456. }
  457. if (g_OtCompressData) {
  458. g_TransportTempPath = pOtCreateTemporaryDir ();
  459. if (!g_TransportTempPath) {
  460. CloseHandle (g_TransportStatusHandle);
  461. g_TransportStatusHandle = NULL;
  462. return FALSE;
  463. }
  464. if (!pOtReadAllImages ()) {
  465. CloseHandle (g_TransportStatusHandle);
  466. g_TransportStatusHandle = NULL;
  467. return FALSE;
  468. }
  469. CloseHandle (g_TransportStatusHandle);
  470. g_TransportStatusHandle = NULL;
  471. }
  472. memDbFile = JoinPaths (pGetRealTransportPath (), S_TRANSPORT_DAT_FILE);
  473. b = MemDbLoad (memDbFile);
  474. FreePathString (memDbFile);
  475. return b;
  476. }
  477. VOID
  478. WINAPI
  479. OpaqueTransportEndApply (
  480. VOID
  481. )
  482. {
  483. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  484. if (g_OtCompressData) {
  485. pOtCleanUpTempDir ();
  486. } else {
  487. CloseHandle (g_TransportStatusHandle);
  488. g_TransportStatusHandle = NULL;
  489. }
  490. }
  491. VOID
  492. WINAPI
  493. OpaqueTransportTerminate (
  494. VOID
  495. )
  496. {
  497. pOtCleanUpTempDir();
  498. if (g_TransportTempPath) {
  499. FreePathString (g_TransportTempPath);
  500. g_TransportTempPath = NULL;
  501. }
  502. if (g_TransportStatus) {
  503. FreePathString (g_TransportStatus);
  504. g_TransportStatus = NULL;
  505. }
  506. if (g_TransportPath) {
  507. FreePathString (g_TransportPath);
  508. g_TransportPath = NULL;
  509. }
  510. }
  511. static
  512. VOID
  513. pGetTempFileName (
  514. OUT PTSTR Buffer
  515. )
  516. {
  517. static fileIndex = 0;
  518. fileIndex ++;
  519. wsprintf (Buffer, TEXT("%08X.DAT"), fileIndex);
  520. }
  521. PCTSTR
  522. pOpaqueAllocStorageFileName (
  523. IN PCTSTR FileName OPTIONAL
  524. )
  525. {
  526. TCHAR buffer[32];
  527. if (FileName) {
  528. StringCopy (buffer, FileName);
  529. } else {
  530. pGetTempFileName (buffer);
  531. }
  532. return JoinPaths (g_TransportPath, buffer);
  533. }
  534. VOID
  535. pFreeStorageFileName (
  536. IN PCTSTR FileName
  537. )
  538. {
  539. FreePathString (FileName);
  540. }
  541. BOOL
  542. pOpaqueSaveDetails (
  543. IN PCTSTR DecoratedObject,
  544. IN PMIG_DETAILS Details
  545. )
  546. {
  547. PCTSTR key;
  548. BOOL b;
  549. if ((!Details) || (!Details->DetailsSize)) {
  550. return TRUE;
  551. }
  552. key = JoinText (S_DETAILS_PREFIX, DecoratedObject);
  553. b = (MemDbSetUnorderedBlob (key, 0, Details->DetailsData, Details->DetailsSize) != 0);
  554. FreeText (key);
  555. return b;
  556. }
  557. BOOL
  558. pOtAddFileToImage (
  559. IN PCTSTR FileName,
  560. IN PCTSTR CabName,
  561. IN OUT CCABHANDLE CabHandle
  562. )
  563. {
  564. return CabAddFileToCabinet (CabHandle, FileName, CabName);
  565. }
  566. BOOL
  567. pOtSaveContentInFile (
  568. IN MIG_OBJECTTYPEID ObjectTypeId,
  569. IN PCTSTR EncodedFileName,
  570. IN PCTSTR DecoratedObject,
  571. IN PMIG_CONTENT Content,
  572. IN OUT CCABHANDLE CabHandle OPTIONAL
  573. )
  574. {
  575. BOOL result = FALSE;
  576. PCTSTR destPath = NULL;
  577. MYASSERT (Content->ContentInFile);
  578. if (!Content->ContentInFile) {
  579. return FALSE;
  580. }
  581. //
  582. // Use the CopyFile API to move the file from local to storage.
  583. //
  584. __try {
  585. if (!Content->FileContent.ContentSize) {
  586. // this must be a directory, let's just write the key
  587. if (!MemDbSetValue (DecoratedObject, TRFLAG_FILE)) {
  588. __leave;
  589. }
  590. } else {
  591. //
  592. // Get a temp file, assemble the src path, copy the file
  593. //
  594. destPath = pOpaqueAllocStorageFileName (NULL);
  595. if (!destPath) {
  596. __leave;
  597. }
  598. if (CabHandle) {
  599. if (!pOtAddFileToImage (Content->FileContent.ContentPath, GetFileNameFromPath (destPath), CabHandle)) {
  600. __leave;
  601. }
  602. } else {
  603. if (!CopyFile (Content->FileContent.ContentPath, destPath, FALSE)) {
  604. __leave;
  605. }
  606. }
  607. //
  608. // Keep track of where the file went
  609. //
  610. if (!MemDbSetValue (DecoratedObject, TRFLAG_FILE)) {
  611. __leave;
  612. }
  613. if (!MemDbAddSingleLinkage (DecoratedObject, GetFileNameFromPath (destPath), 0)) {
  614. __leave;
  615. }
  616. }
  617. //
  618. // Save details
  619. //
  620. result = pOpaqueSaveDetails (DecoratedObject, &(Content->Details));
  621. }
  622. __finally {
  623. pFreeStorageFileName (destPath);
  624. INVALID_POINTER (destPath);
  625. }
  626. return result;
  627. }
  628. BOOL
  629. pOtSaveContentInMemory (
  630. IN MIG_OBJECTTYPEID ObjectTypeId,
  631. IN PCTSTR EncodedObjectName,
  632. IN PCTSTR DecoratedObject,
  633. IN PMIG_CONTENT Content
  634. )
  635. {
  636. BOOL result = FALSE;
  637. MYASSERT (!Content->ContentInFile);
  638. if (Content->ContentInFile) {
  639. return FALSE;
  640. }
  641. MemDbSetValue (DecoratedObject, TRFLAG_MEMORY);
  642. if (Content->MemoryContent.ContentBytes && Content->MemoryContent.ContentSize) {
  643. MemDbSetUnorderedBlob (
  644. DecoratedObject,
  645. 0,
  646. Content->MemoryContent.ContentBytes,
  647. Content->MemoryContent.ContentSize
  648. );
  649. }
  650. result = pOpaqueSaveDetails (DecoratedObject, &(Content->Details));
  651. return result;
  652. }
  653. PCTSTR
  654. pOpaqueBuildDecoratedObject (
  655. IN MIG_OBJECTTYPEID ObjectTypeId,
  656. IN ENCODEDSTRHANDLE ObjectName
  657. )
  658. {
  659. TCHAR prefix[32];
  660. wsprintf (prefix, TEXT("%u"), ObjectTypeId);
  661. return JoinPaths (prefix, ObjectName);
  662. }
  663. VOID
  664. pOtDestroyDecoratedObject (
  665. IN PCTSTR String
  666. )
  667. {
  668. FreePathString (String);
  669. }
  670. BOOL
  671. pOtWriteAllImages (
  672. VOID
  673. )
  674. {
  675. UINT imageIdx = 1;
  676. PCTSTR imageFile;
  677. PCTSTR imageDest;
  678. BOOL result = FALSE;
  679. while (TRUE) {
  680. imageFile = pGetOpaqueImageFile (g_TransportTempPath, imageIdx);
  681. imageDest = pGetOpaqueImageFile (g_TransportPath, imageIdx);
  682. if (DoesFileExist (imageFile)) {
  683. if (!CopyFile (imageFile, imageDest, FALSE)) {
  684. break;
  685. }
  686. } else {
  687. result = TRUE;
  688. break;
  689. }
  690. FreePathString (imageDest);
  691. FreePathString (imageFile);
  692. imageIdx ++;
  693. }
  694. return result;
  695. }
  696. BOOL
  697. pOtSaveAllState (
  698. IN BOOL Compressed
  699. )
  700. {
  701. MIG_CONTENT value;
  702. PMIG_CONTENT convValue;
  703. ULONGLONG size;
  704. MIG_OBJECTWITHATTRIBUTE_ENUM objEnum;
  705. PCTSTR ourDbFile = NULL;
  706. PCTSTR decoratedObject = NULL;
  707. ULONGLONG bytesSaved = 0;
  708. UINT lastTick = GetTickCount();
  709. TCHAR text[64];
  710. UINT fraction;
  711. CCABHANDLE cabHandle = NULL;
  712. INT_PTR appReply;
  713. BOOL okSave = FALSE;
  714. TRANSCOPY_ERROR transCopyError;
  715. BOOL result = FALSE;
  716. __try {
  717. if (Compressed) {
  718. g_TransportTempPath = pOtCreateTemporaryDir ();
  719. if (!g_TransportTempPath) {
  720. __leave;
  721. }
  722. cabHandle = CabCreateCabinet (g_TransportTempPath, S_TRANSPORT_IMG_FILE, S_TRANSPORT_DSK_FILE, IsmGetTempFile, 0);
  723. if (!cabHandle) {
  724. __leave;
  725. }
  726. }
  727. //
  728. // Enumerate all objects with "save" attribute
  729. //
  730. if (IsmEnumFirstPersistentObject (&objEnum)) {
  731. do {
  732. //
  733. // For each object to be saved, do the appropriate
  734. // data copy action
  735. //
  736. okSave = FALSE;
  737. while (!okSave) {
  738. if (!IsmAcquireObjectEx (
  739. objEnum.ObjectTypeId,
  740. objEnum.ObjectName,
  741. &value,
  742. CONTENTTYPE_ANY,
  743. 0
  744. )) {
  745. transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
  746. transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
  747. transCopyError.Error = GetLastError ();
  748. if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.ObjectName)) {
  749. appReply = APPRESPONSE_IGNORE;
  750. } else {
  751. appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError);
  752. if ((appReply == APPRESPONSE_NONE) ||
  753. (appReply == APPRESPONSE_FAIL)
  754. ) {
  755. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName));
  756. IsmReleaseMemory (transCopyError.ObjectName);
  757. IsmAbortPersistentObjectEnum (&objEnum);
  758. __leave;
  759. }
  760. }
  761. if (appReply == APPRESPONSE_IGNORE) {
  762. LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
  763. IsmReleaseMemory (transCopyError.ObjectName);
  764. break;
  765. }
  766. IsmReleaseMemory (transCopyError.ObjectName);
  767. continue;
  768. }
  769. okSave = TRUE;
  770. }
  771. if (okSave) {
  772. #ifdef UNICODE
  773. convValue = &value;
  774. #else
  775. // now let's convert this object content to UNICODE
  776. convValue = IsmConvertObjectContentToUnicode (objEnum.ObjectTypeId, objEnum.ObjectName, &value);
  777. if (!convValue) {
  778. convValue = &value;
  779. }
  780. #endif
  781. decoratedObject = pOpaqueBuildDecoratedObject (objEnum.ObjectTypeId, objEnum.ObjectName);
  782. if (convValue->ContentInFile) {
  783. okSave = FALSE;
  784. while (!okSave) {
  785. if (!pOtSaveContentInFile (objEnum.ObjectTypeId, objEnum.ObjectName, decoratedObject, convValue, cabHandle)) {
  786. transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
  787. transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
  788. transCopyError.Error = GetLastError ();
  789. if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.ObjectName)) {
  790. appReply = APPRESPONSE_IGNORE;
  791. } else {
  792. appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError);
  793. if ((appReply == APPRESPONSE_NONE) ||
  794. (appReply == APPRESPONSE_FAIL)
  795. ) {
  796. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName));
  797. IsmReleaseMemory (transCopyError.ObjectName);
  798. IsmAbortPersistentObjectEnum (&objEnum);
  799. __leave;
  800. }
  801. }
  802. if (appReply == APPRESPONSE_IGNORE) {
  803. LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
  804. IsmReleaseMemory (transCopyError.ObjectName);
  805. break;
  806. }
  807. IsmReleaseMemory (transCopyError.ObjectName);
  808. continue;
  809. }
  810. okSave = TRUE;
  811. }
  812. size = convValue->FileContent.ContentSize;
  813. } else {
  814. okSave = FALSE;
  815. while (!okSave) {
  816. if (!pOtSaveContentInMemory (objEnum.ObjectTypeId, objEnum.ObjectName, decoratedObject, convValue)) {
  817. transCopyError.ObjectType = IsmGetObjectTypeName (objEnum.ObjectTypeId);
  818. transCopyError.ObjectName = IsmGetNativeObjectName (objEnum.ObjectTypeId, objEnum.ObjectName);
  819. transCopyError.Error = GetLastError ();
  820. if (IsmIsNonCriticalObject (objEnum.ObjectTypeId, objEnum.ObjectName)) {
  821. appReply = APPRESPONSE_IGNORE;
  822. } else {
  823. appReply = IsmSendMessageToApp (TRANSPORTMESSAGE_SRC_COPY_ERROR, (ULONG_PTR)&transCopyError);
  824. if ((appReply == APPRESPONSE_NONE) ||
  825. (appReply == APPRESPONSE_FAIL)
  826. ) {
  827. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_COPYSOURCE, transCopyError.ObjectName));
  828. IsmReleaseMemory (transCopyError.ObjectName);
  829. IsmAbortPersistentObjectEnum (&objEnum);
  830. __leave;
  831. }
  832. }
  833. if (appReply == APPRESPONSE_IGNORE) {
  834. LOG ((LOG_WARNING, (PCSTR) MSG_IGNORE_COPYSOURCE, transCopyError.ObjectName));
  835. IsmReleaseMemory (transCopyError.ObjectName);
  836. break;
  837. }
  838. IsmReleaseMemory (transCopyError.ObjectName);
  839. continue;
  840. }
  841. okSave = TRUE;
  842. }
  843. size = convValue->MemoryContent.ContentSize;
  844. }
  845. #ifndef UNICODE
  846. if (convValue != (&value)) {
  847. IsmFreeConvertedObjectContent (objEnum.ObjectTypeId, convValue);
  848. }
  849. #endif
  850. IsmReleaseObject (&value);
  851. pOtDestroyDecoratedObject (decoratedObject);
  852. decoratedObject = NULL;
  853. }
  854. if (!IsmTickProgressBar (g_PersistentSlice, 1)) {
  855. IsmAbortPersistentObjectEnum (&objEnum);
  856. __leave;
  857. }
  858. //
  859. // Send bytes saved to app every 3 seconds
  860. //
  861. bytesSaved += size;
  862. if (GetTickCount() - lastTick > 3000) {
  863. if (bytesSaved < 1048576) {
  864. wsprintf (text, TEXT("Saved: %u K"), (UINT) (bytesSaved / 1024));
  865. } else if (bytesSaved < 8388608) {
  866. fraction = (UINT) (bytesSaved / 10485);
  867. wsprintf (text, TEXT("Saved: %u.%02u M"), fraction / 100, fraction % 100);
  868. } else if (bytesSaved < 1073741824) {
  869. wsprintf (text, TEXT("Saved: %u M"), (UINT) (bytesSaved / 1048576));
  870. } else {
  871. fraction = (UINT) (bytesSaved / 10737418);
  872. wsprintf (text, TEXT("Saved: %u.%02u G"), fraction / 100, fraction % 100);
  873. }
  874. IsmSendMessageToApp (TRANSPORTMESSAGE_SIZE_SAVED, (ULONG_PTR) text);
  875. lastTick = GetTickCount();
  876. }
  877. } while (IsmEnumNextPersistentObject (&objEnum));
  878. }
  879. if (Compressed) {
  880. ourDbFile = JoinPaths (g_TransportTempPath, S_TRANSPORT_DAT_FILE);
  881. } else {
  882. ourDbFile = pOpaqueAllocStorageFileName (S_TRANSPORT_DAT_FILE);
  883. if (!ourDbFile) {
  884. __leave;
  885. }
  886. }
  887. if (!MemDbSave (ourDbFile)) {
  888. __leave;
  889. }
  890. if (Compressed) {
  891. if (!pOtAddFileToImage (ourDbFile, S_TRANSPORT_DAT_FILE, cabHandle)) {
  892. __leave;
  893. }
  894. if (!CabFlushAndCloseCabinet (cabHandle)) {
  895. __leave;
  896. }
  897. if (!pOtWriteAllImages ()) {
  898. __leave;
  899. }
  900. }
  901. IsmSendMessageToApp (TRANSPORTMESSAGE_SIZE_SAVED, 0);
  902. result = TRUE;
  903. }
  904. __finally {
  905. pFreeStorageFileName (ourDbFile);
  906. INVALID_POINTER (ourDbFile);
  907. pOtDestroyDecoratedObject (decoratedObject);
  908. INVALID_POINTER (decoratedObject);
  909. if (g_OtCompressData && g_TransportTempPath) {
  910. pOtCleanUpTempDir ();
  911. }
  912. }
  913. return result;
  914. }
  915. BOOL
  916. WINAPI
  917. OpaqueTransportAcquireObject (
  918. IN MIG_OBJECTTYPEID ObjectTypeId,
  919. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  920. OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED
  921. IN MIG_CONTENTTYPE ContentType,
  922. IN UINT MemoryContentLimit
  923. )
  924. {
  925. UINT value;
  926. PCBYTE memValue;
  927. UINT memValueSize;
  928. PCTSTR fileValue = NULL;
  929. BOOL valueInFile;
  930. KEYHANDLE keyHandle;
  931. PALLOCSTATE allocState;
  932. PCTSTR detailsKey = NULL;
  933. PBYTE details;
  934. UINT detailsSize;
  935. PCTSTR sourceFile;
  936. PCTSTR decoratedObject = NULL;
  937. HANDLE fileHandle;
  938. BOOL result = FALSE;
  939. if (!ObjectContent) {
  940. return FALSE;
  941. }
  942. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  943. MYASSERT ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE);
  944. decoratedObject = pOpaqueBuildDecoratedObject (ObjectTypeId, ObjectName);
  945. allocState = (PALLOCSTATE) MemAllocZeroed (sizeof (ALLOCSTATE));
  946. if (MemDbGetValue (decoratedObject, &value)) {
  947. if (value == TRFLAG_FILE) {
  948. valueInFile = TRUE;
  949. keyHandle = MemDbGetSingleLinkage (decoratedObject, 0, 0);
  950. if (keyHandle) {
  951. fileValue = MemDbGetKeyFromHandle (keyHandle, 0);
  952. result = fileValue != NULL;
  953. } else {
  954. fileValue = NULL;
  955. result = TRUE;
  956. }
  957. } else if (value == TRFLAG_MEMORY) {
  958. valueInFile = FALSE;
  959. memValueSize = 0;
  960. memValue = MemDbGetUnorderedBlob (decoratedObject, 0, &memValueSize);
  961. result = TRUE;
  962. } else {
  963. LOG ((LOG_ERROR, (PCSTR) MSG_UNSUPPORTED_DATA, value));
  964. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  965. }
  966. if (result) {
  967. result = FALSE;
  968. if (valueInFile) {
  969. if ((ContentType == CONTENTTYPE_ANY) ||
  970. (ContentType == CONTENTTYPE_FILE) ||
  971. (ContentType == CONTENTTYPE_DETAILS_ONLY)
  972. ) {
  973. // this is stored as a file and it's wanted as a file
  974. ObjectContent->ObjectTypeId = ObjectTypeId;
  975. ObjectContent->ContentInFile = TRUE;
  976. if (fileValue) {
  977. ObjectContent->FileContent.ContentPath = JoinPaths (pGetRealTransportPath (), fileValue);
  978. ObjectContent->FileContent.ContentSize = BfGetFileSize (ObjectContent->FileContent.ContentPath);
  979. } else {
  980. ObjectContent->FileContent.ContentSize = 0;
  981. ObjectContent->FileContent.ContentPath = NULL;
  982. }
  983. result = TRUE;
  984. } else {
  985. // this is stored as a file and it's wanted as memory
  986. ObjectContent->ObjectTypeId = ObjectTypeId;
  987. ObjectContent->ContentInFile = FALSE;
  988. if (fileValue) {
  989. sourceFile = JoinPaths (pGetRealTransportPath (), fileValue);
  990. ObjectContent->MemoryContent.ContentSize = (UINT) BfGetFileSize (sourceFile);
  991. ObjectContent->MemoryContent.ContentBytes = MapFileIntoMemory (
  992. sourceFile,
  993. &allocState->FileHandle,
  994. &allocState->MapHandle
  995. );
  996. FreePathString (sourceFile);
  997. result = (ObjectContent->MemoryContent.ContentBytes != NULL);
  998. } else {
  999. ObjectContent->MemoryContent.ContentSize = 0;
  1000. ObjectContent->MemoryContent.ContentBytes = NULL;
  1001. result = TRUE;
  1002. }
  1003. }
  1004. MemDbReleaseMemory (fileValue);
  1005. } else {
  1006. if ((ContentType == CONTENTTYPE_ANY) ||
  1007. (ContentType == CONTENTTYPE_MEMORY) ||
  1008. (ContentType == CONTENTTYPE_DETAILS_ONLY)
  1009. ) {
  1010. // this is stored as memory and it's wanted as memory
  1011. ObjectContent->ObjectTypeId = ObjectTypeId;
  1012. ObjectContent->ContentInFile = FALSE;
  1013. ObjectContent->MemoryContent.ContentSize = memValueSize;
  1014. ObjectContent->MemoryContent.ContentBytes = memValue;
  1015. result = TRUE;
  1016. } else {
  1017. // this is stored as memory and it's wanted as a file
  1018. if (memValue) {
  1019. if (IsmGetTempFile (allocState->TempFile, ARRAYSIZE(allocState->TempFile))) {
  1020. fileHandle = BfCreateFile (allocState->TempFile);
  1021. if (fileHandle) {
  1022. if (BfWriteFile (fileHandle, memValue, memValueSize)) {
  1023. ObjectContent->ObjectTypeId = ObjectTypeId;
  1024. ObjectContent->ContentInFile = TRUE;
  1025. ObjectContent->FileContent.ContentSize = memValueSize;
  1026. ObjectContent->FileContent.ContentPath = DuplicatePathString (allocState->TempFile, 0);
  1027. result = TRUE;
  1028. }
  1029. CloseHandle (fileHandle);
  1030. }
  1031. }
  1032. MemDbReleaseMemory (memValue);
  1033. } else {
  1034. ObjectContent->ObjectTypeId = ObjectTypeId;
  1035. ObjectContent->ContentInFile = TRUE;
  1036. ObjectContent->FileContent.ContentSize = 0;
  1037. ObjectContent->FileContent.ContentPath = NULL;
  1038. }
  1039. }
  1040. }
  1041. }
  1042. } else {
  1043. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  1044. }
  1045. if (result) {
  1046. //
  1047. // Fill the details
  1048. //
  1049. detailsKey = JoinText (S_DETAILS_PREFIX, decoratedObject);
  1050. details = MemDbGetUnorderedBlob (detailsKey, 0, &detailsSize);
  1051. if (!details) {
  1052. detailsSize = 0;
  1053. }
  1054. allocState->DetailsPtr = details;
  1055. ObjectContent->Details.DetailsSize = detailsSize;
  1056. ObjectContent->Details.DetailsData = details;
  1057. FreeText (detailsKey);
  1058. ObjectContent->TransHandle = allocState;
  1059. }
  1060. if (!result) {
  1061. FreeAlloc (allocState);
  1062. }
  1063. FreePathString (decoratedObject);
  1064. return result;
  1065. }
  1066. BOOL
  1067. WINAPI
  1068. OpaqueTransportReleaseObject (
  1069. IN OUT PMIG_CONTENT ObjectContent
  1070. )
  1071. {
  1072. PALLOCSTATE allocState;
  1073. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  1074. allocState = (PALLOCSTATE) ObjectContent->TransHandle;
  1075. if (ObjectContent->ContentInFile) {
  1076. FreePathString (ObjectContent->FileContent.ContentPath);
  1077. if (allocState && allocState->TempFile[0]) {
  1078. DeleteFile (allocState->TempFile);
  1079. }
  1080. } else {
  1081. if (allocState && allocState->FileHandle && allocState->MapHandle) {
  1082. UnmapFile (
  1083. ObjectContent->MemoryContent.ContentBytes,
  1084. allocState->MapHandle,
  1085. allocState->FileHandle
  1086. );
  1087. } else {
  1088. MemDbReleaseMemory (ObjectContent->MemoryContent.ContentBytes);
  1089. }
  1090. }
  1091. if (allocState && allocState->DetailsPtr) {
  1092. MemDbReleaseMemory (allocState->DetailsPtr);
  1093. }
  1094. FreeAlloc (allocState);
  1095. return TRUE;
  1096. }