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.

556 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: clipformat.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 SNB.
  12. //
  13. // Functions:
  14. // SNB_UserSize
  15. // SNB_UserMarshal
  16. // SNB_UserUnmarshal
  17. // SNB_UserFree
  18. // SNB_UserSize64
  19. // SNB_UserMarshal64
  20. // SNB_UserUnmarshal64
  21. // SNB_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: SNB_UserSize
  41. //
  42. // Synopsis: Sizes an SNB.
  43. //
  44. // Derivation: An array of strings in one block of memory.
  45. //
  46. // history: June-95 Ryszardk Created, based on SNB_*_xmit.
  47. //
  48. //--------------------------------------------------------------------------
  49. unsigned long __RPC_USER
  50. SNB_UserSize (
  51. unsigned long * pFlags,
  52. unsigned long Offset,
  53. SNB * pSnb )
  54. {
  55. if ( ! pSnb )
  56. return Offset;
  57. // calculate the number of strings and characters (with their terminators)
  58. ULONG ulCntStr = 0;
  59. ULONG ulCntChar = 0;
  60. if (pSnb && *pSnb)
  61. {
  62. SNB snb = *pSnb;
  63. WCHAR *psz = *snb;
  64. while (psz)
  65. {
  66. ulCntChar += lstrlenW(psz) + 1;
  67. ulCntStr++;
  68. snb++;
  69. psz = *snb;
  70. }
  71. }
  72. // The wire size is: conf size, 2 fields and the wchars.
  73. LENGTH_ALIGN( Offset, 3 );
  74. return ( Offset + 3 * sizeof(long) + ulCntChar * sizeof( WCHAR ) );
  75. }
  76. //+-------------------------------------------------------------------------
  77. //
  78. // Function: SNB_UserMarshall
  79. //
  80. // Synopsis: Marshalls an SNB into the RPC buffer.
  81. //
  82. // Derivation: An array of strings in one block of memory.
  83. //
  84. // history: June-95 Ryszardk Created, based on SNB_*_xmit.
  85. //
  86. //--------------------------------------------------------------------------
  87. unsigned char __RPC_FAR * __RPC_USER
  88. SNB_UserMarshal (
  89. unsigned long * pFlags,
  90. unsigned char * pBuffer,
  91. SNB * pSnb )
  92. {
  93. UserNdrDebugOut((UNDR_FORCE, "SNB_UserMarshal\n"));
  94. if ( ! pSnb )
  95. return pBuffer;
  96. // calculate the number of strings and characters (with their terminators)
  97. ULONG ulCntStr = 0;
  98. ULONG ulCntChar = 0;
  99. if (pSnb && *pSnb)
  100. {
  101. SNB snb = *pSnb;
  102. WCHAR *psz = *snb;
  103. while (psz)
  104. {
  105. ulCntChar += lstrlenW(psz) + 1;
  106. ulCntStr++;
  107. snb++;
  108. psz = *snb;
  109. }
  110. }
  111. // conformant size
  112. ALIGN( pBuffer, 3 );
  113. *( PULONG_LV_CAST pBuffer)++ = ulCntChar;
  114. // fields
  115. *( PULONG_LV_CAST pBuffer)++ = ulCntStr;
  116. *( PULONG_LV_CAST pBuffer)++ = ulCntChar;
  117. // actual strings only
  118. if ( pSnb && *pSnb )
  119. {
  120. // There is a NULL string pointer to mark the end of the pointer array.
  121. // However, the strings don't have to follow tightly.
  122. // Hence, we have to copy one string at a time.
  123. SNB snb = *pSnb;
  124. WCHAR *pszSrc;
  125. while (pszSrc = *snb++)
  126. {
  127. ULONG ulCopyLen = (lstrlenW(pszSrc) + 1) * sizeof(WCHAR);
  128. WdtpMemoryCopy( pBuffer, pszSrc, ulCopyLen );
  129. pBuffer += ulCopyLen;
  130. }
  131. }
  132. return pBuffer;
  133. }
  134. //+-------------------------------------------------------------------------
  135. //
  136. // Function: SNB_UserUnmarshall
  137. //
  138. // Synopsis: Unmarshalls an SNB from the RPC buffer.
  139. //
  140. // Derivation: An array of strings in one block of memory.
  141. //
  142. // history: June-95 Ryszardk Created, based on SNB_*_xmit.
  143. // Aug-99 JohnStra Add consistency checks.
  144. //
  145. //--------------------------------------------------------------------------
  146. unsigned char __RPC_FAR * __RPC_USER
  147. SNB_UserUnmarshal (
  148. unsigned long * pFlags,
  149. unsigned char * pBuffer,
  150. SNB * pSnb )
  151. {
  152. UserNdrDebugOut((UNDR_FORCE, "SNB_UserUnmarshal\n"));
  153. // Initialize CUserMarshalInfo object and get the buffer
  154. // size and pointer to the start of the buffer.
  155. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  156. ULONG_PTR BufferSize = MarshalInfo.GetBufferSize();
  157. UCHAR* pBufferStart = MarshalInfo.GetBuffer();
  158. // Align the buffer and save the size of the fixup.
  159. ALIGN( pBuffer, 3 );
  160. ULONG_PTR cbFixup = (ULONG_PTR)(pBuffer - pBufferStart);
  161. // Check for EOB before trying to get header.
  162. CHECK_BUFFER_SIZE( BufferSize, cbFixup + (3 * sizeof( ULONG )) );
  163. // Get the header from the buffer.
  164. ULONG ulCntChar = *( PULONG_LV_CAST pBuffer)++;
  165. ULONG ulCntStr = *( PULONG_LV_CAST pBuffer)++;
  166. ULONG ulCntCharDup = *(PULONG_LV_CAST pBuffer)++;
  167. // Verify that 2nd instance of count matches first.
  168. if ( ulCntCharDup != ulCntChar )
  169. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  170. // No reusage of pSNB.
  171. if ( *pSnb )
  172. WdtpFree( pFlags, *pSnb );
  173. if ( ulCntStr == 0 )
  174. {
  175. // There are no strings.
  176. // NULL pSnb and return.
  177. *pSnb = NULL;
  178. return pBuffer;
  179. }
  180. // Validate the header:
  181. // Repeated char count must match first instance and char count must
  182. // not be less than the number of strings since that would mean at
  183. // least one of them doesn't isn't terminated.
  184. if ( (ulCntChar != ulCntCharDup) || (ulCntChar < ulCntStr) )
  185. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  186. // Check for EOB before trying to get the strings.
  187. CHECK_BUFFER_SIZE(
  188. BufferSize,
  189. cbFixup + (3 * sizeof(ULONG)) + (ulCntChar * sizeof(WCHAR)) );
  190. // Last WCHAR in the buffer must be the UNICODE terminator.
  191. WCHAR* pszChars = (WCHAR*) pBuffer;
  192. if ( pszChars[ulCntChar - 1] != 0x0000 )
  193. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  194. // construct the SNB.
  195. SNB Snb = (SNB) WdtpAllocate( pFlags,
  196. ( (ulCntStr + 1) * sizeof(WCHAR *) +
  197. ulCntChar * sizeof(WCHAR)) );
  198. *pSnb = Snb;
  199. if (Snb)
  200. {
  201. // create the pointer array within the SNB. to do this, we go through
  202. // the buffer, and use strlen to find the end of the each string for
  203. // us.
  204. WCHAR *pszSrc = (WCHAR *) pBuffer;
  205. WCHAR *pszTgt = (WCHAR *) (Snb + ulCntStr + 1); // right behind array
  206. void* SnbStart = Snb;
  207. ULONG ulTotLen = 0;
  208. ULONG i;
  209. for (i = ulCntStr; (i > 0) && (ulTotLen < ulCntChar); i--)
  210. {
  211. *Snb++ = pszTgt;
  212. ULONG ulLen = lstrlenW(pszSrc) + 1;
  213. pszSrc += ulLen;
  214. pszTgt += ulLen;
  215. ulTotLen += ulLen;
  216. }
  217. *Snb++ = NULL;
  218. // Verify that the number of strings and the number of chars
  219. // in the buffer matches what is supposed to be there.
  220. if ( (i > 0) || (ulTotLen < ulCntChar) )
  221. {
  222. WdtpFree( pFlags, SnbStart );
  223. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  224. }
  225. // Copy the actual strings.
  226. // We can do a block copy here as we packed them tight in the buffer.
  227. // Snb points right behind the lastarray of pointers within the SNB.
  228. WdtpMemoryCopy( Snb, pBuffer, ulCntChar * sizeof(WCHAR) );
  229. pBuffer += ulCntChar * sizeof(WCHAR);
  230. }
  231. return pBuffer;
  232. }
  233. //+-------------------------------------------------------------------------
  234. //
  235. // Function: SNB_UserFree
  236. //
  237. // Synopsis: Frees an SNB.
  238. //
  239. // Derivation: An array of strings in one block of memory.
  240. //
  241. // history: June-95 Ryszardk Created, based on SNB_*_xmit.
  242. //
  243. //--------------------------------------------------------------------------
  244. void __RPC_USER
  245. SNB_UserFree(
  246. unsigned long * pFlags,
  247. SNB * pSnb )
  248. {
  249. if ( pSnb && *pSnb )
  250. WdtpFree( pFlags, *pSnb );
  251. }
  252. #if defined(_WIN64)
  253. //+-------------------------------------------------------------------------
  254. //
  255. // Function: SNB_UserSize64
  256. //
  257. // Synopsis: Sizes an SNB.
  258. //
  259. // Derivation: An array of strings in one block of memory.
  260. //
  261. // history: Dec-00 JohnDoty Created from 32bit function
  262. //
  263. //--------------------------------------------------------------------------
  264. unsigned long __RPC_USER
  265. SNB_UserSize64 (
  266. unsigned long * pFlags,
  267. unsigned long Offset,
  268. SNB * pSnb )
  269. {
  270. if ( ! pSnb )
  271. return Offset;
  272. // calculate the number of strings and characters (with their terminators)
  273. ULONG ulCntStr = 0;
  274. ULONG ulCntChar = 0;
  275. if (pSnb && *pSnb)
  276. {
  277. SNB snb = *pSnb;
  278. WCHAR *psz = *snb;
  279. while (psz)
  280. {
  281. ulCntChar += lstrlenW(psz) + 1;
  282. ulCntStr++;
  283. snb++;
  284. psz = *snb;
  285. }
  286. }
  287. // The wire size is: conf size, 2 fields and the wchars.
  288. LENGTH_ALIGN( Offset, 7 );
  289. return ( Offset + 8 + (2 * sizeof(long)) + (ulCntChar * sizeof(WCHAR)) );
  290. }
  291. //+-------------------------------------------------------------------------
  292. //
  293. // Function: SNB_UserMarshal64
  294. //
  295. // Synopsis: Marshalls an SNB into the RPC buffer.
  296. //
  297. // Derivation: An array of strings in one block of memory.
  298. //
  299. // history: Dec-00 JohnDoty Created from 32bit function
  300. //
  301. //--------------------------------------------------------------------------
  302. unsigned char __RPC_FAR * __RPC_USER
  303. SNB_UserMarshal64 (
  304. unsigned long * pFlags,
  305. unsigned char * pBuffer,
  306. SNB * pSnb )
  307. {
  308. UserNdrDebugOut((UNDR_FORCE, "SNB_UserMarshal\n"));
  309. if ( ! pSnb )
  310. return pBuffer;
  311. // calculate the number of strings and characters (with their terminators)
  312. ULONG ulCntStr = 0;
  313. ULONG ulCntChar = 0;
  314. if (pSnb && *pSnb)
  315. {
  316. SNB snb = *pSnb;
  317. WCHAR *psz = *snb;
  318. while (psz)
  319. {
  320. ulCntChar += lstrlenW(psz) + 1;
  321. ulCntStr++;
  322. snb++;
  323. psz = *snb;
  324. }
  325. }
  326. // conformant size
  327. ALIGN( pBuffer, 7 );
  328. *( PHYPER_LV_CAST pBuffer)++ = ulCntChar;
  329. // fields
  330. *( PULONG_LV_CAST pBuffer)++ = ulCntStr;
  331. *( PULONG_LV_CAST pBuffer)++ = ulCntChar;
  332. // actual strings only
  333. if ( pSnb && *pSnb )
  334. {
  335. // There is a NULL string pointer to mark the end of the pointer array.
  336. // However, the strings don't have to follow tightly.
  337. // Hence, we have to copy one string at a time.
  338. SNB snb = *pSnb;
  339. WCHAR *pszSrc;
  340. while (pszSrc = *snb++)
  341. {
  342. ULONG ulCopyLen = (lstrlenW(pszSrc) + 1) * sizeof(WCHAR);
  343. WdtpMemoryCopy( pBuffer, pszSrc, ulCopyLen );
  344. pBuffer += ulCopyLen;
  345. }
  346. }
  347. return pBuffer;
  348. }
  349. //+-------------------------------------------------------------------------
  350. //
  351. // Function: SNB_UserUnmarshal64
  352. //
  353. // Synopsis: Unmarshalls an SNB from the RPC buffer.
  354. //
  355. // Derivation: An array of strings in one block of memory.
  356. //
  357. // history: Dec-00 JohnDoty Created from 32bit function
  358. //
  359. //--------------------------------------------------------------------------
  360. unsigned char __RPC_FAR * __RPC_USER
  361. SNB_UserUnmarshal64 (
  362. unsigned long * pFlags,
  363. unsigned char * pBuffer,
  364. SNB * pSnb )
  365. {
  366. UserNdrDebugOut((UNDR_FORCE, "SNB_UserUnmarshal\n"));
  367. // Initialize CUserMarshalInfo object and get the buffer
  368. // size and pointer to the start of the buffer.
  369. CUserMarshalInfo MarshalInfo( pFlags, pBuffer );
  370. CarefulBufferReader stream( pBuffer, MarshalInfo.GetBufferSize() );
  371. // Get the header from the buffer.... (ReadHYPER aligns on 8).
  372. ULONG ulCntChar = (ULONG)stream.ReadHYPER();
  373. ULONG ulCntStr = stream.ReadULONGNA();
  374. ULONG ulCntCharDup = stream.ReadULONGNA();
  375. // Verify that 2nd instance of count matches first.
  376. if ( ulCntCharDup != ulCntChar )
  377. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  378. // No reusage of pSNB.
  379. if ( *pSnb )
  380. {
  381. WdtpFree( pFlags, *pSnb );
  382. *pSnb = NULL;
  383. }
  384. if ( ulCntStr == 0 )
  385. {
  386. // There are no strings.
  387. return stream.GetBuffer();
  388. }
  389. // Validate the header:
  390. // Repeated char count must match first instance and char count must
  391. // not be less than the number of strings since that would mean at
  392. // least one of them doesn't isn't terminated.
  393. if ( ulCntChar < ulCntStr )
  394. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  395. // Check for EOB before trying to get the strings.
  396. stream.CheckSize(ulCntChar * sizeof(WCHAR));
  397. // Last WCHAR in the buffer must be the UNICODE terminator.
  398. WCHAR* pszChars = (WCHAR*)stream.GetBuffer();
  399. if ( pszChars[ulCntChar - 1] != L'\0' )
  400. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  401. // construct the SNB.
  402. SNB Snb = (SNB) WdtpAllocate( pFlags,
  403. ( (ulCntStr + 1) * sizeof(WCHAR *) +
  404. ulCntChar * sizeof(WCHAR)) );
  405. *pSnb = Snb;
  406. if (Snb)
  407. {
  408. // create the pointer array within the SNB. to do this, we go through
  409. // the buffer, and use strlen to find the end of the each string for
  410. // us.
  411. WCHAR *pszSrc = (WCHAR *) stream.GetBuffer();
  412. WCHAR *pszTgt = (WCHAR *) (Snb + ulCntStr + 1); // right behind array
  413. void* SnbStart = Snb;
  414. ULONG ulTotLen = 0;
  415. ULONG i;
  416. for (i = ulCntStr; (i > 0) && (ulTotLen < ulCntChar); i--)
  417. {
  418. *Snb++ = pszTgt;
  419. ULONG ulLen = lstrlenW(pszSrc) + 1;
  420. pszSrc += ulLen;
  421. pszTgt += ulLen;
  422. ulTotLen += ulLen;
  423. }
  424. *Snb++ = NULL;
  425. // Verify that the number of strings and the number of chars
  426. // in the buffer matches what is supposed to be there.
  427. if ( (i > 0) || (ulTotLen < ulCntChar) )
  428. {
  429. WdtpFree( pFlags, SnbStart );
  430. RAISE_RPC_EXCEPTION( RPC_X_BAD_STUB_DATA );
  431. }
  432. // Copy the actual strings.
  433. // We can do a block copy here as we packed them tight in the buffer.
  434. // Snb points right behind the lastarray of pointers within the SNB.
  435. WdtpMemoryCopy( Snb, stream.GetBuffer(), ulCntChar * sizeof(WCHAR) );
  436. stream.Advance(ulCntChar * sizeof(WCHAR));
  437. }
  438. return stream.GetBuffer();
  439. }
  440. //+-------------------------------------------------------------------------
  441. //
  442. // Function: SNB_UserFree64
  443. //
  444. // Synopsis: Frees an SNB.
  445. //
  446. // Derivation: An array of strings in one block of memory.
  447. //
  448. // history: Dec-00 JohnDoty Created from 32bit function
  449. //
  450. //--------------------------------------------------------------------------
  451. void __RPC_USER
  452. SNB_UserFree64 (
  453. unsigned long * pFlags,
  454. SNB * pSnb )
  455. {
  456. if ( pSnb && *pSnb )
  457. WdtpFree( pFlags, *pSnb );
  458. }
  459. #endif