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.

1121 lines
27 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (c) 1997 - 1999 Microsoft Corporation. All rights reserved.
  4. File:
  5. udt.cxx
  6. Abstract:
  7. Marshalling support for user defined data types.
  8. Author:
  9. ShannonC 21-Apr-1997
  10. Environment:
  11. Windows NT and Windows 95. We do not support DOS and Win16.
  12. Revision History:
  13. --*/
  14. #include <ndrp.h>
  15. #include <oaidl.h>
  16. #include <typegen.h>
  17. #include <interp2.h>
  18. extern USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[3];
  19. class CTypeFactory : public ITypeFactory, public IClassFactory
  20. {
  21. public:
  22. HRESULT STDMETHODCALLTYPE QueryInterface(
  23. IN REFIID riid,
  24. OUT void **ppv);
  25. ULONG STDMETHODCALLTYPE AddRef();
  26. ULONG STDMETHODCALLTYPE Release();
  27. HRESULT STDMETHODCALLTYPE CreateFromTypeInfo(
  28. IN ITypeInfo *pTypeInfo,
  29. IN REFIID riid,
  30. OUT IUnknown **ppv);
  31. HRESULT STDMETHODCALLTYPE CreateInstance(
  32. IN IUnknown * pUnkOuter,
  33. IN REFIID riid,
  34. OUT void ** ppv);
  35. HRESULT STDMETHODCALLTYPE LockServer(
  36. IN BOOL fLock);
  37. CTypeFactory();
  38. private:
  39. long _cRefs;
  40. };
  41. CLSID CLSID_TypeFactory = { /* b5866878-bd99-11d0-b04b-00c04fd91550 */
  42. 0xb5866878,
  43. 0xbd99,
  44. 0x11d0,
  45. {0xb0, 0x4b, 0x00, 0xc0, 0x4f, 0xd9, 0x15, 0x50}
  46. };
  47. class CTypeMarshal : public ITypeMarshal, public IMarshal
  48. {
  49. public:
  50. // IUnknown methods
  51. HRESULT STDMETHODCALLTYPE QueryInterface(
  52. IN REFIID riid,
  53. OUT void **ppvObject);
  54. ULONG STDMETHODCALLTYPE AddRef();
  55. ULONG STDMETHODCALLTYPE Release();
  56. // ITypeMarshal methods
  57. HRESULT STDMETHODCALLTYPE Size(
  58. IN void * pType,
  59. IN DWORD dwDestContext,
  60. IN void * pvDestContext,
  61. OUT ULONG * pSize);
  62. HRESULT STDMETHODCALLTYPE Marshal(
  63. IN void * pType,
  64. IN DWORD dwDestContext,
  65. IN void * pvDestContext,
  66. IN ULONG cbBufferLength,
  67. OUT BYTE * pBuffer,
  68. OUT ULONG * pcbWritten);
  69. HRESULT STDMETHODCALLTYPE Unmarshal(
  70. IN void * pType,
  71. IN DWORD dwFlags,
  72. IN ULONG cbBufferLength,
  73. IN BYTE * pBuffer,
  74. OUT ULONG * pcbRead);
  75. HRESULT STDMETHODCALLTYPE Free(
  76. IN void * pType);
  77. // IMarshal methods.
  78. HRESULT STDMETHODCALLTYPE GetUnmarshalClass
  79. (
  80. IN REFIID riid,
  81. IN void *pv,
  82. IN DWORD dwDestContext,
  83. IN void *pvDestContext,
  84. IN DWORD mshlflags,
  85. OUT CLSID *pCid
  86. );
  87. HRESULT STDMETHODCALLTYPE GetMarshalSizeMax
  88. (
  89. IN REFIID riid,
  90. IN void *pv,
  91. IN DWORD dwDestContext,
  92. IN void *pvDestContext,
  93. IN DWORD mshlflags,
  94. OUT DWORD *pSize
  95. );
  96. HRESULT STDMETHODCALLTYPE MarshalInterface
  97. (
  98. IN IStream *pStm,
  99. IN REFIID riid,
  100. IN void *pv,
  101. IN DWORD dwDestContext,
  102. IN void *pvDestContext,
  103. IN DWORD mshlflags
  104. );
  105. HRESULT STDMETHODCALLTYPE UnmarshalInterface
  106. (
  107. IN IStream *pStm,
  108. IN REFIID riid,
  109. OUT void **ppv
  110. );
  111. HRESULT STDMETHODCALLTYPE ReleaseMarshalData
  112. (
  113. IN IStream *pStm
  114. );
  115. HRESULT STDMETHODCALLTYPE DisconnectObject
  116. (
  117. IN DWORD dwReserved
  118. );
  119. CTypeMarshal(
  120. IN PFORMAT_STRING pFormatString,
  121. IN ULONG length,
  122. IN ULONG offset);
  123. private:
  124. ~CTypeMarshal();
  125. long _cRefs;
  126. ULONG _offset;
  127. ULONG _length;
  128. PFORMAT_STRING _pFormatString;
  129. MIDL_STUB_DESC _StubDesc;
  130. };
  131. //+---------------------------------------------------------------------------
  132. //
  133. // Function: DllGetClassObject
  134. //
  135. // Synopsis: Gets an interface pointer to the specified class object.
  136. //
  137. // Arguments: rclsid - CLSID for the class object.
  138. // riid - IID for the requested interface
  139. // [ppv] - Returns the interface pointer to the class object.
  140. //
  141. // Returns: S_OK
  142. // CLASS_E_CLASSNOTAVAILABLE
  143. // E_INVALIDARG
  144. // E_NOINTERFACE
  145. // E_OUTOFMEMORY
  146. //
  147. //----------------------------------------------------------------------------
  148. STDAPI DllGetClassObject(
  149. REFCLSID rclsid,
  150. REFIID riid,
  151. void ** ppv)
  152. {
  153. HRESULT hr;
  154. RPC_STATUS rc;
  155. __try
  156. {
  157. *ppv = NULL;
  158. //Initialize the RPC heap.
  159. rc = NdrpPerformRpcInitialization();
  160. if (rc == RPC_S_OK)
  161. {
  162. if(rclsid == CLSID_TypeFactory)
  163. {
  164. CTypeFactory * pTypeFactory;
  165. pTypeFactory = new CTypeFactory;
  166. if(pTypeFactory != NULL)
  167. {
  168. hr = pTypeFactory->QueryInterface(riid, ppv);
  169. pTypeFactory->Release();
  170. }
  171. else
  172. {
  173. hr = E_OUTOFMEMORY;
  174. }
  175. }
  176. else
  177. {
  178. hr = CLASS_E_CLASSNOTAVAILABLE;
  179. }
  180. }
  181. else
  182. hr = HRESULT_FROM_WIN32(rc);
  183. }
  184. __except(EXCEPTION_EXECUTE_HANDLER)
  185. {
  186. hr = E_INVALIDARG;
  187. }
  188. return hr;
  189. }
  190. //+---------------------------------------------------------------------------
  191. //
  192. // Method: CTypeFactory::CTypeFactory
  193. //
  194. // Synopsis: Constructor for CTypeFactory
  195. //
  196. //----------------------------------------------------------------------------
  197. CTypeFactory::CTypeFactory()
  198. : _cRefs(1)
  199. {
  200. }
  201. //+---------------------------------------------------------------------------
  202. //
  203. // Method: CTypeFactory::QueryInterface
  204. //
  205. // Synopsis: Gets a pointer to the specified interface.
  206. //
  207. // Arguments: riid - IID of the requested interface.
  208. // ppv - Returns the interface pointer.
  209. //
  210. // Returns: S_OK
  211. // E_INVALIDARG
  212. // E_NOINTERFACE
  213. //
  214. //----------------------------------------------------------------------------
  215. HRESULT STDMETHODCALLTYPE
  216. CTypeFactory::QueryInterface(
  217. REFIID riid,
  218. void **ppv)
  219. {
  220. HRESULT hr;
  221. __try
  222. {
  223. *ppv = NULL;
  224. if(IsEqualIID(riid, IID_IUnknown) ||
  225. IsEqualIID(riid, IID_ITypeFactory))
  226. {
  227. AddRef();
  228. *ppv = (ITypeFactory *) this;
  229. hr = S_OK;
  230. }
  231. else if(IsEqualIID(riid, IID_IClassFactory))
  232. {
  233. AddRef();
  234. *ppv = (IClassFactory *) this;
  235. hr = S_OK;
  236. }
  237. else
  238. {
  239. hr = E_NOINTERFACE;
  240. }
  241. }
  242. __except(EXCEPTION_EXECUTE_HANDLER)
  243. {
  244. hr = E_INVALIDARG;
  245. }
  246. return hr;
  247. }
  248. //+---------------------------------------------------------------------------
  249. //
  250. // Method: CTypeFactory::AddRef
  251. //
  252. // Synopsis: Increment the reference count.
  253. //
  254. // Arguments: void
  255. //
  256. // Returns: ULONG -- the new reference count
  257. //
  258. // Notes: Use InterlockedIncrement to make it multi-thread safe.
  259. //
  260. //----------------------------------------------------------------------------
  261. ULONG STDMETHODCALLTYPE
  262. CTypeFactory::AddRef(void)
  263. {
  264. InterlockedIncrement(&_cRefs);
  265. return _cRefs;
  266. }
  267. //+---------------------------------------------------------------------------
  268. //
  269. // Method: CTypeFactory::Release
  270. //
  271. // Synopsis: Decrement the reference count.
  272. //
  273. // Arguments: void
  274. //
  275. // Returns: ULONG -- the remaining reference count
  276. //
  277. // Notes: Use InterlockedDecrement to make it multi-thread safe.
  278. // We use a local variable so that we don't access
  279. // a data member after decrementing the reference count.
  280. //
  281. //----------------------------------------------------------------------------
  282. ULONG STDMETHODCALLTYPE
  283. CTypeFactory::Release(void)
  284. {
  285. ULONG count = _cRefs - 1;
  286. if(0 == InterlockedDecrement(&_cRefs))
  287. {
  288. delete this;
  289. count = 0;
  290. }
  291. return count;
  292. }
  293. //+-------------------------------------------------------------------------
  294. //
  295. // Member: CTypeFactory::LockServer
  296. //
  297. // Synopsis: Lock the server. Does nothing.
  298. //
  299. // Arguments: fLock
  300. //
  301. // Returns: S_OK
  302. //
  303. //--------------------------------------------------------------------------
  304. STDMETHODIMP CTypeFactory::LockServer(BOOL fLock)
  305. {
  306. return S_OK;
  307. }
  308. //+-------------------------------------------------------------------------
  309. //
  310. // Member: CTypeFactory::CreateInstance
  311. //
  312. // Synopsis: Creates a CTypeMarshal.
  313. //
  314. // Arguments: [pUnkOuter] - The controlling unknown (for aggregation)
  315. // [iid] - The requested interface ID.
  316. // [ppv] - Returns the pointer to the new object
  317. //
  318. // Returns: S_OK
  319. // CLASS_E_NOAGGREGATION
  320. // E_NOINTERFACE
  321. // E_OUTOFMEMORY
  322. // E_INVALIDARG
  323. //
  324. //--------------------------------------------------------------------------
  325. STDMETHODIMP CTypeFactory::CreateInstance(
  326. IUnknown * pUnkOuter,
  327. REFIID riid,
  328. void ** ppv)
  329. {
  330. HRESULT hr;
  331. IID iid;
  332. __try
  333. {
  334. //Parameter validation.
  335. *ppv = NULL;
  336. iid = riid;
  337. if(NULL == pUnkOuter)
  338. {
  339. CTypeMarshal *pTypeMarshal = new CTypeMarshal(NULL, 0, 0);
  340. if(pTypeMarshal != NULL)
  341. {
  342. hr = pTypeMarshal->QueryInterface(iid, ppv);
  343. pTypeMarshal->Release();
  344. }
  345. else
  346. {
  347. hr = E_OUTOFMEMORY;
  348. }
  349. }
  350. else
  351. {
  352. //CTypeMarshal does not support aggregation.
  353. hr = CLASS_E_NOAGGREGATION;
  354. }
  355. }
  356. __except(EXCEPTION_EXECUTE_HANDLER)
  357. {
  358. hr = E_INVALIDARG;
  359. }
  360. return hr;
  361. }
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Method: CTypeFactory::CreateFromTypeInfo
  365. //
  366. // Synopsis: Create a type marshaller from the typeinfo.
  367. //
  368. // Arguments: void
  369. //
  370. // Returns: S_OK
  371. // DISP_E_BADVARTYPE
  372. // E_INVALIDARG
  373. // E_NOINTERFACE
  374. // E_OUTOFMEMORY
  375. //
  376. //----------------------------------------------------------------------------
  377. HRESULT STDMETHODCALLTYPE
  378. CTypeFactory::CreateFromTypeInfo(
  379. IN ITypeInfo * pTypeInfo,
  380. IN REFIID riid,
  381. OUT IUnknown ** ppv)
  382. {
  383. HRESULT hr;
  384. CTypeMarshal * pTypeMarshal;
  385. PFORMAT_STRING pFormatString;
  386. USHORT length;
  387. USHORT offset;
  388. PARAMINFO paramInfo;
  389. CTypeGen *ptypeGen = new CTypeGen;
  390. DWORD structInfo = 0;
  391. if (NULL == ptypeGen)
  392. return E_OUTOFMEMORY;
  393. __try
  394. {
  395. *ppv = NULL;
  396. //Build a type format string from the typeinfo.
  397. paramInfo.vt = VT_USERDEFINED;
  398. paramInfo.pTypeInfo = pTypeInfo;
  399. pTypeInfo->AddRef();
  400. hr = ptypeGen->RegisterType(&paramInfo,
  401. &offset,
  402. &structInfo);
  403. if (SUCCEEDED(hr) && (0 == offset))
  404. {
  405. ASSERT( !(paramInfo.vt & VT_BYREF));
  406. switch (paramInfo.vt)
  407. {
  408. case VT_I1:
  409. case VT_UI1:
  410. offset = 734;
  411. break;
  412. case VT_I2:
  413. case VT_UI2:
  414. case VT_BOOL:
  415. offset = 738;
  416. break;
  417. case VT_I4:
  418. case VT_UI4:
  419. case VT_INT:
  420. case VT_UINT:
  421. case VT_ERROR:
  422. case VT_HRESULT:
  423. offset = 742;
  424. break;
  425. case VT_I8:
  426. case VT_UI8:
  427. case VT_CY:
  428. offset = 310;
  429. break;
  430. case VT_R4:
  431. offset = 746;
  432. break;
  433. case VT_R8:
  434. case VT_DATE:
  435. offset = 750;
  436. break;
  437. }
  438. }
  439. if(SUCCEEDED(hr))
  440. {
  441. hr = ptypeGen->GetTypeFormatString(&pFormatString, &length);
  442. if(SUCCEEDED(hr))
  443. {
  444. pTypeMarshal = new CTypeMarshal(pFormatString, length, offset);
  445. if(pTypeMarshal != NULL)
  446. {
  447. hr = pTypeMarshal->QueryInterface(riid, (void **) ppv);
  448. pTypeMarshal->Release();
  449. }
  450. else
  451. {
  452. hr = E_OUTOFMEMORY;
  453. ReleaseTypeFormatString(pFormatString);
  454. }
  455. }
  456. }
  457. delete ptypeGen; // fix compile warning
  458. }
  459. __except(EXCEPTION_EXECUTE_HANDLER)
  460. {
  461. delete ptypeGen; // fix compile warning
  462. hr = E_INVALIDARG;
  463. }
  464. return hr;
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Method: CTypeMarshal::CTypeMarshal
  469. //
  470. // Synopsis: Constructor for CTypeMarshal
  471. //
  472. //----------------------------------------------------------------------------
  473. CTypeMarshal::CTypeMarshal(
  474. IN PFORMAT_STRING pFormatString,
  475. IN ULONG length,
  476. IN ULONG offset)
  477. : _pFormatString(pFormatString), _length(length), _offset(offset), _cRefs(1)
  478. {
  479. //Initialize the MIDL_STUB_DESC.
  480. MIDL_memset(&_StubDesc, 0, sizeof(_StubDesc));
  481. _StubDesc.pfnAllocate = NdrOleAllocate;
  482. _StubDesc.pfnFree = NdrOleFree;
  483. _StubDesc.pFormatTypes = pFormatString;
  484. #if !defined(__RPC_WIN64__)
  485. _StubDesc.Version = 0x20000; /* Ndr library version */
  486. _StubDesc.MIDLVersion = MIDL_VERSION_3_0_44;
  487. #else
  488. _StubDesc.Version = 0x50002; /* Ndr library version */
  489. _StubDesc.MIDLVersion = MIDL_VERSION_5_2_202;
  490. #endif
  491. _StubDesc.aUserMarshalQuadruple = UserMarshalRoutines;
  492. }
  493. //+---------------------------------------------------------------------------
  494. //
  495. // Method: CTypeMarshal::~CTypeMarshal
  496. //
  497. // Synopsis: Destructor for CTypeMarshal
  498. //
  499. //----------------------------------------------------------------------------
  500. CTypeMarshal::~CTypeMarshal()
  501. {
  502. ReleaseTypeFormatString(_pFormatString);
  503. }
  504. //+---------------------------------------------------------------------------
  505. //
  506. // Method: CTypeMarshal::QueryInterface
  507. //
  508. // Synopsis: Gets a pointer to the specified interface.
  509. //
  510. // Arguments: riid - IID of the requested interface.
  511. // ppv - Returns the interface pointer.
  512. //
  513. // Returns: S_OK
  514. // E_INVALIDARG
  515. // E_NOINTERFACE
  516. //
  517. //----------------------------------------------------------------------------
  518. HRESULT STDMETHODCALLTYPE
  519. CTypeMarshal::QueryInterface(
  520. REFIID riid,
  521. void **ppv)
  522. {
  523. HRESULT hr;
  524. __try
  525. {
  526. *ppv = NULL;
  527. if(IsEqualIID(riid, IID_IUnknown) ||
  528. IsEqualIID(riid, IID_ITypeMarshal))
  529. {
  530. AddRef();
  531. *ppv = (ITypeMarshal *) this;
  532. hr = S_OK;
  533. }
  534. else if (IsEqualIID(riid, IID_IMarshal))
  535. {
  536. AddRef();
  537. *ppv = (IMarshal *) this;
  538. hr = S_OK;
  539. }
  540. else
  541. {
  542. hr = E_NOINTERFACE;
  543. }
  544. }
  545. __except(EXCEPTION_EXECUTE_HANDLER)
  546. {
  547. hr = E_INVALIDARG;
  548. }
  549. return hr;
  550. }
  551. //+---------------------------------------------------------------------------
  552. //
  553. // Method: CTypeMarshal::AddRef
  554. //
  555. // Synopsis: Increment the reference count.
  556. //
  557. // Arguments: void
  558. //
  559. // Returns: ULONG -- the new reference count
  560. //
  561. // Notes: Use InterlockedIncrement to make it multi-thread safe.
  562. //
  563. //----------------------------------------------------------------------------
  564. ULONG STDMETHODCALLTYPE
  565. CTypeMarshal::AddRef(void)
  566. {
  567. InterlockedIncrement(&_cRefs);
  568. return _cRefs;
  569. }
  570. //+---------------------------------------------------------------------------
  571. //
  572. // Method: CTypeMarshal::Release
  573. //
  574. // Synopsis: Decrement the reference count.
  575. //
  576. // Arguments: void
  577. //
  578. // Returns: ULONG -- the remaining reference count
  579. //
  580. // Notes: Use InterlockedDecrement to make it multi-thread safe.
  581. // We use a local variable so that we don't access
  582. // a data member after decrementing the reference count.
  583. //
  584. //----------------------------------------------------------------------------
  585. ULONG STDMETHODCALLTYPE
  586. CTypeMarshal::Release(void)
  587. {
  588. ULONG count = _cRefs - 1;
  589. if(0 == InterlockedDecrement(&_cRefs))
  590. {
  591. delete this;
  592. count = 0;
  593. }
  594. return count;
  595. }
  596. //+---------------------------------------------------------------------------
  597. //
  598. // Method: CTypeMarshal::Size
  599. //
  600. // Synopsis: Computes the size of the marshalled data type.
  601. //
  602. // Returns: S_OK
  603. // E_INVALIDARG
  604. //
  605. //----------------------------------------------------------------------------
  606. HRESULT STDMETHODCALLTYPE
  607. CTypeMarshal::Size(
  608. IN void * pType,
  609. IN DWORD dwDestContext,
  610. IN void * pvDestContext,
  611. OUT ULONG * pSize)
  612. {
  613. HRESULT hr = S_OK;
  614. MIDL_STUB_MESSAGE StubMsg;
  615. PFORMAT_STRING pTypeFormat;
  616. __try
  617. {
  618. if(!_pFormatString)
  619. return E_UNEXPECTED;
  620. pTypeFormat = _pFormatString + _offset;
  621. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  622. StubMsg.StubDesc = &_StubDesc;
  623. StubMsg.pfnFree = NdrOleFree;
  624. StubMsg.pfnAllocate = NdrOleAllocate;
  625. StubMsg.IsClient = 1;
  626. StubMsg.BufferLength = 1; //Reserve space for an alignment gap.
  627. StubMsg.dwDestContext = dwDestContext;
  628. StubMsg.pvDestContext = pvDestContext;
  629. (*pfnSizeRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  630. &StubMsg,
  631. (unsigned char *)pType,
  632. pTypeFormat);
  633. *pSize = StubMsg.BufferLength - 1;
  634. }
  635. __except(EXCEPTION_EXECUTE_HANDLER)
  636. {
  637. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  638. }
  639. return hr;
  640. }
  641. //+---------------------------------------------------------------------------
  642. //
  643. // Method: CTypeMarshal::Marshal
  644. //
  645. // Synopsis: Marshals the user-defined type into a buffer.
  646. //
  647. // Returns: S_OK
  648. // E_INVALIDARG
  649. //
  650. //----------------------------------------------------------------------------
  651. HRESULT STDMETHODCALLTYPE
  652. CTypeMarshal::Marshal(
  653. IN void * pType,
  654. IN DWORD dwDestContext,
  655. IN void * pvDestContext,
  656. IN ULONG cbBufferLength,
  657. OUT BYTE * pBuffer,
  658. OUT ULONG * pcbWritten)
  659. {
  660. HRESULT hr = S_OK;
  661. MIDL_STUB_MESSAGE StubMsg;
  662. RPC_MESSAGE RpcMsg;
  663. PFORMAT_STRING pTypeFormat;
  664. __try
  665. {
  666. if(!_pFormatString)
  667. return E_UNEXPECTED;
  668. pTypeFormat = _pFormatString + _offset;
  669. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  670. StubMsg.StubDesc = &_StubDesc;
  671. StubMsg.pfnFree = NdrOleFree;
  672. StubMsg.pfnAllocate = NdrOleAllocate;
  673. StubMsg.IsClient = 1;
  674. StubMsg.dwDestContext = dwDestContext;
  675. StubMsg.pvDestContext = pvDestContext;
  676. StubMsg.Buffer = pBuffer;
  677. MIDL_memset(&RpcMsg, 0, sizeof(RpcMsg));
  678. RpcMsg.DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
  679. RpcMsg.Buffer = pBuffer;
  680. RpcMsg.BufferLength = cbBufferLength;
  681. StubMsg.RpcMsg = &RpcMsg;
  682. (*pfnMarshallRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  683. &StubMsg,
  684. (unsigned char *)pType,
  685. pTypeFormat);
  686. *pcbWritten = (ULONG)(StubMsg.Buffer - pBuffer);
  687. }
  688. __except(EXCEPTION_EXECUTE_HANDLER)
  689. {
  690. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  691. }
  692. return hr;
  693. }
  694. //+---------------------------------------------------------------------------
  695. //
  696. // Method: CTypeMarshal::Unmarshal
  697. //
  698. // Synopsis: Unmarshals a user-defined type from a buffer.
  699. //
  700. // Returns: S_OK
  701. // E_INVALIDARG
  702. //
  703. //----------------------------------------------------------------------------
  704. HRESULT STDMETHODCALLTYPE
  705. CTypeMarshal::Unmarshal(
  706. OUT void * pType,
  707. IN DWORD dwFlags,
  708. IN ULONG cbBufferLength,
  709. IN BYTE * pBuffer,
  710. OUT ULONG * pcbRead)
  711. {
  712. HRESULT hr = S_OK;
  713. MIDL_STUB_MESSAGE StubMsg;
  714. RPC_MESSAGE RpcMsg;
  715. PFORMAT_STRING pTypeFormat;
  716. __try
  717. {
  718. if(pcbRead)
  719. *pcbRead = 0;
  720. if(!_pFormatString)
  721. return E_UNEXPECTED;
  722. pTypeFormat = _pFormatString + _offset;
  723. // HACK! OA might pass in 0xffffffff, which
  724. // will break the attack checking in ndr engine.
  725. // what we do now is mask off the highest byte.
  726. // This will lead to a 64M limit buffer, but that
  727. // should be good enough for now.
  728. cbBufferLength &= 0xffffff;
  729. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  730. StubMsg.StubDesc = &_StubDesc;
  731. StubMsg.pfnFree = NdrOleFree;
  732. StubMsg.pfnAllocate = NdrOleAllocate;
  733. StubMsg.IsClient = 1;
  734. StubMsg.dwDestContext = dwFlags & 0x0000FFFF;
  735. StubMsg.Buffer = pBuffer;
  736. StubMsg.BufferStart = pBuffer;
  737. StubMsg.BufferLength = cbBufferLength;
  738. StubMsg.BufferEnd = pBuffer + cbBufferLength;
  739. MIDL_memset(&RpcMsg, 0, sizeof(RpcMsg));
  740. RpcMsg.DataRepresentation = dwFlags >> 16;
  741. RpcMsg.Buffer = pBuffer;
  742. RpcMsg.BufferLength = cbBufferLength;
  743. StubMsg.RpcMsg = &RpcMsg;
  744. NdrClientZeroOut(&StubMsg,
  745. pTypeFormat,
  746. (uchar *) pType);
  747. //Endianness
  748. if(RpcMsg.DataRepresentation != NDR_LOCAL_DATA_REPRESENTATION)
  749. {
  750. (*pfnConvertRoutines[ROUTINE_INDEX(*pTypeFormat)])(&StubMsg,
  751. pTypeFormat,
  752. FALSE);
  753. StubMsg.Buffer = pBuffer;
  754. }
  755. //Unmarshal
  756. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  757. &StubMsg,
  758. (unsigned char **)&pType,
  759. pTypeFormat,
  760. FALSE);
  761. if(pcbRead)
  762. *pcbRead = (ULONG)(StubMsg.Buffer - pBuffer);
  763. }
  764. __except(EXCEPTION_EXECUTE_HANDLER)
  765. {
  766. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  767. }
  768. return hr;
  769. }
  770. //+---------------------------------------------------------------------------
  771. //
  772. // Method: CTypeMarshal::Free
  773. //
  774. // Synopsis: Frees a user-defined type.
  775. //
  776. // Returns: S_OK
  777. // E_INVALIDARG
  778. //
  779. //----------------------------------------------------------------------------
  780. HRESULT STDMETHODCALLTYPE
  781. CTypeMarshal::Free(
  782. void * pType)
  783. {
  784. HRESULT hr = S_OK;
  785. MIDL_STUB_MESSAGE StubMsg;
  786. PFORMAT_STRING pTypeFormat;
  787. __try
  788. {
  789. if(pType != NULL)
  790. {
  791. if(!_pFormatString)
  792. return E_UNEXPECTED;
  793. pTypeFormat = _pFormatString + _offset;
  794. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  795. StubMsg.StubDesc = &_StubDesc;
  796. StubMsg.pfnFree = NdrOleFree;
  797. StubMsg.pfnAllocate = NdrOleAllocate;
  798. StubMsg.IsClient = 1;
  799. (*pfnFreeRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  800. &StubMsg,
  801. (unsigned char *)pType,
  802. pTypeFormat);
  803. }
  804. }
  805. __except(EXCEPTION_EXECUTE_HANDLER)
  806. {
  807. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  808. }
  809. return hr;
  810. }
  811. //+---------------------------------------------------------------------------
  812. //
  813. // Method: CTypeMarshal::GetUnmarshalClass
  814. //
  815. // Synopsis: Get the class ID.
  816. //
  817. //----------------------------------------------------------------------------
  818. STDMETHODIMP CTypeMarshal::GetUnmarshalClass(
  819. REFIID riid,
  820. LPVOID pv,
  821. DWORD dwDestContext,
  822. LPVOID pvDestContext,
  823. DWORD mshlflags,
  824. CLSID * pClassID)
  825. {
  826. HRESULT hr = S_OK;
  827. __try
  828. {
  829. *pClassID = CLSID_TypeFactory;
  830. }
  831. __except(EXCEPTION_EXECUTE_HANDLER)
  832. {
  833. hr = E_INVALIDARG;
  834. }
  835. return hr;
  836. }
  837. //+---------------------------------------------------------------------------
  838. //
  839. // Method: CTypeMarshal::GetMarshalSizeMax
  840. //
  841. // Synopsis: Get maximum size of marshalled moniker.
  842. //
  843. //----------------------------------------------------------------------------
  844. STDMETHODIMP CTypeMarshal::GetMarshalSizeMax(
  845. REFIID riid,
  846. LPVOID pv,
  847. DWORD dwDestContext,
  848. LPVOID pvDestContext,
  849. DWORD mshlflags,
  850. DWORD *pSize)
  851. {
  852. HRESULT hr;
  853. __try
  854. {
  855. *pSize = sizeof(_offset) + sizeof(_length) + _length;
  856. hr = S_OK;
  857. }
  858. __except(EXCEPTION_EXECUTE_HANDLER)
  859. {
  860. hr = E_INVALIDARG;
  861. }
  862. return hr;
  863. }
  864. //+---------------------------------------------------------------------------
  865. //
  866. // Method: CTypeMarshal::MarshalInterface
  867. //
  868. // Synopsis: Marshal moniker into a stream.
  869. //
  870. //----------------------------------------------------------------------------
  871. STDMETHODIMP CTypeMarshal::MarshalInterface(
  872. IStream * pStream,
  873. REFIID riid,
  874. void * pv,
  875. DWORD dwDestContext,
  876. LPVOID pvDestContext,
  877. DWORD mshlflags)
  878. {
  879. HRESULT hr;
  880. ULONG cb;
  881. hr = pStream->Write(&_offset, sizeof(_offset), &cb);
  882. if(SUCCEEDED(hr))
  883. {
  884. hr = pStream->Write(&_length, sizeof(_length), &cb);
  885. if(SUCCEEDED(hr))
  886. {
  887. hr = pStream->Write(_pFormatString, _length, &cb);
  888. }
  889. }
  890. return hr;
  891. }
  892. //+---------------------------------------------------------------------------
  893. //
  894. // Method: CTypeMarshal::UnmarshalInterface
  895. //
  896. // Synopsis: Unmarshal moniker from a stream.
  897. //
  898. //----------------------------------------------------------------------------
  899. STDMETHODIMP CTypeMarshal::UnmarshalInterface(
  900. IStream * pStream,
  901. REFIID riid,
  902. void ** ppv)
  903. {
  904. HRESULT hr;
  905. ULONG cb;
  906. __try
  907. {
  908. //Validate parameters.
  909. *ppv = NULL;
  910. hr = pStream->Read(&_offset, sizeof(_offset), &cb);
  911. if(SUCCEEDED(hr) &&
  912. (sizeof(_offset) == cb))
  913. {
  914. hr = pStream->Read(&_length, sizeof(_length), &cb);
  915. if(SUCCEEDED(hr) &&
  916. (sizeof(_length) == cb))
  917. {
  918. _pFormatString = (PFORMAT_STRING) I_RpcAllocate(_length);
  919. if(_pFormatString != NULL)
  920. {
  921. hr = pStream->Read((void *) _pFormatString, _length, &_length);
  922. if(SUCCEEDED(hr))
  923. {
  924. hr = QueryInterface(riid, ppv);
  925. }
  926. }
  927. else
  928. {
  929. hr = E_OUTOFMEMORY;
  930. }
  931. }
  932. }
  933. }
  934. __except(EXCEPTION_EXECUTE_HANDLER)
  935. {
  936. hr = E_INVALIDARG;
  937. }
  938. return hr;
  939. }
  940. //+---------------------------------------------------------------------------
  941. //
  942. // Method: CTypeMarshal::ReleaseMarshalData
  943. //
  944. // Synopsis: Release a marshalled class moniker.
  945. // Just seek to the end of the marshalled class moniker.
  946. //
  947. //----------------------------------------------------------------------------
  948. STDMETHODIMP CTypeMarshal::ReleaseMarshalData(
  949. IStream * pStream)
  950. {
  951. HRESULT hr;
  952. ULONG cb;
  953. hr = pStream->Read(&_offset, sizeof(_offset), &cb);
  954. if(SUCCEEDED(hr) &&
  955. (sizeof(_offset) == cb))
  956. {
  957. hr = pStream->Read(&_length, sizeof(_length), &cb);
  958. if(SUCCEEDED(hr) &&
  959. (sizeof(_length) == cb))
  960. {
  961. LARGE_INTEGER liSize;
  962. liSize.LowPart = _length;
  963. liSize.HighPart = 0;
  964. hr = pStream->Seek(liSize, STREAM_SEEK_CUR, NULL);
  965. }
  966. }
  967. return hr;
  968. }
  969. //+---------------------------------------------------------------------------
  970. //
  971. // Method: CTypeMarshal::DisconnectObject
  972. //
  973. // Synopsis: Disconnect the object.
  974. //
  975. //----------------------------------------------------------------------------
  976. STDMETHODIMP CTypeMarshal::DisconnectObject(
  977. DWORD dwReserved)
  978. {
  979. return S_OK;
  980. }