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.

699 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: hglobal.cxx
  7. //
  8. // Contents: Support for Windows/OLE data types for oleprx32.dll.
  9. // Used to be transmit_as routines, now user_marshal routines.
  10. //
  11. // This file contains support for HGLOBAL.
  12. //
  13. // Functions:
  14. // HGLOBAL_UserSize
  15. // HGLOBAL_UserMarshal
  16. // HGLOBAL_UserUnmarshal
  17. // HGLOBAL_UserFree
  18. // HGLOBAL_UserSize64
  19. // HGLOBAL_UserMarshal64
  20. // HGLOBAL_UserUnmarshal64
  21. // HGLOBAL_UserFree64
  22. //
  23. // History: 13-Dec-00 JohnDoty Migrated from transmit.cxx
  24. //
  25. //--------------------------------------------------------------------------
  26. #include "stdrpc.hxx"
  27. #pragma hdrstop
  28. #include <oleauto.h>
  29. #include <objbase.h>
  30. #include "transmit.hxx"
  31. #include <rpcwdt.h>
  32. #include <storext.h>
  33. #include "widewrap.h"
  34. #include <valid.h>
  35. #include <obase.h>
  36. #include <stream.hxx>
  37. #include "carefulreader.hxx"
  38. //+-------------------------------------------------------------------------
  39. //
  40. // Function: HGLOBAL_UserSize
  41. //
  42. // Synopsis: Get the wire size the HGLOBAL handle and data.
  43. //
  44. // Derivation: Conformant struct with a flag field:
  45. // align + 12 + data size.
  46. //
  47. // history: May-95 Ryszardk Created.
  48. // Dec-98 Ryszardk Ported to 64b.
  49. //
  50. //--------------------------------------------------------------------------
  51. unsigned long __RPC_USER
  52. HGLOBAL_UserSize (
  53. unsigned long * pFlags,
  54. unsigned long Offset,
  55. HGLOBAL * pGlobal)
  56. {
  57. if ( !pGlobal )
  58. return Offset;
  59. // userHGLOBAL: the encapsulated union.
  60. // Discriminant and then handle or pointer from the union arm.
  61. LENGTH_ALIGN( Offset, 3 );
  62. // Union discriminent is 4 bytes
  63. Offset += sizeof( long );
  64. // Handle represented by a polymorphic type - for inproc case only!
  65. if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
  66. {
  67. LENGTH_ALIGN( Offset, sizeof( HGLOBAL )-1 );
  68. Offset += sizeof( HGLOBAL );
  69. }
  70. else
  71. Offset += ( sizeof(long) + sizeof(HGLOBAL) );
  72. if ( ! *pGlobal )
  73. return Offset;
  74. if ( HGLOBAL_DATA_PASSING(*pFlags) )
  75. {
  76. unsigned long ulDataSize = (ULONG) GlobalSize( *pGlobal );
  77. Offset += 3 * sizeof(long) + ulDataSize;
  78. }
  79. return( Offset );
  80. }
  81. //+-------------------------------------------------------------------------
  82. //
  83. // Function: HGLOBAL_UserMarshall
  84. //
  85. // Synopsis: Marshalls an HGLOBAL object into the RPC buffer.
  86. //
  87. // Derivation: Conformant struct with a flag field:
  88. // align, size, null flag, size, data (bytes, if any)
  89. //
  90. // history: May-95 Ryszardk Created.
  91. // Dec-98 Ryszardk Ported to 64b.
  92. //
  93. //--------------------------------------------------------------------------
  94. unsigned char __RPC_FAR * __RPC_USER
  95. HGLOBAL_UserMarshal (
  96. unsigned long * pFlags,
  97. unsigned char * pBuffer,
  98. HGLOBAL * pGlobal)
  99. {
  100. if ( !pGlobal )
  101. return pBuffer;
  102. // We marshal a null handle, too.
  103. UserNdrDebugOut((UNDR_OUT4, "HGLOBAL_UserMarshal\n"));
  104. ALIGN( pBuffer, 3 );
  105. // Discriminant of the encapsulated union and union arm.
  106. if ( HGLOBAL_DATA_PASSING(*pFlags) )
  107. {
  108. unsigned long ulDataSize;
  109. // userHGLOBAL
  110. *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
  111. *( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
  112. if ( ! *pGlobal )
  113. return pBuffer;
  114. // FLAGGED_BYTE_BLOB
  115. ulDataSize = (ULONG) GlobalSize( *pGlobal );
  116. *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
  117. // Handle is the non-null flag
  118. *( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
  119. *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
  120. if( ulDataSize )
  121. {
  122. void * pData = GlobalLock( *pGlobal);
  123. memcpy( pBuffer, pData, ulDataSize );
  124. GlobalUnlock( *pGlobal);
  125. }
  126. pBuffer += ulDataSize;
  127. }
  128. else
  129. {
  130. // Sending a handle.
  131. // For WIN64 HGLOBALs, 64 bits may by significant (e.i. GPTR).
  132. #if defined(_WIN64)
  133. *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER;
  134. ALIGN( pBuffer, 7 );
  135. *( PHYPER_LV_CAST pBuffer)++ = *(__int64 *)pGlobal;
  136. #else
  137. *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
  138. *( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
  139. #endif
  140. }
  141. return( pBuffer );
  142. }
  143. //+-------------------------------------------------------------------------
  144. //
  145. // Function: WdtpGlobalUnmarshal
  146. //
  147. // Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
  148. //
  149. // Derivation: Conformant struct with a flag field:
  150. // align, size, null flag, size, data (bytes, if any)
  151. //
  152. // Note: Reallocation is forbidden when the hglobal is part of
  153. // an [in,out] STGMEDIUM in IDataObject::GetDataHere.
  154. // This affects only data passing with old handles being
  155. // non null.
  156. //
  157. // history: May-95 Ryszardk Created.
  158. //
  159. //--------------------------------------------------------------------------
  160. unsigned char __RPC_FAR * __RPC_USER
  161. WdtpGlobalUnmarshal (
  162. unsigned long * pFlags,
  163. unsigned char * pBuffer,
  164. HGLOBAL * pGlobal,
  165. BOOL fCanReallocate,
  166. ULONG_PTR BufferSize )
  167. {
  168. unsigned long ulDataSize, fHandle, UnionDisc;
  169. HGLOBAL hGlobal;
  170. // Align the buffer and save the fixup size.
  171. UCHAR* pBufferStart = pBuffer;
  172. ALIGN( pBuffer, 3 );
  173. ULONG_PTR cbFixup = (ULONG_PTR)(pBuffer - pBufferStart);
  174. // Check for EOB before accessing discriminant and handle.
  175. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (2 * sizeof( ULONG )) );
  176. // Get the tag from buffer.
  177. UnionDisc = *( PULONG_LV_CAST pBuffer)++;
  178. if ( IS_DATA_MARKER( UnionDisc) )
  179. {
  180. // Get the marker from the buffer.
  181. hGlobal = (HGLOBAL) LongToHandle( *( PLONG_LV_CAST pBuffer)++ );
  182. // If handle is NULL, we are done.
  183. if ( ! hGlobal )
  184. {
  185. if ( *pGlobal )
  186. GlobalFree( *pGlobal );
  187. *pGlobal = NULL;
  188. return pBuffer;
  189. }
  190. // Check for EOB before accessing header.
  191. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (5 * sizeof( ULONG )) );
  192. // Get the rest of the header from the buffer.
  193. ulDataSize = *( PULONG_LV_CAST pBuffer)++;
  194. HGLOBAL hGlobalDup = (HGLOBAL) LongToHandle( *( PLONG_LV_CAST pBuffer)++ );
  195. ULONG ulDataSizeDup = *( PULONG_LV_CAST pBuffer)++;
  196. // Validate the header: handle and size are put on wire twice, make
  197. // sure both instances of each are the same.
  198. if ( (hGlobalDup != hGlobal) ||
  199. (ulDataSizeDup != ulDataSize) )
  200. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  201. if ( *pGlobal )
  202. {
  203. // Check for reallocation
  204. if ( GlobalSize( *pGlobal ) == ulDataSize )
  205. hGlobal = *pGlobal;
  206. else
  207. {
  208. if ( fCanReallocate )
  209. {
  210. GlobalFree( *pGlobal );
  211. hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
  212. }
  213. else
  214. {
  215. if ( GlobalSize(*pGlobal) < ulDataSize )
  216. {
  217. RAISE_RPC_EXCEPTION( STG_E_MEDIUMFULL );
  218. }
  219. else
  220. hGlobal = *pGlobal;
  221. }
  222. }
  223. }
  224. else
  225. {
  226. // allocate a new block
  227. hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
  228. }
  229. if ( hGlobal == NULL )
  230. {
  231. RAISE_RPC_EXCEPTION(E_OUTOFMEMORY);
  232. }
  233. else
  234. {
  235. // Check for EOB before accessing data.
  236. CHECK_BUFFER_SIZE( BufferSize,
  237. cbFixup + (5 * sizeof( ULONG )) + ulDataSize );
  238. // Get the data from the buffer.
  239. void * pData = GlobalLock( hGlobal);
  240. memcpy( pData, pBuffer, ulDataSize );
  241. pBuffer += ulDataSize;
  242. GlobalUnlock( hGlobal);
  243. }
  244. }
  245. else
  246. {
  247. // Sending a handle only.
  248. // Reallocation problem doesn't apply to handle passing.
  249. if ( IS_HANDLE_MARKER( UnionDisc ) )
  250. {
  251. hGlobal = (HGLOBAL) LongToHandle( *( PLONG_LV_CAST pBuffer)++ );
  252. }
  253. else if (IS_HANDLE64_MARKER( UnionDisc ) )
  254. {
  255. ALIGN( pBuffer, 7 );
  256. // Must be enough buffer to do alignment fixup.
  257. CHECK_BUFFER_SIZE( BufferSize, cbFixup +
  258. (ULONG_PTR) (pBuffer - pBufferStart) + sizeof( __int64 ));
  259. hGlobal = (HGLOBAL) ( *( PHYPER_LV_CAST pBuffer)++ );
  260. }
  261. else
  262. {
  263. RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
  264. }
  265. if ( *pGlobal != hGlobal && *pGlobal )
  266. GlobalFree( *pGlobal );
  267. }
  268. *pGlobal = hGlobal;
  269. return( pBuffer );
  270. }
  271. //+-------------------------------------------------------------------------
  272. //
  273. // Function: HGLOBAL_UserUnmarshall
  274. //
  275. // Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
  276. //
  277. // Derivation: Conformant struct with a flag field:
  278. // align, size, null flag, size, data (bytes, if any)
  279. //
  280. // history: May-95 Ryszardk Created.
  281. //
  282. //--------------------------------------------------------------------------
  283. unsigned char __RPC_FAR * __RPC_USER
  284. HGLOBAL_UserUnmarshal (
  285. unsigned long * pFlags,
  286. unsigned char * pBuffer,
  287. HGLOBAL * pGlobal)
  288. {
  289. // Get the buffer size and the start of the buffer.
  290. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  291. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  292. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  293. pBuffer = WdtpGlobalUnmarshal( pFlags,
  294. pBufferStart,
  295. pGlobal,
  296. TRUE, // reallocation possible
  297. BufferSize );
  298. return( pBuffer );
  299. }
  300. //+-------------------------------------------------------------------------
  301. //
  302. // Function: HGLOBAL_UserFree
  303. //
  304. // Synopsis: Free an HGLOBAL.
  305. //
  306. // history: May-95 Ryszardk Created.
  307. //
  308. //--------------------------------------------------------------------------
  309. void __RPC_USER
  310. HGLOBAL_UserFree(
  311. unsigned long * pFlags,
  312. HGLOBAL * pGlobal)
  313. {
  314. if( pGlobal && *pGlobal )
  315. {
  316. if ( HGLOBAL_DATA_PASSING(*pFlags) )
  317. GlobalFree( *pGlobal);
  318. }
  319. }
  320. #if defined(_WIN64)
  321. //+-------------------------------------------------------------------------
  322. //
  323. // Function: HGLOBAL_UserSize64
  324. //
  325. // Synopsis: Get the wire size the HGLOBAL handle and data.
  326. //
  327. // Derivation: Union around a pointer to a conformant struct with a
  328. // flag field.
  329. //
  330. // history: Dec-00 JohnDoty Created from 32bit function
  331. //
  332. //--------------------------------------------------------------------------
  333. unsigned long __RPC_USER
  334. HGLOBAL_UserSize64 (
  335. unsigned long * pFlags,
  336. unsigned long Offset,
  337. HGLOBAL * pGlobal)
  338. {
  339. if ( !pGlobal )
  340. return Offset;
  341. // userHGLOBAL: the encapsulated union.
  342. // Discriminant and then handle or pointer from the union arm.
  343. // Union discriminent is 4 bytes, but it contains a pointer, so
  344. // align on union is 8 bytes.
  345. LENGTH_ALIGN( Offset, 7 );
  346. Offset += sizeof( long );
  347. LENGTH_ALIGN( Offset, 7 );
  348. // Handle represented by a polymorphic type - for inproc case only!
  349. if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
  350. {
  351. // Doesn't matter which arm we take inproc, it's size of native
  352. // HGLOBAL.
  353. Offset += sizeof( HGLOBAL );
  354. }
  355. else
  356. {
  357. // Pointer representation...
  358. Offset += 8;
  359. }
  360. if ( ! *pGlobal )
  361. return Offset;
  362. if ( HGLOBAL_DATA_PASSING(*pFlags) )
  363. {
  364. // Struct must be aligned on 8, but already aligned on
  365. // 8...
  366. unsigned long ulDataSize = (ULONG) GlobalSize( *pGlobal );
  367. Offset += 8 + 2 * sizeof(long) + ulDataSize;
  368. }
  369. return( Offset );
  370. }
  371. //+-------------------------------------------------------------------------
  372. //
  373. // Function: HGLOBAL_UserMarshal64
  374. //
  375. // Synopsis: Marshalls an HGLOBAL object into the RPC buffer.
  376. //
  377. // Derivation: Conformant struct with a flag field:
  378. // align, size, null flag, size, data (bytes, if any)
  379. //
  380. // history: Dec-00 JohnDoty Created from 32bit function
  381. //
  382. //--------------------------------------------------------------------------
  383. unsigned char __RPC_FAR * __RPC_USER
  384. HGLOBAL_UserMarshal64 (
  385. unsigned long * pFlags,
  386. unsigned char * pBuffer,
  387. HGLOBAL * pGlobal)
  388. {
  389. if ( !pGlobal )
  390. return pBuffer;
  391. // We marshal a null handle, too.
  392. UserNdrDebugOut((UNDR_OUT4, "HGLOBAL_UserMarshal\n"));
  393. ALIGN( pBuffer, 7 );
  394. // Discriminant of the encapsulated union and union arm.
  395. if ( HGLOBAL_DATA_PASSING(*pFlags) )
  396. {
  397. unsigned long ulDataSize;
  398. // userHGLOBAL
  399. *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
  400. ALIGN( pBuffer, 7 );
  401. *( PHYPER_LV_CAST pBuffer)++ = (hyper)*pGlobal;
  402. if ( ! *pGlobal )
  403. return pBuffer;
  404. // FLAGGED_BYTE_BLOB
  405. ulDataSize = (ULONG) GlobalSize( *pGlobal );
  406. *( PHYPER_LV_CAST pBuffer)++ = ulDataSize;
  407. // Handle is the non-null flag
  408. *( PLONG_LV_CAST pBuffer)++ = HandleToLong( *pGlobal );
  409. *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
  410. if( ulDataSize )
  411. {
  412. void * pData = GlobalLock( *pGlobal);
  413. memcpy( pBuffer, pData, ulDataSize );
  414. GlobalUnlock( *pGlobal);
  415. }
  416. pBuffer += ulDataSize;
  417. }
  418. else
  419. {
  420. // Sending a handle.
  421. // For WIN64 HGLOBALs, 64 bits may by significant (e.i. GPTR).
  422. *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE64_MARKER;
  423. ALIGN( pBuffer, 7 );
  424. *( PHYPER_LV_CAST pBuffer)++ = *(__int64 *)pGlobal;
  425. }
  426. return( pBuffer );
  427. }
  428. //+-------------------------------------------------------------------------
  429. //
  430. // Function: WdtpGlobalUnmarshal64
  431. //
  432. // Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
  433. //
  434. // Derivation: Conformant struct with a flag field:
  435. // align, size, null flag, size, data (bytes, if any)
  436. //
  437. // Note: Reallocation is forbidden when the hglobal is part of
  438. // an [in,out] STGMEDIUM in IDataObject::GetDataHere.
  439. // This affects only data passing with old handles being
  440. // non null.
  441. //
  442. // history: Dec-00 JohnDoty Created from 32bit function
  443. //
  444. //--------------------------------------------------------------------------
  445. unsigned char __RPC_FAR * __RPC_USER
  446. WdtpGlobalUnmarshal64 (
  447. unsigned long * pFlags,
  448. unsigned char * pBuffer,
  449. HGLOBAL * pGlobal,
  450. BOOL fCanReallocate,
  451. ULONG_PTR BufferSize )
  452. {
  453. CarefulBufferReader stream(pBuffer, BufferSize);
  454. unsigned long ulDataSize, fHandle, UnionDisc;
  455. HGLOBAL hGlobal;
  456. // Align the buffer and save the fixup size.
  457. stream.Align(8);
  458. // Get the tag from buffer.
  459. UnionDisc = stream.ReadULONGNA();
  460. // Get the marker from the buffer.
  461. hGlobal = (HGLOBAL)stream.ReadHYPER();
  462. if ( IS_DATA_MARKER(UnionDisc) )
  463. {
  464. // If the handle was NULL, return out now.
  465. if (!hGlobal)
  466. {
  467. if (*pGlobal)
  468. GlobalFree(*pGlobal);
  469. *pGlobal = NULL;
  470. return stream.GetBuffer();
  471. }
  472. // Get the rest of the header from the buffer.
  473. ulDataSize = (ULONG)stream.ReadHYPERNA();
  474. LONG hGlobalDup = stream.ReadLONGNA();
  475. ULONG ulDataSizeDup = stream.ReadULONGNA();
  476. // Validate the header: handle and size are put on wire twice, make
  477. // sure both instances of each are the same.
  478. if ( (hGlobalDup != HandleToLong(hGlobal)) ||
  479. (ulDataSizeDup != ulDataSize) )
  480. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  481. if ( *pGlobal )
  482. {
  483. // Check for reallocation
  484. if ( GlobalSize( *pGlobal ) == ulDataSize )
  485. hGlobal = *pGlobal;
  486. else
  487. {
  488. if ( fCanReallocate )
  489. {
  490. GlobalFree( *pGlobal );
  491. hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
  492. }
  493. else
  494. {
  495. if ( GlobalSize(*pGlobal) < ulDataSize )
  496. {
  497. RAISE_RPC_EXCEPTION( STG_E_MEDIUMFULL );
  498. }
  499. else
  500. hGlobal = *pGlobal;
  501. }
  502. }
  503. }
  504. else
  505. {
  506. // allocate a new block
  507. hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
  508. }
  509. if ( hGlobal == NULL )
  510. {
  511. RAISE_RPC_EXCEPTION(E_OUTOFMEMORY);
  512. }
  513. else
  514. {
  515. // Check for EOB before accessing data.
  516. stream.CheckSize(ulDataSize);
  517. // Get the data from the buffer.
  518. void * pData = GlobalLock( hGlobal);
  519. memcpy( pData, stream.GetBuffer(), ulDataSize );
  520. GlobalUnlock( hGlobal);
  521. stream.Advance(ulDataSize);
  522. }
  523. }
  524. else if (IS_HANDLE64_MARKER( UnionDisc ))
  525. {
  526. // Make sure the old stuff is cleaned up...
  527. if ( *pGlobal != hGlobal && *pGlobal )
  528. GlobalFree( *pGlobal );
  529. }
  530. else
  531. {
  532. RAISE_RPC_EXCEPTION( RPC_S_INVALID_TAG );
  533. }
  534. *pGlobal = hGlobal;
  535. return( stream.GetBuffer() );
  536. }
  537. //+-------------------------------------------------------------------------
  538. //
  539. // Function: HGLOBAL_UserUnmarshal64
  540. //
  541. // Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
  542. //
  543. // Derivation: Conformant struct with a flag field:
  544. // align, size, null flag, size, data (bytes, if any)
  545. //
  546. // history: Dec-00 JohnDoty Created from 32bit function
  547. //
  548. //--------------------------------------------------------------------------
  549. unsigned char __RPC_FAR * __RPC_USER
  550. HGLOBAL_UserUnmarshal64 (
  551. unsigned long * pFlags,
  552. unsigned char * pBuffer,
  553. HGLOBAL * pGlobal)
  554. {
  555. // Get the buffer size and the start of the buffer.
  556. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  557. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  558. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  559. pBuffer = WdtpGlobalUnmarshal64( pFlags,
  560. pBufferStart,
  561. pGlobal,
  562. TRUE, // reallocation possible
  563. BufferSize );
  564. return( pBuffer );
  565. }
  566. //+-------------------------------------------------------------------------
  567. //
  568. // Function: HGLOBAL_UserFree64
  569. //
  570. // Synopsis: Free an HGLOBAL.
  571. //
  572. // history: Dec-00 JohnDoty Created from 32bit function
  573. //
  574. //--------------------------------------------------------------------------
  575. void __RPC_USER
  576. HGLOBAL_UserFree64 (
  577. unsigned long * pFlags,
  578. HGLOBAL * pGlobal)
  579. {
  580. if( pGlobal && *pGlobal )
  581. {
  582. if ( HGLOBAL_DATA_PASSING(*pFlags) )
  583. GlobalFree( *pGlobal);
  584. }
  585. }
  586. #endif