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.

1122 lines
28 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. MemoryInfo StructInfo;
  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. memset( &StructInfo, 0, sizeof( MemoryInfo ) );
  401. hr = ptypeGen->RegisterType(&paramInfo,
  402. &offset,
  403. &StructInfo);
  404. if (SUCCEEDED(hr) && (0 == offset))
  405. {
  406. ASSERT( !(paramInfo.vt & VT_BYREF));
  407. switch (paramInfo.vt)
  408. {
  409. case VT_I1:
  410. case VT_UI1:
  411. offset = 734;
  412. break;
  413. case VT_I2:
  414. case VT_UI2:
  415. case VT_BOOL:
  416. offset = 738;
  417. break;
  418. case VT_I4:
  419. case VT_UI4:
  420. case VT_INT:
  421. case VT_UINT:
  422. case VT_ERROR:
  423. case VT_HRESULT:
  424. offset = 742;
  425. break;
  426. case VT_I8:
  427. case VT_UI8:
  428. case VT_CY:
  429. offset = 310;
  430. break;
  431. case VT_R4:
  432. offset = 746;
  433. break;
  434. case VT_R8:
  435. case VT_DATE:
  436. offset = 750;
  437. break;
  438. }
  439. }
  440. if(SUCCEEDED(hr))
  441. {
  442. hr = ptypeGen->GetTypeFormatString(&pFormatString, &length);
  443. if(SUCCEEDED(hr))
  444. {
  445. pTypeMarshal = new CTypeMarshal(pFormatString, length, offset);
  446. if(pTypeMarshal != NULL)
  447. {
  448. hr = pTypeMarshal->QueryInterface(riid, (void **) ppv);
  449. pTypeMarshal->Release();
  450. }
  451. else
  452. {
  453. hr = E_OUTOFMEMORY;
  454. ReleaseTypeFormatString(pFormatString);
  455. }
  456. }
  457. }
  458. delete ptypeGen; // fix compile warning
  459. }
  460. __except(EXCEPTION_EXECUTE_HANDLER)
  461. {
  462. delete ptypeGen; // fix compile warning
  463. hr = E_INVALIDARG;
  464. }
  465. return hr;
  466. }
  467. //+---------------------------------------------------------------------------
  468. //
  469. // Method: CTypeMarshal::CTypeMarshal
  470. //
  471. // Synopsis: Constructor for CTypeMarshal
  472. //
  473. //----------------------------------------------------------------------------
  474. CTypeMarshal::CTypeMarshal(
  475. IN PFORMAT_STRING pFormatString,
  476. IN ULONG length,
  477. IN ULONG offset)
  478. : _pFormatString(pFormatString), _length(length), _offset(offset), _cRefs(1)
  479. {
  480. //Initialize the MIDL_STUB_DESC.
  481. MIDL_memset(&_StubDesc, 0, sizeof(_StubDesc));
  482. _StubDesc.pfnAllocate = NdrOleAllocate;
  483. _StubDesc.pfnFree = NdrOleFree;
  484. _StubDesc.pFormatTypes = pFormatString;
  485. #if !defined(__RPC_WIN64__)
  486. _StubDesc.Version = 0x20000; /* Ndr library version */
  487. _StubDesc.MIDLVersion = MIDL_VERSION_3_0_44;
  488. #else
  489. _StubDesc.Version = 0x50002; /* Ndr library version */
  490. _StubDesc.MIDLVersion = MIDL_VERSION_5_2_202;
  491. #endif
  492. _StubDesc.aUserMarshalQuadruple = UserMarshalRoutines;
  493. }
  494. //+---------------------------------------------------------------------------
  495. //
  496. // Method: CTypeMarshal::~CTypeMarshal
  497. //
  498. // Synopsis: Destructor for CTypeMarshal
  499. //
  500. //----------------------------------------------------------------------------
  501. CTypeMarshal::~CTypeMarshal()
  502. {
  503. ReleaseTypeFormatString(_pFormatString);
  504. }
  505. //+---------------------------------------------------------------------------
  506. //
  507. // Method: CTypeMarshal::QueryInterface
  508. //
  509. // Synopsis: Gets a pointer to the specified interface.
  510. //
  511. // Arguments: riid - IID of the requested interface.
  512. // ppv - Returns the interface pointer.
  513. //
  514. // Returns: S_OK
  515. // E_INVALIDARG
  516. // E_NOINTERFACE
  517. //
  518. //----------------------------------------------------------------------------
  519. HRESULT STDMETHODCALLTYPE
  520. CTypeMarshal::QueryInterface(
  521. REFIID riid,
  522. void **ppv)
  523. {
  524. HRESULT hr;
  525. __try
  526. {
  527. *ppv = NULL;
  528. if(IsEqualIID(riid, IID_IUnknown) ||
  529. IsEqualIID(riid, IID_ITypeMarshal))
  530. {
  531. AddRef();
  532. *ppv = (ITypeMarshal *) this;
  533. hr = S_OK;
  534. }
  535. else if (IsEqualIID(riid, IID_IMarshal))
  536. {
  537. AddRef();
  538. *ppv = (IMarshal *) this;
  539. hr = S_OK;
  540. }
  541. else
  542. {
  543. hr = E_NOINTERFACE;
  544. }
  545. }
  546. __except(EXCEPTION_EXECUTE_HANDLER)
  547. {
  548. hr = E_INVALIDARG;
  549. }
  550. return hr;
  551. }
  552. //+---------------------------------------------------------------------------
  553. //
  554. // Method: CTypeMarshal::AddRef
  555. //
  556. // Synopsis: Increment the reference count.
  557. //
  558. // Arguments: void
  559. //
  560. // Returns: ULONG -- the new reference count
  561. //
  562. // Notes: Use InterlockedIncrement to make it multi-thread safe.
  563. //
  564. //----------------------------------------------------------------------------
  565. ULONG STDMETHODCALLTYPE
  566. CTypeMarshal::AddRef(void)
  567. {
  568. InterlockedIncrement(&_cRefs);
  569. return _cRefs;
  570. }
  571. //+---------------------------------------------------------------------------
  572. //
  573. // Method: CTypeMarshal::Release
  574. //
  575. // Synopsis: Decrement the reference count.
  576. //
  577. // Arguments: void
  578. //
  579. // Returns: ULONG -- the remaining reference count
  580. //
  581. // Notes: Use InterlockedDecrement to make it multi-thread safe.
  582. // We use a local variable so that we don't access
  583. // a data member after decrementing the reference count.
  584. //
  585. //----------------------------------------------------------------------------
  586. ULONG STDMETHODCALLTYPE
  587. CTypeMarshal::Release(void)
  588. {
  589. ULONG count = _cRefs - 1;
  590. if(0 == InterlockedDecrement(&_cRefs))
  591. {
  592. delete this;
  593. count = 0;
  594. }
  595. return count;
  596. }
  597. //+---------------------------------------------------------------------------
  598. //
  599. // Method: CTypeMarshal::Size
  600. //
  601. // Synopsis: Computes the size of the marshalled data type.
  602. //
  603. // Returns: S_OK
  604. // E_INVALIDARG
  605. //
  606. //----------------------------------------------------------------------------
  607. HRESULT STDMETHODCALLTYPE
  608. CTypeMarshal::Size(
  609. IN void * pType,
  610. IN DWORD dwDestContext,
  611. IN void * pvDestContext,
  612. OUT ULONG * pSize)
  613. {
  614. HRESULT hr = S_OK;
  615. MIDL_STUB_MESSAGE StubMsg;
  616. PFORMAT_STRING pTypeFormat;
  617. __try
  618. {
  619. if(!_pFormatString)
  620. return E_UNEXPECTED;
  621. pTypeFormat = _pFormatString + _offset;
  622. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  623. StubMsg.StubDesc = &_StubDesc;
  624. StubMsg.pfnFree = NdrOleFree;
  625. StubMsg.pfnAllocate = NdrOleAllocate;
  626. StubMsg.IsClient = 1;
  627. StubMsg.BufferLength = 1; //Reserve space for an alignment gap.
  628. StubMsg.dwDestContext = dwDestContext;
  629. StubMsg.pvDestContext = pvDestContext;
  630. (*pfnSizeRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  631. &StubMsg,
  632. (unsigned char *)pType,
  633. pTypeFormat);
  634. *pSize = StubMsg.BufferLength - 1;
  635. }
  636. __except(EXCEPTION_EXECUTE_HANDLER)
  637. {
  638. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  639. }
  640. return hr;
  641. }
  642. //+---------------------------------------------------------------------------
  643. //
  644. // Method: CTypeMarshal::Marshal
  645. //
  646. // Synopsis: Marshals the user-defined type into a buffer.
  647. //
  648. // Returns: S_OK
  649. // E_INVALIDARG
  650. //
  651. //----------------------------------------------------------------------------
  652. HRESULT STDMETHODCALLTYPE
  653. CTypeMarshal::Marshal(
  654. IN void * pType,
  655. IN DWORD dwDestContext,
  656. IN void * pvDestContext,
  657. IN ULONG cbBufferLength,
  658. OUT BYTE * pBuffer,
  659. OUT ULONG * pcbWritten)
  660. {
  661. HRESULT hr = S_OK;
  662. MIDL_STUB_MESSAGE StubMsg;
  663. RPC_MESSAGE RpcMsg;
  664. PFORMAT_STRING pTypeFormat;
  665. __try
  666. {
  667. if(!_pFormatString)
  668. return E_UNEXPECTED;
  669. pTypeFormat = _pFormatString + _offset;
  670. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  671. StubMsg.StubDesc = &_StubDesc;
  672. StubMsg.pfnFree = NdrOleFree;
  673. StubMsg.pfnAllocate = NdrOleAllocate;
  674. StubMsg.IsClient = 1;
  675. StubMsg.dwDestContext = dwDestContext;
  676. StubMsg.pvDestContext = pvDestContext;
  677. StubMsg.Buffer = pBuffer;
  678. MIDL_memset(&RpcMsg, 0, sizeof(RpcMsg));
  679. RpcMsg.DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
  680. RpcMsg.Buffer = pBuffer;
  681. RpcMsg.BufferLength = cbBufferLength;
  682. StubMsg.RpcMsg = &RpcMsg;
  683. (*pfnMarshallRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  684. &StubMsg,
  685. (unsigned char *)pType,
  686. pTypeFormat);
  687. *pcbWritten = (ULONG)(StubMsg.Buffer - pBuffer);
  688. }
  689. __except(EXCEPTION_EXECUTE_HANDLER)
  690. {
  691. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  692. }
  693. return hr;
  694. }
  695. //+---------------------------------------------------------------------------
  696. //
  697. // Method: CTypeMarshal::Unmarshal
  698. //
  699. // Synopsis: Unmarshals a user-defined type from a buffer.
  700. //
  701. // Returns: S_OK
  702. // E_INVALIDARG
  703. //
  704. //----------------------------------------------------------------------------
  705. HRESULT STDMETHODCALLTYPE
  706. CTypeMarshal::Unmarshal(
  707. OUT void * pType,
  708. IN DWORD dwFlags,
  709. IN ULONG cbBufferLength,
  710. IN BYTE * pBuffer,
  711. OUT ULONG * pcbRead)
  712. {
  713. HRESULT hr = S_OK;
  714. MIDL_STUB_MESSAGE StubMsg;
  715. RPC_MESSAGE RpcMsg;
  716. PFORMAT_STRING pTypeFormat;
  717. __try
  718. {
  719. if(pcbRead)
  720. *pcbRead = 0;
  721. if(!_pFormatString)
  722. return E_UNEXPECTED;
  723. pTypeFormat = _pFormatString + _offset;
  724. // HACK! OA might pass in 0xffffffff, which
  725. // will break the attack checking in ndr engine.
  726. // what we do now is mask off the highest byte.
  727. // This will lead to a 64M limit buffer, but that
  728. // should be good enough for now.
  729. cbBufferLength &= 0xffffff;
  730. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  731. StubMsg.StubDesc = &_StubDesc;
  732. StubMsg.pfnFree = NdrOleFree;
  733. StubMsg.pfnAllocate = NdrOleAllocate;
  734. StubMsg.IsClient = 1;
  735. StubMsg.dwDestContext = dwFlags & 0x0000FFFF;
  736. StubMsg.Buffer = pBuffer;
  737. StubMsg.BufferStart = pBuffer;
  738. StubMsg.BufferLength = cbBufferLength;
  739. StubMsg.BufferEnd = pBuffer + cbBufferLength;
  740. MIDL_memset(&RpcMsg, 0, sizeof(RpcMsg));
  741. RpcMsg.DataRepresentation = dwFlags >> 16;
  742. RpcMsg.Buffer = pBuffer;
  743. RpcMsg.BufferLength = cbBufferLength;
  744. StubMsg.RpcMsg = &RpcMsg;
  745. NdrClientZeroOut(&StubMsg,
  746. pTypeFormat,
  747. (uchar *) pType);
  748. //Endianness
  749. if(RpcMsg.DataRepresentation != NDR_LOCAL_DATA_REPRESENTATION)
  750. {
  751. (*pfnConvertRoutines[ROUTINE_INDEX(*pTypeFormat)])(&StubMsg,
  752. pTypeFormat,
  753. FALSE);
  754. StubMsg.Buffer = pBuffer;
  755. }
  756. //Unmarshal
  757. (*pfnUnmarshallRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  758. &StubMsg,
  759. (unsigned char **)&pType,
  760. pTypeFormat,
  761. FALSE);
  762. if(pcbRead)
  763. *pcbRead = (ULONG)(StubMsg.Buffer - pBuffer);
  764. }
  765. __except(EXCEPTION_EXECUTE_HANDLER)
  766. {
  767. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  768. }
  769. return hr;
  770. }
  771. //+---------------------------------------------------------------------------
  772. //
  773. // Method: CTypeMarshal::Free
  774. //
  775. // Synopsis: Frees a user-defined type.
  776. //
  777. // Returns: S_OK
  778. // E_INVALIDARG
  779. //
  780. //----------------------------------------------------------------------------
  781. HRESULT STDMETHODCALLTYPE
  782. CTypeMarshal::Free(
  783. void * pType)
  784. {
  785. HRESULT hr = S_OK;
  786. MIDL_STUB_MESSAGE StubMsg;
  787. PFORMAT_STRING pTypeFormat;
  788. __try
  789. {
  790. if(pType != NULL)
  791. {
  792. if(!_pFormatString)
  793. return E_UNEXPECTED;
  794. pTypeFormat = _pFormatString + _offset;
  795. MIDL_memset(&StubMsg, 0, sizeof(StubMsg));
  796. StubMsg.StubDesc = &_StubDesc;
  797. StubMsg.pfnFree = NdrOleFree;
  798. StubMsg.pfnAllocate = NdrOleAllocate;
  799. StubMsg.IsClient = 1;
  800. (*pfnFreeRoutines[ROUTINE_INDEX(*pTypeFormat)])(
  801. &StubMsg,
  802. (unsigned char *)pType,
  803. pTypeFormat);
  804. }
  805. }
  806. __except(EXCEPTION_EXECUTE_HANDLER)
  807. {
  808. hr = HRESULT_FROM_WIN32(GetExceptionCode());
  809. }
  810. return hr;
  811. }
  812. //+---------------------------------------------------------------------------
  813. //
  814. // Method: CTypeMarshal::GetUnmarshalClass
  815. //
  816. // Synopsis: Get the class ID.
  817. //
  818. //----------------------------------------------------------------------------
  819. STDMETHODIMP CTypeMarshal::GetUnmarshalClass(
  820. REFIID riid,
  821. LPVOID pv,
  822. DWORD dwDestContext,
  823. LPVOID pvDestContext,
  824. DWORD mshlflags,
  825. CLSID * pClassID)
  826. {
  827. HRESULT hr = S_OK;
  828. __try
  829. {
  830. *pClassID = CLSID_TypeFactory;
  831. }
  832. __except(EXCEPTION_EXECUTE_HANDLER)
  833. {
  834. hr = E_INVALIDARG;
  835. }
  836. return hr;
  837. }
  838. //+---------------------------------------------------------------------------
  839. //
  840. // Method: CTypeMarshal::GetMarshalSizeMax
  841. //
  842. // Synopsis: Get maximum size of marshalled moniker.
  843. //
  844. //----------------------------------------------------------------------------
  845. STDMETHODIMP CTypeMarshal::GetMarshalSizeMax(
  846. REFIID riid,
  847. LPVOID pv,
  848. DWORD dwDestContext,
  849. LPVOID pvDestContext,
  850. DWORD mshlflags,
  851. DWORD *pSize)
  852. {
  853. HRESULT hr;
  854. __try
  855. {
  856. *pSize = sizeof(_offset) + sizeof(_length) + _length;
  857. hr = S_OK;
  858. }
  859. __except(EXCEPTION_EXECUTE_HANDLER)
  860. {
  861. hr = E_INVALIDARG;
  862. }
  863. return hr;
  864. }
  865. //+---------------------------------------------------------------------------
  866. //
  867. // Method: CTypeMarshal::MarshalInterface
  868. //
  869. // Synopsis: Marshal moniker into a stream.
  870. //
  871. //----------------------------------------------------------------------------
  872. STDMETHODIMP CTypeMarshal::MarshalInterface(
  873. IStream * pStream,
  874. REFIID riid,
  875. void * pv,
  876. DWORD dwDestContext,
  877. LPVOID pvDestContext,
  878. DWORD mshlflags)
  879. {
  880. HRESULT hr;
  881. ULONG cb;
  882. hr = pStream->Write(&_offset, sizeof(_offset), &cb);
  883. if(SUCCEEDED(hr))
  884. {
  885. hr = pStream->Write(&_length, sizeof(_length), &cb);
  886. if(SUCCEEDED(hr))
  887. {
  888. hr = pStream->Write(_pFormatString, _length, &cb);
  889. }
  890. }
  891. return hr;
  892. }
  893. //+---------------------------------------------------------------------------
  894. //
  895. // Method: CTypeMarshal::UnmarshalInterface
  896. //
  897. // Synopsis: Unmarshal moniker from a stream.
  898. //
  899. //----------------------------------------------------------------------------
  900. STDMETHODIMP CTypeMarshal::UnmarshalInterface(
  901. IStream * pStream,
  902. REFIID riid,
  903. void ** ppv)
  904. {
  905. HRESULT hr;
  906. ULONG cb;
  907. __try
  908. {
  909. //Validate parameters.
  910. *ppv = NULL;
  911. hr = pStream->Read(&_offset, sizeof(_offset), &cb);
  912. if(SUCCEEDED(hr) &&
  913. (sizeof(_offset) == cb))
  914. {
  915. hr = pStream->Read(&_length, sizeof(_length), &cb);
  916. if(SUCCEEDED(hr) &&
  917. (sizeof(_length) == cb))
  918. {
  919. _pFormatString = (PFORMAT_STRING) I_RpcAllocate(_length);
  920. if(_pFormatString != NULL)
  921. {
  922. hr = pStream->Read((void *) _pFormatString, _length, &_length);
  923. if(SUCCEEDED(hr))
  924. {
  925. hr = QueryInterface(riid, ppv);
  926. }
  927. }
  928. else
  929. {
  930. hr = E_OUTOFMEMORY;
  931. }
  932. }
  933. }
  934. }
  935. __except(EXCEPTION_EXECUTE_HANDLER)
  936. {
  937. hr = E_INVALIDARG;
  938. }
  939. return hr;
  940. }
  941. //+---------------------------------------------------------------------------
  942. //
  943. // Method: CTypeMarshal::ReleaseMarshalData
  944. //
  945. // Synopsis: Release a marshalled class moniker.
  946. // Just seek to the end of the marshalled class moniker.
  947. //
  948. //----------------------------------------------------------------------------
  949. STDMETHODIMP CTypeMarshal::ReleaseMarshalData(
  950. IStream * pStream)
  951. {
  952. HRESULT hr;
  953. ULONG cb;
  954. hr = pStream->Read(&_offset, sizeof(_offset), &cb);
  955. if(SUCCEEDED(hr) &&
  956. (sizeof(_offset) == cb))
  957. {
  958. hr = pStream->Read(&_length, sizeof(_length), &cb);
  959. if(SUCCEEDED(hr) &&
  960. (sizeof(_length) == cb))
  961. {
  962. LARGE_INTEGER liSize;
  963. liSize.LowPart = _length;
  964. liSize.HighPart = 0;
  965. hr = pStream->Seek(liSize, STREAM_SEEK_CUR, NULL);
  966. }
  967. }
  968. return hr;
  969. }
  970. //+---------------------------------------------------------------------------
  971. //
  972. // Method: CTypeMarshal::DisconnectObject
  973. //
  974. // Synopsis: Disconnect the object.
  975. //
  976. //----------------------------------------------------------------------------
  977. STDMETHODIMP CTypeMarshal::DisconnectObject(
  978. DWORD dwReserved)
  979. {
  980. return S_OK;
  981. }