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.

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