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.

697 lines
17 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. floatc.cxx
  5. Abstract:
  6. Float and double conversion routines.
  7. Author:
  8. Dov Harel (DovH) 23-Apr-1992
  9. Environment:
  10. This code should execute in all environments supported by RPC
  11. (DOS, Win 3.X, and Win/NT as well as OS2).
  12. Comments:
  13. This file was completely rewritten to incorporate DCE floating
  14. point conversion. Currently the only supported DCE interoperation
  15. is with DEC system. The vax conversion routines used
  16. (cvt_vax_f_to_ieee_single, and cvt_vax_g_to_ieee_double)
  17. were supplied by Digital, and are used for full compatibility with
  18. DCE RPC. (See name.map for Digital files used).
  19. Also added floating point array conversion routines.
  20. Revision history:
  21. Donna Liu 07-23-1992 Added LowerIndex parameter to
  22. <basetype>_array_from_ndr routines
  23. Dov Harel 08-19-1992 Added RpcpMemoryCopy ([_f]memcpy)
  24. to ..._array_from_ndr routines
  25. Dov Harel 08-25-1992 Added byte swapping for IEEE big endian
  26. machines (such as HP).
  27. --*/
  28. #include <sysinc.h>
  29. #include <rpc.h>
  30. #include <rpcdcep.h>
  31. #include <rpcndr.h>
  32. #include <..\..\ndr20\cvt.h>
  33. #include <ndrlibp.h>
  34. //
  35. // For longs assume the following 32-bit word layout:
  36. //
  37. // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  38. // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  39. // +---------------+---------------+---------------+---------------+
  40. // | A | B | C | D |
  41. // +---------------+---------------+---------------+---------------+
  42. //
  43. //
  44. // Masks defined for long byte swapping:
  45. //
  46. #define MASK_AB__ (unsigned long)0XFFFF0000L
  47. #define MASK___CD (unsigned long)0X0000FFFFL
  48. #define MASK_A_C_ (unsigned long)0XFF00FF00L
  49. #define MASK__B_D (unsigned long)0X00FF00FFL
  50. //
  51. // #define NDR_CHAR_REP_MASK (unsigned long)0X0000000FL
  52. // #define NDR_INT_REP_MASK (unsigned long)0X000000F0L
  53. // #define NDR_FLOAT_REP_MASK (unsigned long)0X0000FF00L
  54. //
  55. // #define NDR_LITTLE_ENDIAN (unsigned long)0X00000010L
  56. // #define NDR_BIG_ENDIAN (unsigned long)0X00000000L
  57. //
  58. // #define NDR_IEEE_FLOAT (unsigned long)0X00000000L
  59. // #define NDR_VAX_FLOAT (unsigned long)0X00000100L
  60. //
  61. // #define NDR_ASCII_CHAR (unsigned long)0X00000000L
  62. // #define NDR_EBCDIC_CHAR (unsigned long)0X00000001L
  63. //
  64. // #define NDR_LOCAL_DATA_REPRESENTATION (unsigned long)0X00000010L
  65. //
  66. #define NDR_FLOAT_INT_MASK (unsigned long)0X0000FFF0L
  67. #define NDR_BIG_IEEE_REP (unsigned long)0X00000000L
  68. #define NDR_LITTLE_IEEE_REP (unsigned long)0X00000010L
  69. void RPC_ENTRY
  70. NdrpLongByteSwap(
  71. IN void PAPI * Source,
  72. OUT void PAPI * Target
  73. )
  74. /*++
  75. Routine Description:
  76. Assuming both Source and Target point to aligned unsigned longs,
  77. move the bytes of *Source into *Target in reverse oreder. The value
  78. of (*Target) following the call is the bate swapped value of
  79. (*Source).
  80. Arguments:
  81. Source - A pointer to an aligned unsigned long.
  82. Target - A pointer to the long to swap the *Source bytes into.
  83. Return Values:
  84. None.
  85. --*/
  86. {
  87. //
  88. // Swap bytes:
  89. //
  90. // First apply the transformation: ABCD => BADC
  91. //
  92. *(unsigned long *)Target =
  93. (*(unsigned long *)Source & MASK_A_C_) >> 8 |
  94. (*(unsigned long *)Source & MASK__B_D) << 8 ;
  95. //
  96. // Now swap the left and right halves of the Target long word
  97. // achieving full swap: BADC => DCBA
  98. //
  99. *(unsigned long *)Target =
  100. (*(unsigned long *)Target & MASK_AB__) >> 16 |
  101. (*(unsigned long *)Target & MASK___CD) << 16 ;
  102. }
  103. //
  104. // end NdrpLongByteSwap
  105. //
  106. /*
  107. //
  108. // Relevant definitions from cvt.h (Digital):
  109. //
  110. typedef unsigned char CVT_BYTE;
  111. typedef CVT_BYTE *CVT_BYTE_PTR;
  112. typedef CVT_BYTE CVT_VAX_F[4];
  113. typedef CVT_BYTE CVT_VAX_D[8];
  114. typedef CVT_BYTE CVT_VAX_G[8];
  115. typedef CVT_BYTE CVT_IEEE_SINGLE[4];
  116. typedef CVT_BYTE CVT_IEEE_DOUBLE[8];
  117. //
  118. // Relevant definitions from vaxout.c
  119. // (previous floating point conversion test):
  120. //
  121. CVT_VAX_F inputf;
  122. CVT_IEEE_SINGLE outputf;
  123. CVT_VAX_G inputg;
  124. CVT_IEEE_DOUBLE outputg;
  125. cvt_vax_f_to_ieee_single( inputf, 0, outputf );
  126. cvt_vax_g_to_ieee_double( inputg, 0, outputg );
  127. */
  128. void RPC_ENTRY
  129. float_from_ndr (
  130. IN OUT PRPC_MESSAGE SourceMessage,
  131. OUT void * Target
  132. )
  133. /*++
  134. Routine Description:
  135. Unmarshall a float from an RPC message buffer into the target
  136. (*Target). This routine:
  137. o Aligns the buffer pointer to the next (0 mod 4) boundary.
  138. o Unmarshalls the float; performs data conversion if necessary
  139. (only VAX and IEEE Big Endian conversion currently supported).
  140. o Advances the buffer pointer to the address immediately
  141. following the unmarshalled float.
  142. Arguments:
  143. SourceMessage - A pointer to an RPC_MESSAGE.
  144. IN - SourceMessage->Buffer points to the address just prior to
  145. the float to be unmarshalled.
  146. OUT - SourceMessage->Buffer points to the address just following
  147. the float which was just unmarshalled.
  148. Target - A pointer to the float to unmarshall the data into.
  149. A (void*) pointer is used, so that the runtime library code
  150. is not loaded, unless the application code actually uses
  151. floating point.
  152. Return Values:
  153. None.
  154. --*/
  155. {
  156. unsigned char PAPI * F_Input =
  157. (unsigned char *)SourceMessage->Buffer;
  158. unsigned char PAPI * F_Output = (unsigned char PAPI *)Target;
  159. // CVT_IEEE_SINGLE F_Output = (unsigned char PAPI *)Target;
  160. unsigned long SenderDataRepresentation;
  161. //
  162. // Align F_Input to next (0 mod 4) address
  163. //
  164. *(unsigned long *)&F_Input += 3;
  165. *(unsigned long *)&F_Input &= 0XFFFFFFFCL;
  166. if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
  167. NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
  168. //
  169. // Robust check for little endian IEEE (local data representation)
  170. //
  171. {
  172. *(unsigned long *)Target = *(unsigned long*)F_Input;
  173. }
  174. else if ( (SenderDataRepresentation & NDR_FLOAT_REP_MASK) ==
  175. NDR_VAX_FLOAT )
  176. {
  177. cvt_vax_f_to_ieee_single(F_Input, 0, F_Output);
  178. }
  179. else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
  180. NDR_BIG_IEEE_REP )
  181. //
  182. // Big endian IEEE sender:
  183. //
  184. {
  185. NdrpLongByteSwap(F_Input, F_Output);
  186. }
  187. else
  188. {
  189. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  190. }
  191. //
  192. // Advance the buffer pointer before returning:
  193. //
  194. SourceMessage->Buffer = F_Input + 4;
  195. }
  196. //
  197. // end float_from_ndr
  198. //
  199. void RPC_ENTRY
  200. float_array_from_ndr (
  201. IN OUT PRPC_MESSAGE SourceMessage,
  202. IN unsigned long LowerIndex,
  203. IN unsigned long UpperIndex,
  204. OUT void * Target
  205. )
  206. /*++
  207. Routine Description:
  208. Unmarshall an array of floats from an RPC message buffer into
  209. the range Target[LowerIndex] .. Target[UpperIndex-1] of the
  210. target array of floats (Target[]). This routine:
  211. o Aligns the buffer pointer to the next (0 mod 4) boundary,
  212. o Unmarshalls MemberCount floats; performs data
  213. conversion if necessary (Currently VAX format only), and
  214. o Advances the buffer pointer to the address immediately
  215. following the last unmarshalled float.
  216. Arguments:
  217. SourceMessage - A pointer to an RPC_MESSAGE.
  218. IN - SourceMessage->Buffer points to the address just prior to
  219. the first float to be unmarshalled.
  220. OUT - SourceMessage->Buffer points to the address just following
  221. the last float which was just unmarshalled.
  222. LowerIndex - Lower index into the target array.
  223. UpperIndex - Upper bound index into the target array.
  224. Target - A pointer to an array of floats to unmarshall the data into.
  225. A (void*) pointer is used, so that the runtime library code
  226. is not loaded, unless the application code actually uses
  227. floating point.
  228. Return Values:
  229. None.
  230. --*/
  231. {
  232. unsigned char PAPI * F_Input =
  233. (unsigned char PAPI *)SourceMessage->Buffer;
  234. unsigned char PAPI * F_Output = (unsigned char PAPI *)Target;
  235. register unsigned int Index;
  236. unsigned long SenderDataRepresentation;
  237. //
  238. // Align F_Input to next (0 mod 4) address
  239. //
  240. *(unsigned long *)&F_Input += 3;
  241. *(unsigned long *)&F_Input &= 0XFFFFFFFCL;
  242. if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
  243. NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
  244. //
  245. // Robust check for little endian IEEE (local data representation)
  246. //
  247. {
  248. int byteCount = 4*(int)(UpperIndex - LowerIndex);
  249. RpcpMemoryCopy(
  250. F_Output,
  251. F_Input,
  252. byteCount
  253. );
  254. //
  255. // Update SourceMessage->Buffer
  256. //
  257. SourceMessage->Buffer = (void PAPI *)(F_Input + byteCount);
  258. /* Replaced by RpcpMemoryCopy:
  259. for (Index = LowerIndex; Index < UpperIndex; Index++)
  260. {
  261. ((unsigned long *)F_Output)[Index] =
  262. *(unsigned long *)F_Input;
  263. F_Input += 4;
  264. }
  265. //
  266. // Advance the buffer pointer before returning:
  267. //
  268. SourceMessage->Buffer = F_Input;
  269. */
  270. }
  271. else if ( (SenderDataRepresentation & NDR_FLOAT_REP_MASK) ==
  272. NDR_VAX_FLOAT )
  273. {
  274. F_Output += 4 * LowerIndex;
  275. for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
  276. {
  277. cvt_vax_f_to_ieee_single(F_Input, 0, F_Output);
  278. F_Input += 4;
  279. F_Output += 4;
  280. }
  281. //
  282. // Advance the buffer pointer before returning:
  283. //
  284. SourceMessage->Buffer = F_Input;
  285. }
  286. else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
  287. NDR_BIG_IEEE_REP )
  288. //
  289. // Big endian IEEE sender:
  290. //
  291. {
  292. F_Output += 4 * LowerIndex;
  293. for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
  294. {
  295. NdrpLongByteSwap(F_Input, F_Output);
  296. F_Input += 4;
  297. F_Output += 4;
  298. }
  299. //
  300. // Advance the buffer pointer before returning:
  301. //
  302. SourceMessage->Buffer = F_Input;
  303. }
  304. else
  305. {
  306. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  307. }
  308. }
  309. //
  310. // end float_array_from_ndr
  311. //
  312. void RPC_ENTRY
  313. double_from_ndr (
  314. IN OUT PRPC_MESSAGE SourceMessage,
  315. OUT void * Target
  316. )
  317. /*++
  318. Routine Description:
  319. Unmarshall a double from an RPC message buffer into the target
  320. (*Target). This routine:
  321. o Aligns the buffer pointer to the next (0 mod 8) boundary.
  322. o Unmarshalls the double; performs data conversion if necessary
  323. (only VAX conversion currently supported).
  324. o Advances the buffer pointer to the address immediately
  325. following the unmarshalled double.
  326. Arguments:
  327. SourceMessage - A pointer to an RPC_MESSAGE.
  328. IN - SourceMessage->Buffer points to the address just prior to
  329. the double to be unmarshalled.
  330. OUT - SourceMessage->Buffer points to the address just following
  331. the double which was just unmarshalled.
  332. Target - A pointer to the double to unmarshall the data into.
  333. A (void*) pointer is used, so that the runtime library code
  334. is not loaded, unless the application code actually uses
  335. floating point.
  336. Return Values:
  337. None.
  338. --*/
  339. {
  340. unsigned char PAPI * D_Input =
  341. (unsigned char PAPI *)SourceMessage->Buffer;
  342. unsigned char PAPI * D_Output = (unsigned char PAPI *)Target;
  343. unsigned long SenderDataRepresentation;
  344. //
  345. // Align D_Input to next (0 mod 8) address
  346. //
  347. *(unsigned long *)&D_Input += 7;
  348. *(unsigned long *)&D_Input &= 0XFFFFFFF8L;
  349. if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
  350. NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
  351. //
  352. // Robust check for little endian IEEE (local data representation)
  353. //
  354. {
  355. ((unsigned long *)Target)[0] = ((unsigned long*)D_Input)[0];
  356. ((unsigned long *)Target)[1] = ((unsigned long*)D_Input)[1];
  357. }
  358. else if ( (SourceMessage->DataRepresentation & NDR_FLOAT_REP_MASK) ==
  359. NDR_VAX_FLOAT )
  360. {
  361. cvt_vax_g_to_ieee_double(D_Input, 0, D_Output);
  362. }
  363. else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
  364. NDR_BIG_IEEE_REP )
  365. //
  366. // Big endian IEEE sender:
  367. //
  368. {
  369. //
  370. // Swap the low half of D_Input into the high half of D_Output
  371. //
  372. NdrpLongByteSwap(
  373. &((unsigned long*)D_Input)[0],
  374. &((unsigned long *)Target)[1]
  375. );
  376. //
  377. // Swap the high half of D_Input into the low half of D_Output
  378. //
  379. NdrpLongByteSwap(
  380. &((unsigned long*)D_Input)[1],
  381. &((unsigned long *)Target)[0]
  382. );
  383. }
  384. else
  385. {
  386. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  387. }
  388. //
  389. // Advance the buffer pointer before returning:
  390. //
  391. SourceMessage->Buffer = D_Input + 8;
  392. }
  393. //
  394. // end double_from_ndr
  395. //
  396. void RPC_ENTRY
  397. double_array_from_ndr (
  398. IN OUT PRPC_MESSAGE SourceMessage,
  399. IN unsigned long LowerIndex,
  400. IN unsigned long UpperIndex,
  401. OUT void * Target
  402. )
  403. /*++
  404. Routine Description:
  405. Unmarshall an array of doubles from an RPC message buffer into
  406. the range Target[LowerIndex] .. Target[UpperIndex-1] of the
  407. target array of (Target[]). This routine:
  408. o Aligns the buffer pointer to the next (0 mod 8) boundary,
  409. o Unmarshalls MemberCount doubles; performs data
  410. conversion if necessary (Currently VAX format only), and
  411. o Advances the buffer pointer to the address immediately
  412. following the last unmarshalled double.
  413. Arguments:
  414. SourceMessage - A pointer to an RPC_MESSAGE.
  415. IN - SourceMessage->Buffer points to the address just prior to
  416. the first double to be unmarshalled.
  417. OUT - SourceMessage->Buffer points to the address just following
  418. the last double which was just unmarshalled.
  419. LowerIndex - Lower index into the target array.
  420. UpperIndex - Upper bound index into the target array.
  421. Target - A pointer to an array of doubles to unmarshall the data into.
  422. A (void*) pointer is used, so that the runtime library code
  423. is not loaded, unless the application code actually uses
  424. floating point.
  425. Return Values:
  426. None.
  427. --*/
  428. {
  429. unsigned char PAPI * D_Input =
  430. (unsigned char PAPI *)SourceMessage->Buffer;
  431. unsigned char PAPI * D_Output = (unsigned char PAPI *)Target;
  432. register unsigned int Index;
  433. unsigned long SenderDataRepresentation;
  434. //
  435. // Align D_Input to next (0 mod 8) address
  436. //
  437. *(unsigned long *)&D_Input += 7;
  438. *(unsigned long *)&D_Input &= 0XFFFFFFF8L;
  439. if ( ( (SenderDataRepresentation = SourceMessage->DataRepresentation) &
  440. NDR_FLOAT_INT_MASK ) == NDR_LITTLE_IEEE_REP )
  441. //
  442. // Robust check for little endian IEEE (local data representation)
  443. //
  444. {
  445. int byteCount = 8*(int)(UpperIndex - LowerIndex);
  446. RpcpMemoryCopy(
  447. D_Output,
  448. D_Input,
  449. byteCount
  450. );
  451. //
  452. // Update SourceMessage->Buffer
  453. //
  454. SourceMessage->Buffer = (void PAPI *)(D_Input + byteCount);
  455. /* Replaced by RpcpMemoryCopy:
  456. for (Index = LowerIndex; Index < UpperIndex; Index++)
  457. {
  458. ((unsigned long *)D_Output)[(Index * 2)] =
  459. *(unsigned long *)D_Input;
  460. D_Input += 4;
  461. ((unsigned long *)D_Output)[(Index * 2 + 1)] =
  462. *((unsigned long *)D_Input) ;
  463. D_Input += 4;
  464. }
  465. //
  466. // Advance the buffer pointer before returning:
  467. //
  468. SourceMessage->Buffer = D_Input;
  469. */
  470. }
  471. else if ( (SourceMessage->DataRepresentation & NDR_FLOAT_REP_MASK) ==
  472. NDR_VAX_FLOAT )
  473. {
  474. for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
  475. {
  476. cvt_vax_g_to_ieee_double(D_Input, 0, D_Output);
  477. D_Input += 8;
  478. D_Output += 8;
  479. }
  480. //
  481. // Advance the buffer pointer before returning:
  482. //
  483. SourceMessage->Buffer = D_Input;
  484. }
  485. else if ( (SenderDataRepresentation & NDR_FLOAT_INT_MASK) ==
  486. NDR_BIG_IEEE_REP )
  487. //
  488. // Big endian IEEE sender:
  489. //
  490. {
  491. for (Index = (int)LowerIndex; Index < UpperIndex; Index++)
  492. {
  493. NdrpLongByteSwap(
  494. &((unsigned long PAPI *)D_Input)[0],
  495. &((unsigned long PAPI *)D_Output)[1]
  496. );
  497. NdrpLongByteSwap(
  498. &((unsigned long PAPI *)D_Input)[1],
  499. &((unsigned long PAPI *)D_Output)[0]
  500. );
  501. D_Input += 8;
  502. D_Output += 8;
  503. }
  504. //
  505. // Advance the buffer pointer before returning:
  506. //
  507. SourceMessage->Buffer = D_Input;
  508. }
  509. else
  510. {
  511. RpcRaiseException( RPC_X_BAD_STUB_DATA );
  512. }
  513. }
  514. //
  515. // end double_array_from_ndr
  516. //
  517.