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.

1068 lines
32 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: marshl.cxx
  7. //
  8. // Contents: Marshal/Unmarshal implementation
  9. //
  10. // History: 04-May-92 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include <exphead.cxx>
  14. #pragma hdrstop
  15. #include <expdf.hxx>
  16. #include <expst.hxx>
  17. #include <pbstream.hxx>
  18. #include <marshl.hxx>
  19. #include <logfile.hxx>
  20. // Standard marshal data is an IID plus a DWORD
  21. #define CBSTDMARSHALSIZE (sizeof(IID)+sizeof(DWORD))
  22. SCODE VerifyIid(REFIID iid, REFIID iidObj)
  23. {
  24. if ((IsEqualIID(iid, IID_IUnknown) || (IsEqualIID(iid, iidObj))))
  25. {
  26. return S_OK;
  27. }
  28. if (IsEqualIID(iidObj, IID_ILockBytes))
  29. {
  30. if (IsEqualIID(iid, IID_IFillLockBytes))
  31. {
  32. return S_OK;
  33. }
  34. }
  35. if (IsEqualIID(iidObj, IID_IStorage))
  36. {
  37. if ( IsEqualIID(iid, IID_IPropertySetStorage)
  38. || IsEqualIID(iid, IID_IPropertyBagEx) )
  39. {
  40. return S_OK;
  41. }
  42. }
  43. return STG_E_INVALIDPARAMETER;
  44. }
  45. //+--------------------------------------------------------------
  46. //
  47. // Function: DfUnMarshalInterface, public
  48. //
  49. // Synopsis: Unmarshals marshaled data
  50. //
  51. // Arguments: [pstStm] - Stream to read data from
  52. // [iid] - Interface to unmarshal
  53. // [fFirst] - First time unmarshalling
  54. // [ppvObj] - Interface return
  55. //
  56. // Returns: Appropriate status code
  57. //
  58. // Modifies: [ppvObj]
  59. //
  60. // History: 04-May-92 DrewB Created
  61. //
  62. //---------------------------------------------------------------
  63. STDAPI DfUnMarshalInterface(IStream *pstStm,
  64. REFIID iid,
  65. BOOL fFirst,
  66. void **ppvObj)
  67. {
  68. SCODE sc;
  69. ULONG cbRead;
  70. IID iidSt;
  71. DWORD mshlflags;
  72. SafeIUnknown punk;
  73. olLog(("--------::In DfUnMarshalInterface(%p, iid, %d, %p). "
  74. "Context == %lX\n", pstStm, fFirst, ppvObj,
  75. (ULONG)GetCurrentContextId()));
  76. olDebugOut((DEB_TRACE, "In DfUnMarshalInterface("
  77. "%p, ?, %d, %p)\n", pstStm, fFirst, ppvObj));
  78. olChk(ValidateOutPtrBuffer(ppvObj));
  79. *ppvObj = NULL;
  80. olChk(ValidateInterface(pstStm, IID_IStream));
  81. olChk(ValidateIid(iid));
  82. if (!fFirst)
  83. olErr(EH_Err, STG_E_INVALIDPARAMETER);
  84. olHChk(pstStm->Read(&iidSt, sizeof(iidSt), &cbRead));
  85. if (cbRead != sizeof(iidSt))
  86. olErr(EH_Err, STG_E_READFAULT);
  87. olHChk(pstStm->Read(&mshlflags, sizeof(mshlflags), &cbRead));
  88. if (cbRead != sizeof(mshlflags))
  89. olErr(EH_Err, STG_E_READFAULT);
  90. olChk(VerifyIid(iid, iidSt));
  91. #if !defined(MULTIHEAP)
  92. olChk(DfSyncSharedMemory());
  93. DfInitSharedMemBase();
  94. #endif
  95. if (IsEqualIID(iidSt, IID_ILockBytes))
  96. sc = CFileStream::Unmarshal(pstStm, (void **)&punk, mshlflags);
  97. else if (IsEqualIID(iidSt, IID_IStream))
  98. sc = CExposedStream::Unmarshal(pstStm, (void **)&punk, mshlflags);
  99. else if (IsEqualIID(iidSt, IID_IStorage))
  100. sc = CExposedDocFile::Unmarshal(pstStm, (void **)&punk, mshlflags);
  101. else
  102. sc = E_NOINTERFACE;
  103. if (SUCCEEDED(sc))
  104. {
  105. if (!IsEqualIID(iid, iidSt))
  106. {
  107. sc = punk->QueryInterface(iid, ppvObj);
  108. }
  109. else
  110. {
  111. TRANSFER_INTERFACE(punk, IUnknown, ppvObj);
  112. #if DBG == 1
  113. void *pvCheck;
  114. HRESULT scCheck = ((IUnknown*)*ppvObj)->QueryInterface(iidSt, &pvCheck);
  115. olAssert (scCheck == S_OK || scCheck == STG_E_REVERTED);
  116. if (SUCCEEDED(scCheck))
  117. {
  118. olAssert( pvCheck == *ppvObj );
  119. ((IUnknown*)pvCheck)->Release();
  120. }
  121. #endif
  122. }
  123. }
  124. olDebugOut((DEB_TRACE, "Out DfUnMarshalInterface => %p\n",
  125. *ppvObj));
  126. EH_Err:
  127. olLog(("--------::Out DfUnMarshalInterface(). "
  128. "*ppvObj == %p, ret == %lX\n", *ppvObj, sc));
  129. return ResultFromScode(sc);
  130. }
  131. //+---------------------------------------------------------------------------
  132. //
  133. // Function: GetCoMarshalSize, private
  134. //
  135. // Synopsis: Gets the marshal size for an interface marshalled using
  136. // CoMarshalInterface
  137. //
  138. // Arguments: [riid] - Interface id
  139. // [punk] - Interface pointer
  140. // [pv] - Context info
  141. // [dwDestContext] - Destination context
  142. // [pvDestContext] - Destination context
  143. // [mshlflags] - Marshal flags
  144. // [pcb] - Size return
  145. //
  146. // Returns: Appropriate status code
  147. //
  148. // Modifies: [pcb]
  149. //
  150. // Algorithm: CoMarshalInterface is guaranteed to add no more than
  151. // MARSHALINTERFACE_MIN bytes of overhead to a marshal
  152. // Also, the standard marshaller takes no more than that
  153. // So if the given object supports IMarshal, the return
  154. // is IMarshal::GetMarshalSizeMax+MARSHALINTERFACE_MIN,
  155. // otherwise it is just MARSHALINTERFACE_MIN
  156. //
  157. // History: 03-Aug-93 DrewB Created
  158. //
  159. // Notes: On 32-bit platforms, we can use CoGetMarshalSizeMax
  160. //
  161. //----------------------------------------------------------------------------
  162. #ifndef WIN32
  163. static SCODE GetCoMarshalSize(REFIID riid,
  164. IUnknown *punk,
  165. void *pv,
  166. DWORD dwDestContext,
  167. void *pvDestContext,
  168. DWORD mshlflags,
  169. DWORD *pcb)
  170. {
  171. IMarshal *pmsh;
  172. SCODE sc;
  173. DWORD cb;
  174. olDebugOut((DEB_ITRACE, "In GetCoMarshalSize("
  175. "riid, %p, %p, %lu, %p, %lu, %p)\n", pv, punk, dwDestContext,
  176. pvDestContext, mshlflags, pcb));
  177. sc = DfGetScode(punk->QueryInterface(IID_IMarshal, (void **)&pmsh));
  178. if (sc == E_NOINTERFACE)
  179. {
  180. *pcb = MARSHALINTERFACE_MIN;
  181. sc = S_OK;
  182. }
  183. else if (SUCCEEDED(sc))
  184. {
  185. sc = DfGetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
  186. pvDestContext, mshlflags,
  187. &cb));
  188. if (SUCCEEDED(sc))
  189. *pcb = MARSHALINTERFACE_MIN+cb;
  190. pmsh->Release();
  191. }
  192. olDebugOut((DEB_ITRACE, "Out GetCoMarshalSize => %lu, 0x%lX\n",
  193. *pcb, sc));
  194. return sc;
  195. }
  196. #else
  197. #define GetCoMarshalSize(riid, punk, pv, dwDestContext, pvDestContext,\
  198. mshlflags, pcb) \
  199. GetScode(CoGetMarshalSizeMax(pcb, riid, punk, dwDestContext, \
  200. pvDestContext, mshlflags))
  201. #endif
  202. //+--------------------------------------------------------------
  203. //
  204. // Function: GetStdMarshalSize, public
  205. //
  206. // Synopsis: Returns the size needed for a standard marshal buffer
  207. //
  208. // Arguments: [iid] - Requested marshal IID
  209. // [iidObj] - IID of object being marshalled
  210. // [dwDestContext] - Destination context
  211. // [pvDestContext] - Unreferenced
  212. // [mshlflags] - Marshal flags
  213. // [pcbSize] - Size return
  214. // [cbSize] - Object private size
  215. // [ppc] - Context to marshal or NULL
  216. // [fMarshalOriginal] - Marshal original in context
  217. //
  218. // Returns: Appropriate status code
  219. //
  220. // Modifies: [pcbSize]
  221. //
  222. // History: 04-May-92 DrewB Created
  223. //
  224. //---------------------------------------------------------------
  225. SCODE GetStdMarshalSize(REFIID iid,
  226. REFIID iidObj,
  227. DWORD dwDestContext,
  228. LPVOID pvDestContext,
  229. DWORD mshlflags,
  230. DWORD *pcbSize,
  231. DWORD cbSize,
  232. #ifdef ASYNC
  233. CAsyncConnection *pcpoint,
  234. BOOL fMarshalILBs,
  235. #endif
  236. CPerContext *ppc,
  237. BOOL const fMarshalOriginal)
  238. {
  239. DWORD cbLBSize;
  240. SCODE sc;
  241. olDebugOut((DEB_ITRACE, "In GetStdMarshalSize("
  242. "iid, iidObj, %lu, %p, %lu, %p, %lu, %p, %d)\n",
  243. dwDestContext, pvDestContext, mshlflags, pcbSize, cbSize, ppc,
  244. fMarshalOriginal));
  245. olChk(ValidateOutBuffer(pcbSize, sizeof(DWORD)));
  246. *pcbSize = 0;
  247. olChk(ValidateIid(iid));
  248. olChk(VerifyIid(iid, iidObj));
  249. if (((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
  250. || pvDestContext != NULL)
  251. olErr(EH_Err, STG_E_INVALIDFLAG);
  252. *pcbSize = CBSTDMARSHALSIZE+cbSize;
  253. #ifdef MULTIHEAP
  254. *pcbSize += sizeof(ULONG)+sizeof(ContextId)+sizeof(CPerContext*);
  255. #endif
  256. #ifdef POINTER_IDENTITY
  257. *pcbSize += sizeof(CMarshalList*);
  258. #endif
  259. #ifdef ASYNC
  260. if ((ppc) && fMarshalILBs)
  261. #else
  262. if (ppc)
  263. #endif
  264. {
  265. *pcbSize += sizeof(CGlobalContext *);
  266. olChk(GetCoMarshalSize(IID_ILockBytes,
  267. (ILockBytes *)ppc->GetBase(),
  268. NULL, dwDestContext, pvDestContext,
  269. mshlflags, &cbLBSize));
  270. *pcbSize += cbLBSize;
  271. olChk(GetCoMarshalSize(IID_ILockBytes,
  272. (ILockBytes *)ppc->GetDirty(),
  273. NULL, dwDestContext, pvDestContext,
  274. mshlflags, &cbLBSize));
  275. *pcbSize += cbLBSize;
  276. if (fMarshalOriginal)
  277. {
  278. olChk(GetCoMarshalSize(IID_ILockBytes,
  279. (ILockBytes *)ppc->GetOriginal(),
  280. NULL, dwDestContext, pvDestContext,
  281. mshlflags, &cbLBSize));
  282. *pcbSize += cbLBSize;
  283. }
  284. }
  285. #ifdef ASYNC
  286. //BOOL determines whether we have a connection to marshal or not
  287. *pcbSize += sizeof(BOOL);
  288. if ((pcpoint) && (pcpoint->GetMarshalPoint() != NULL))
  289. {
  290. ULONG cbConnectSize;
  291. //Async flags
  292. *pcbSize += sizeof(DWORD);
  293. olChk(GetCoMarshalSize(IID_IDocfileAsyncConnectionPoint,
  294. pcpoint->GetMarshalPoint(),
  295. NULL, dwDestContext, pvDestContext,
  296. mshlflags, &cbConnectSize));
  297. *pcbSize += cbConnectSize;
  298. }
  299. #endif
  300. olDebugOut((DEB_ITRACE, "Out GetStdMarshalSize\n"));
  301. EH_Err:
  302. return sc;
  303. }
  304. //+--------------------------------------------------------------
  305. //
  306. // Member: StartMarshal, public
  307. //
  308. // Synopsis: Writes standard marshal header
  309. //
  310. // Arguments: [pstStm] - Stream to write marshal data into
  311. // [iid] - Interface to marshal
  312. // [iidObj] - Object being marshalled
  313. // [mshlflags] - Marshal flags
  314. //
  315. // Returns: Appropriate status code
  316. //
  317. // History: 04-May-92 DrewB Created
  318. //
  319. //---------------------------------------------------------------
  320. SCODE StartMarshal(IStream *pstStm,
  321. REFIID iid,
  322. REFIID iidObj,
  323. DWORD mshlflags)
  324. {
  325. SCODE sc;
  326. ULONG cbWritten;
  327. olDebugOut((DEB_ITRACE, "In StartMarshal(%p, iid, iidObj, %lu)\n",
  328. pstStm, mshlflags));
  329. olChk(ValidateInterface(pstStm, IID_IStream));
  330. olChk(ValidateIid(iid));
  331. olChk(VerifyIid(iid, iidObj));
  332. olHChk(pstStm->Write((void *)&iidObj, sizeof(iidObj), &cbWritten));
  333. if (cbWritten != sizeof(iidObj))
  334. olErr(EH_Err, STG_E_WRITEFAULT);
  335. #if defined(_WIN64)
  336. mshlflags |= MSHLFLAGS_STG_WIN64;
  337. #endif
  338. olHChk(pstStm->Write((void *)&mshlflags, sizeof(mshlflags), &cbWritten));
  339. if (cbWritten != sizeof(mshlflags))
  340. olErr(EH_Err, STG_E_WRITEFAULT);
  341. olDebugOut((DEB_ITRACE, "Out StartMarshal\n"));
  342. EH_Err:
  343. return sc;
  344. }
  345. //+---------------------------------------------------------------------------
  346. //
  347. // Function: SkipStdMarshal, public
  348. //
  349. // Synopsis: Skips over the standard marshal data
  350. //
  351. // Arguments: [pstm] - Marshal stream
  352. // [piid] - IID return
  353. // [pmshlflags] - Return marshal flags
  354. //
  355. // Returns: Appropriate status code
  356. //
  357. // Modifies: [piid]
  358. // [pmshlflags]
  359. //
  360. // History: 20-Nov-92 DrewB Created
  361. //
  362. //----------------------------------------------------------------------------
  363. #ifdef WIN32
  364. SCODE SkipStdMarshal(IStream *pstm, IID *piid, DWORD *pmshlflags)
  365. {
  366. SCODE sc;
  367. ULONG cbRead;
  368. olDebugOut((DEB_ITRACE, "In SkipStdMarshal(%p, %p, %p)\n", pstm,
  369. piid, pmshlflags));
  370. olHChk(pstm->Read(piid, sizeof(IID), &cbRead));
  371. if (cbRead != sizeof(IID))
  372. olErr(EH_Err, STG_E_READFAULT);
  373. olHChk(pstm->Read(pmshlflags, sizeof(DWORD), &cbRead));
  374. if (cbRead != sizeof(DWORD))
  375. olErr(EH_Err, STG_E_READFAULT);
  376. olDebugOut((DEB_ITRACE, "Out SkipStdMarshal => %lX\n", sc));
  377. EH_Err:
  378. return sc;
  379. }
  380. #endif
  381. //+--------------------------------------------------------------
  382. //
  383. // Function: MarshalPointer, public
  384. //
  385. // Synopsis: Marshals a pointer
  386. //
  387. // Arguments: [pstm] - Marshal stream
  388. // [pv] - Pointer
  389. //
  390. // Returns: Appropriate status code
  391. //
  392. // History: 20-Aug-92 DrewB Created
  393. //
  394. //---------------------------------------------------------------
  395. SCODE MarshalPointer(IStream *pstm, void *pv)
  396. {
  397. SCODE sc;
  398. ULONG cbWritten;
  399. olDebugOut((DEB_ITRACE, "In MarshalPointer(%p, %p)\n", pstm, pv));
  400. #ifdef USEBASED
  401. ULONG ul = (ULONG)((ULONG_PTR)pv - (ULONG_PTR)DFBASEPTR);
  402. #endif
  403. sc = DfGetScode(pstm->Write(&ul, sizeof(ul), &cbWritten));
  404. if (SUCCEEDED(sc) && cbWritten != sizeof(ul))
  405. sc = STG_E_WRITEFAULT;
  406. olDebugOut((DEB_ITRACE, "Out MarshalPointer\n"));
  407. return sc;
  408. }
  409. //+--------------------------------------------------------------
  410. //
  411. // Function: MarshalContext, public
  412. //
  413. // Synopsis: Marshals a context
  414. //
  415. // Arguments: [pstm] - Marshal stream
  416. // [ppc] - Context
  417. // [dwDestContext] - Destination context
  418. // [pvDestContext] - Unreferenced
  419. // [mshlflags] - Marshal flags
  420. // [fMarshalOriginal] - Marshal original or not
  421. //
  422. // Returns: Appropriate status code
  423. //
  424. // History: 20-Aug-92 DrewB Created
  425. //
  426. //---------------------------------------------------------------
  427. SCODE MarshalContext(IStream *pstm,
  428. CPerContext *ppc,
  429. DWORD dwDestContext,
  430. LPVOID pvDestContext,
  431. DWORD mshlflags,
  432. #ifdef ASYNC
  433. BOOL const fMarshalILBs,
  434. #endif
  435. BOOL const fMarshalOriginal)
  436. {
  437. SCODE sc;
  438. olDebugOut((DEB_ITRACE, "In MarshalContext(%p, %p, %lu, %p, %lu, %d)\n",
  439. pstm, ppc, dwDestContext, pvDestContext, mshlflags,
  440. fMarshalOriginal));
  441. olChk(MarshalPointer(pstm, ppc->GetGlobal()));
  442. #ifdef ASYNC
  443. if (fMarshalILBs)
  444. #endif
  445. {
  446. olHChk(CoMarshalInterface(pstm, IID_ILockBytes, ppc->GetBase(),
  447. dwDestContext, pvDestContext, mshlflags));
  448. olHChk(CoMarshalInterface(pstm, IID_ILockBytes,
  449. (ILockBytes *)ppc->GetDirty(),
  450. dwDestContext, pvDestContext, mshlflags));
  451. if (fMarshalOriginal)
  452. olHChk(CoMarshalInterface(pstm, IID_ILockBytes, ppc->GetOriginal(),
  453. dwDestContext, pvDestContext, mshlflags));
  454. }
  455. olDebugOut((DEB_ITRACE, "Out MarshalContext\n"));
  456. EH_Err:
  457. return sc;
  458. }
  459. //+--------------------------------------------------------------
  460. //
  461. // Function: UnmarshalPointer, public
  462. //
  463. // Synopsis: Unmarshals a pointer
  464. //
  465. // Arguments: [pstm] - Marshal stream
  466. // [ppv] - Pointer return
  467. //
  468. // Returns: Appropriate status code
  469. //
  470. // Modifies: [ppv]
  471. //
  472. // History: 20-Aug-92 DrewB Created
  473. //
  474. //---------------------------------------------------------------
  475. SCODE UnmarshalPointer(IStream *pstm,
  476. void **ppv)
  477. {
  478. SCODE sc;
  479. ULONG cbRead;
  480. ULONG ul;
  481. olDebugOut((DEB_ITRACE, "In UnmarshalPointer(%p, %p)\n", pstm, ppv));
  482. sc = DfGetScode(pstm->Read(&ul, sizeof(ul), &cbRead));
  483. if (SUCCEEDED(sc) && cbRead != sizeof(ul))
  484. sc = STG_E_READFAULT;
  485. #ifdef USEBASED
  486. *ppv = (void *)(ul + (BYTE*)DFBASEPTR);
  487. #endif
  488. olDebugOut((DEB_ITRACE, "Out UnmarshalPointer => %p\n", *ppv));
  489. return sc;
  490. }
  491. //+--------------------------------------------------------------
  492. //
  493. // Function: UnmarshalContext, public
  494. //
  495. // Synopsis: Unmarshals a context
  496. //
  497. // Arguments: [pstm] - Marshal stream
  498. // [pppc] - Context return
  499. // [fUnmarshalOriginal] - Marshalled original exists or not
  500. // [fIsRoot] - Root unmarshal or not
  501. //
  502. // Returns: Appropriate status code
  503. //
  504. // Modifies: [pppc]
  505. //
  506. // History: 20-Aug-92 DrewB Created
  507. //
  508. //---------------------------------------------------------------
  509. SCODE UnmarshalContext(IStream *pstm,
  510. CGlobalContext *pgc,
  511. CPerContext **pppc,
  512. DWORD mshlflags,
  513. #ifdef ASYNC
  514. BOOL const fUnmarshalILBs,
  515. #endif
  516. BOOL const fUnmarshalOriginal,
  517. #ifdef MULTIHEAP
  518. ContextId cntxid,
  519. #endif
  520. BOOL const fIsRoot)
  521. {
  522. BOOL fNewContext;
  523. ILockBytes *plkbBase = NULL;
  524. CFileStream *pfstDirty = NULL;
  525. ILockBytes *plkbOriginal = NULL;
  526. SCODE sc, sc2;
  527. CPerContext *ppc;
  528. ULONG ulOpenLock = 0;
  529. olDebugOut((DEB_ITRACE, "In UnmarshalContext(%p, %p, %lu, %d, %d)\n",
  530. pstm, pppc, mshlflags, fUnmarshalOriginal, fIsRoot));
  531. ppc = pgc->Find(GetCurrentContextId());
  532. // ignore leaked contexts from processes that died and their ID got reused
  533. if (ppc != NULL && !ppc->IsHandleValid())
  534. ppc = NULL;
  535. fNewContext = (ppc == NULL);
  536. #ifdef MULTIHEAP
  537. // when marshaling to the same process, use the same heap
  538. // when marshaling to a different process, check the context list
  539. // if there is a matching percontext, use that heap
  540. if (GetCurrentContextId() != cntxid && ppc != NULL)
  541. {
  542. ppc->SetThreadAllocatorState(NULL); // set new base
  543. // Whenever we unmarshal into a different process, we create
  544. // a new mapping (of the same heap),
  545. // even if a mapping of the same heap may already exist in
  546. // the same process. For pointer identity, it is essential
  547. // that we find and use the existing heap.
  548. // process A ---marshal---> process B ---marshal----> process A
  549. // The "final" unmarshaled exposed object in process A should
  550. // match the original pointer used when the exposed object
  551. // was originally marshaled. To do this, we check the global
  552. // context list, and if there's a percontext match, we use
  553. // its allocator and heap mapping (and don't create a new one).
  554. // However, to actually search the global context list (it
  555. // lives in shared memory), we need a temporary mapping until
  556. // a matching percontext can be found and reused.
  557. // If not, then a new percontext is allocated and the temporary
  558. // mapping becomes "permanent" for the lifetime of the new percontext.
  559. }
  560. #endif
  561. if (fNewContext)
  562. {
  563. olMemTo(EH_Open,
  564. ppc = new (pgc->GetMalloc()) CPerContext(pgc->GetMalloc()));
  565. olChkTo(EH_ppc, ppc->InitFromGlobal(pgc));
  566. }
  567. #ifdef MULTIHEAP
  568. // take the ownership of the heap away from the temporary
  569. ppc->SetAllocatorState (NULL, &g_smAllocator);
  570. //ppc from above may have used incorrect base (base of temporary heap).
  571. // Since we're returning and storing an unbased pointer, we need to get
  572. // the real absolute pointer here. At this point, ppc will always be in
  573. // the context list, so we don't need to worry about a NULL return.
  574. ppc = pgc->Find(GetCurrentContextId());
  575. olAssert(ppc != NULL);
  576. #endif
  577. #ifdef ASYNC
  578. if (fUnmarshalILBs)
  579. {
  580. #endif
  581. // attempt to unmarshal all the interfaces first. this makes cleanup
  582. // easier.
  583. sc = CoUnmarshalInterface(pstm, IID_ILockBytes, (void **)&plkbBase);
  584. sc2 = CoUnmarshalInterface(pstm, IID_ILockBytes, (void **)&pfstDirty);
  585. sc = (SUCCEEDED(sc)) ? sc2 : sc; // sc = first failure code (if any)
  586. if (fUnmarshalOriginal)
  587. {
  588. sc2 = CoUnmarshalInterface(pstm, IID_ILockBytes,
  589. (void **)&plkbOriginal);
  590. sc = (SUCCEEDED(sc)) ? sc2 : sc; // sc = first failure code (if any)
  591. }
  592. // cleanup if any failure so far
  593. olChkTo(EH_plkbOriginal, sc);
  594. if (ppc->GetBase() != NULL)
  595. {
  596. // already have context, just release the things we unmarshaled.
  597. plkbBase->Release();
  598. plkbBase = NULL;
  599. }
  600. if (ppc->GetDirty() != NULL)
  601. {
  602. pfstDirty->Release();
  603. pfstDirty = NULL;
  604. }
  605. if ((plkbOriginal) && (ppc->GetOriginal() != NULL))
  606. {
  607. plkbOriginal->Release();
  608. plkbOriginal = NULL;
  609. }
  610. else if ((NULL == plkbOriginal) && plkbBase)
  611. {
  612. plkbBase->AddRef();
  613. plkbOriginal = plkbBase;
  614. }
  615. olAssert (plkbOriginal != NULL || ppc->GetOriginal() != NULL);
  616. // Make sure there is a reserved handle if this is a root
  617. // file-based lockbytes
  618. if (fIsRoot)
  619. {
  620. IFileLockBytes *pflkb;
  621. if (SUCCEEDED(DfGetScode((plkbOriginal ? plkbOriginal :
  622. ppc->GetOriginal())->
  623. QueryInterface(IID_IFileLockBytes,
  624. (void **)&pflkb))))
  625. {
  626. sc = DfGetScode(pflkb->ReserveHandle());
  627. pflkb->Release();
  628. olChkTo(EH_plkbOriginal, sc);
  629. }
  630. }
  631. #ifdef ASYNC
  632. }
  633. #endif
  634. if (fNewContext)
  635. {
  636. olAssert(plkbOriginal != NULL);
  637. // Take open locks if necessary
  638. if (fIsRoot && pgc->TakeLock())
  639. {
  640. olChkTo(EH_plkbOriginal,
  641. GetOpen(plkbOriginal, pgc->GetOpenLockFlags(),
  642. FALSE, &ulOpenLock));
  643. }
  644. ppc->SetILBInfo(plkbBase, pfstDirty, plkbOriginal, ulOpenLock);
  645. }
  646. else
  647. {
  648. if (ppc->GetBase() == NULL)
  649. {
  650. //Fill in the ILB fields
  651. ppc->SetILBInfo(plkbBase, pfstDirty, plkbOriginal, ulOpenLock);
  652. }
  653. ppc->AddRef();
  654. }
  655. *pppc = ppc;
  656. olDebugOut((DEB_ITRACE, "Out UnmarshalContext => %p\n", *pppc));
  657. return S_OK;
  658. EH_ppc:
  659. // Preserve plkbOriginal so the lock is released even after the
  660. // context releases things;
  661. plkbOriginal->AddRef();
  662. ppc->Release();
  663. pfstDirty = NULL;
  664. plkbBase = NULL;
  665. EH_Open:
  666. if (ulOpenLock != 0)
  667. {
  668. olAssert(plkbOriginal != NULL);
  669. ReleaseOpen(plkbOriginal, pgc->GetOpenLockFlags(), ulOpenLock);
  670. }
  671. EH_plkbOriginal:
  672. if (plkbOriginal)
  673. plkbOriginal->Release();
  674. if (pfstDirty)
  675. pfstDirty->Release();
  676. if (plkbBase)
  677. plkbBase->Release();
  678. return sc;
  679. }
  680. //+---------------------------------------------------------------------------
  681. //
  682. // Function: ReleaseContext, public
  683. //
  684. // Synopsis: Releases references for a context's marshal data
  685. //
  686. // Arguments: [pstm] - Marshal stream
  687. // [fHasOriginal] - Original is marshalled
  688. // [mshlflags] - Marshal flags
  689. //
  690. // Returns: Appropriate status code
  691. //
  692. // History: 20-Nov-92 DrewB Created
  693. //
  694. //----------------------------------------------------------------------------
  695. #ifdef WIN32
  696. SCODE ReleaseContext(IStream *pstm,
  697. #ifdef ASYNC
  698. BOOL const fUnmarshalILBs,
  699. #endif
  700. BOOL const fHasOriginal,
  701. DWORD mshlflags)
  702. {
  703. CGlobalContext *pgc;
  704. SCODE sc;
  705. olDebugOut((DEB_ITRACE, "In ReleaseContext(%p, %d, %lu)\n", pstm,
  706. fHasOriginal, mshlflags));
  707. olChk(UnmarshalPointer(pstm, (void **)&pgc));
  708. if (fUnmarshalILBs)
  709. {
  710. olHChk(CoReleaseMarshalData(pstm));
  711. olHChk(CoReleaseMarshalData(pstm));
  712. if (fHasOriginal)
  713. olHChk(CoReleaseMarshalData(pstm));
  714. }
  715. olDebugOut((DEB_ITRACE, "Out ReleaseContext\n"));
  716. EH_Err:
  717. return sc;
  718. }
  719. #endif
  720. #ifdef MULTIHEAP
  721. //+---------------------------------------------------------------------------
  722. //
  723. // Function: MarshalSharedMemory, public
  724. //
  725. // Synopsis: marshals the shared memory context
  726. //
  727. // Arguments: [pstm] - Marshal stream
  728. // [ppc] - per context structure
  729. //
  730. // Returns: Appropriate status code
  731. //
  732. // History: 02-Dec-95 HenryLee Created
  733. //
  734. //----------------------------------------------------------------------------
  735. SCODE MarshalSharedMemory (IStream *pstStm, CPerContext *ppc)
  736. {
  737. SCODE sc = S_OK;
  738. ULONG cbWritten;
  739. ULONG ulHeapName;
  740. ContextId cntxid = GetCurrentContextId();
  741. ULONGLONG ulppc = (ULONGLONG) ppc;
  742. ulHeapName = g_smAllocator.GetHeapName();
  743. olHChk(pstStm->Write((void*) &ulHeapName, sizeof(ulHeapName), &cbWritten));
  744. if (cbWritten != sizeof(ulHeapName))
  745. olErr(EH_Err, STG_E_WRITEFAULT);
  746. olHChk(pstStm->Write((void*) &cntxid, sizeof(cntxid), &cbWritten));
  747. if (cbWritten != sizeof(cntxid))
  748. olErr(EH_Err, STG_E_WRITEFAULT);
  749. olHChk(pstStm->Write((void*) &ulppc, sizeof(ulppc), &cbWritten));
  750. if (cbWritten != sizeof(ulppc))
  751. olErr(EH_Err, STG_E_WRITEFAULT);
  752. EH_Err:
  753. return sc;
  754. }
  755. //+---------------------------------------------------------------------------
  756. //
  757. // Function: SkipSharedMemory, public
  758. //
  759. // Synopsis: Cleanup marshaling packet during CoReleaseMarshalData
  760. //
  761. // Arguments: [pstm] - Marshal stream
  762. //
  763. // Returns: Appropriate status code
  764. //
  765. // History: 02-Dec-95 HenryLee Created
  766. //
  767. //----------------------------------------------------------------------------
  768. SCODE SkipSharedMemory (IStream *pstStm, DWORD mshlflags)
  769. {
  770. SCODE sc = S_OK;
  771. ULONG cbRead;
  772. ULONG ulHeapName;
  773. ContextId cntxid;
  774. ULONGLONG ulppc;
  775. olChk(pstStm->Read(&ulHeapName, sizeof(ulHeapName), &cbRead));
  776. if (cbRead != sizeof(ulHeapName))
  777. olErr(EH_Err, STG_E_READFAULT);
  778. olChk(pstStm->Read(&cntxid, sizeof(cntxid), &cbRead));
  779. if (cbRead != sizeof(cntxid))
  780. olErr(EH_Err, STG_E_READFAULT);
  781. olChk(pstStm->Read(&ulppc, sizeof(ulppc), &cbRead));
  782. if (cbRead != sizeof(ulppc))
  783. olErr(EH_Err, STG_E_READFAULT);
  784. EH_Err:
  785. return sc;
  786. }
  787. //+---------------------------------------------------------------------------
  788. //
  789. // Function: UnMarshalSharedMemory, public
  790. //
  791. // Synopsis: Unmarshals the shared memory context
  792. //
  793. // Arguments: [pstm] - Marshal stream
  794. //
  795. // Returns: Appropriate status code
  796. //
  797. // History: 02-Dec-95 HenryLee Created
  798. //
  799. //----------------------------------------------------------------------------
  800. SCODE UnmarshalSharedMemory (IStream *pstStm, DWORD mshlflags,
  801. CPerContext *ppcOwner, ContextId *pcntxid)
  802. {
  803. SCODE sc = S_OK;
  804. ULONG cbRead;
  805. ULONG ulHeapName;
  806. ContextId cntxid;
  807. CPerContext *ppc;
  808. ULONGLONG ulppc;
  809. olHChk(pstStm->Read(&ulHeapName, sizeof(ulHeapName), &cbRead));
  810. if (cbRead != sizeof(ulHeapName))
  811. olErr(EH_Err, STG_E_READFAULT);
  812. olHChk(pstStm->Read(&cntxid, sizeof(cntxid), &cbRead));
  813. if (cbRead != sizeof(cntxid))
  814. olErr(EH_Err, STG_E_READFAULT);
  815. olHChk(pstStm->Read(&ulppc, sizeof(ulppc), &cbRead));
  816. if (cbRead != sizeof(ulppc))
  817. olErr(EH_Err, STG_E_READFAULT);
  818. ppc = (CPerContext *) ulppc;
  819. #if defined(_WIN64)
  820. if ((mshlflags & MSHLFLAGS_STG_WIN64) == 0)
  821. olErr (EH_Err, STG_E_INVALIDFUNCTION);
  822. #else
  823. if ((mshlflags & MSHLFLAGS_STG_WIN64) != 0)
  824. olErr (EH_Err, STG_E_INVALIDFUNCTION);
  825. #endif
  826. *pcntxid = cntxid;
  827. if (GetCurrentContextId() == cntxid)
  828. {
  829. // marshaling to the same process, reuse the per context and heap
  830. // in the case of marshaling to another thread
  831. // the per context takes ownership of the thread's allocator
  832. ppc->SetThreadAllocatorState(NULL);
  833. }
  834. else
  835. {
  836. // marshaling to another process on the same machine
  837. // if the name of heap is different that current one, open it
  838. if (g_smAllocator.GetHeapName() != ulHeapName)
  839. {
  840. DfInitSharedMemBase();
  841. olChk(DfSyncSharedMemory(ulHeapName));
  842. }
  843. // Because the unmarshaling code calls IStream::Read,
  844. // possibly using another shared heap, we need a temporary
  845. // owner until the real CPerContext is unmarshaled
  846. ppcOwner->GetThreadAllocatorState();
  847. ppcOwner->SetThreadAllocatorState(NULL);
  848. }
  849. EH_Err:
  850. return sc;
  851. }
  852. #endif
  853. #ifdef ASYNC
  854. SCODE MarshalConnection(IStream *pstm,
  855. CAsyncConnection *pcpoint,
  856. DWORD dwDestContext,
  857. LPVOID pvDestContext,
  858. DWORD mshlflags)
  859. {
  860. SCODE sc;
  861. ULONG cbWritten;
  862. IDocfileAsyncConnectionPoint *pdacp = pcpoint->GetMarshalPoint();
  863. BOOL fIsInitialized = (pdacp != NULL);
  864. //Write out the pointer.
  865. olHChk(pstm->Write(&fIsInitialized,
  866. sizeof(BOOL),
  867. &cbWritten));
  868. if (cbWritten != sizeof(BOOL))
  869. {
  870. olErr(EH_Err, STG_E_READFAULT);
  871. }
  872. if (fIsInitialized)
  873. {
  874. //If the pointer was NULL, we don't need to worry about actually
  875. //marshalling anything, and we can detect this in the unmarshal
  876. //path. If it wasn't NULL, we need to store some additional
  877. //information: The async flags and the actual connection point,
  878. //which will be standard marshalled.
  879. DWORD dwAsyncFlags = pcpoint->GetAsyncFlags();
  880. olChk(pstm->Write(&dwAsyncFlags, sizeof(DWORD), &cbWritten));
  881. if (cbWritten != sizeof(DWORD))
  882. {
  883. olErr(EH_Err, STG_E_WRITEFAULT);
  884. }
  885. //Finally, standard marshal the connection point itself.
  886. olHChk(CoMarshalInterface(pstm,
  887. IID_IDocfileAsyncConnectionPoint,
  888. pdacp,
  889. dwDestContext,
  890. pvDestContext,
  891. mshlflags));
  892. }
  893. EH_Err:
  894. return sc;
  895. }
  896. SCODE UnmarshalConnection(IStream *pstm,
  897. DWORD *pdwAsyncFlags,
  898. IDocfileAsyncConnectionPoint **ppdacp,
  899. DWORD mshlflags)
  900. {
  901. SCODE sc;
  902. BOOL fIsInitialized;
  903. ULONG cbRead;
  904. *ppdacp = NULL;
  905. *pdwAsyncFlags = 0;
  906. olHChk(pstm->Read(&fIsInitialized, sizeof(BOOL), &cbRead));
  907. if (cbRead != sizeof(BOOL))
  908. {
  909. olErr(EH_Err, STG_E_READFAULT);
  910. }
  911. if (fIsInitialized)
  912. {
  913. olChk(pstm->Read(pdwAsyncFlags, sizeof(DWORD), &cbRead));
  914. if (cbRead != sizeof(DWORD))
  915. {
  916. olErr(EH_Err, STG_E_READFAULT);
  917. }
  918. sc = CoUnmarshalInterface(pstm,
  919. IID_IDocfileAsyncConnectionPoint,
  920. (void **)ppdacp);
  921. }
  922. EH_Err:
  923. return sc;
  924. }
  925. SCODE ReleaseConnection(IStream *pstm, DWORD mshlflags)
  926. {
  927. SCODE sc;
  928. ULONG cbRead;
  929. BOOL fIsInitialized;
  930. DWORD dwAsyncFlags;
  931. olHChk(pstm->Read(&fIsInitialized, sizeof(BOOL), &cbRead));
  932. if (cbRead != sizeof(BOOL))
  933. {
  934. olErr(EH_Err, STG_E_READFAULT);
  935. }
  936. if (fIsInitialized)
  937. {
  938. olChk(pstm->Read(&dwAsyncFlags, sizeof(DWORD), &cbRead));
  939. if (cbRead != sizeof(DWORD))
  940. {
  941. olErr(EH_Err, STG_E_READFAULT);
  942. }
  943. olHChk(CoReleaseMarshalData(pstm));
  944. }
  945. EH_Err:
  946. return sc;
  947. }
  948. #endif