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.

2478 lines
78 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. Convert.c
  5. Abstract:
  6. This module contains RapConvertSingleEntry and RapConvertSingleEntryEx,
  7. routines used by XactSrv and RpcXlate.
  8. Author:
  9. David Treadwell (davidtr) 07-Jan-1991
  10. Environment:
  11. Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. 12-Mar-1991 JohnRo
  15. Converted from Xs routines to Rap routines.
  16. Added TransmissionMode handling.
  17. Changed to use <remtypes.h> REM_ equates for descriptor chars.
  18. 18-Mar-1991 W-Shanku
  19. Added new conversion pairs.
  20. Changes to make code neater.
  21. Use SmbGet/Put for all structure data greater than one byte.
  22. 14-Apr-1991 JohnRo
  23. Reduce recompiles.
  24. 16-Apr-1991 JohnRo
  25. Include <lmcons.h> for <netlib.h>.
  26. 21-Apr-1991 JohnRo
  27. Clarify that OutStructure is OUT, not IN.
  28. 29-Apr-1991 JohnRo
  29. Quiet debug output by default.
  30. 15-May-1991 JohnRo
  31. Added conversion mode handling.
  32. 20-May-1991 JohnRo
  33. Stub out REM_SEND_LENBUF for print APIs. Use FORMAT_LPVOID.
  34. 05-Jun-1991 JohnRo
  35. Added support for RapTotalSize().
  36. 19-Jun-1991 JohnRo
  37. Do more alignment handling, to fix print job get info (level 1) bug.
  38. 01-Jul-1991 JohnRo
  39. Use Rap Get/Put macros.
  40. 19-Aug-1991 JohnRo
  41. Reduce recompiles (use MEMCPY macro). Use DESCLEN macro.
  42. Use DESC_CHAR_IS_DIGIT() macro too.
  43. 07-Sep-1991 JohnRo
  44. PC-LINT says we don't need <lmcons.h> here.
  45. 19-Sep-1991 T-JamesW
  46. Added support for string maximum length counts.
  47. Added support for REM_ASCIZ_TRUNCATABLE.
  48. Removed DESCLEN calls in which string is not a descriptor.
  49. 07-Oct-1991 JohnRo
  50. Support implicit conversion between UNICODE and code page.
  51. Changed last debug print formats to use equates. (This will help if
  52. we change the descriptor strings to be UNICODE.)
  53. Use DESC_CHAR in T-JamesW's code.
  54. 26-Oct-1991 W-ShankN
  55. Fixed z->B conversion to support a NULL source string.
  56. 13-Nov-1991 W-ShankN
  57. Fixed up bugs in some of newer code.
  58. 22-Nov-1991 JohnRo
  59. Added debug print if we aren't even writing fixed portion.
  60. Get rid of a few unused local variables.
  61. 24-Nov-1991 W-ShankN
  62. Added Unicode support for several cases.
  63. 05-Dec-1991 W-ShankN
  64. Added REM_BYTE_PTR, REM_SEND_LENBUF.
  65. 15-Jun-1992 JohnRo
  66. RAID 10324: net print vs. UNICODE (added REM_BYTE to REM_WORD convert).
  67. 17-Aug-1992 JohnRo
  68. RAID 2920: Support UTC timezone in net code.
  69. Use PREFIX_ equates.
  70. 01-Oct-1992 JohnRo
  71. RAID 3556: Added NetpSystemTimeToGmtTime() for DosPrint APIs.
  72. --*/
  73. #define UNSUPPORTED_COMBINATION(One, TheOther) \
  74. { \
  75. NetpKdPrint(( PREFIX_NETRAP \
  76. "RapConvertSingleEntry: Unsupported combination: " \
  77. "'" FORMAT_DESC_CHAR "' and '" FORMAT_DESC_CHAR "'\n", \
  78. (One), (TheOther) )); \
  79. NetpAssert(FALSE); \
  80. }
  81. // These must be included first:
  82. #include <windows.h> // IN, LPTSTR, etc.
  83. #include <lmcons.h> // NET_API_STATUS.
  84. // These may be included in any order:
  85. #include <lmerr.h> // NERR_Success, etc.
  86. #include <align.h> // ROUND_UP_POINTER(), ALIGN_DWORD, etc.
  87. #include <netdebug.h> // FORMAT_ equates, NetpAssert(), etc.
  88. #include <rap.h> // My prototype, LPDESC, DESCLEN(), etc.
  89. #include <rapdebug.h> // IF_DEBUG().
  90. #include <rapgtpt.h> // RapGetDword(), etc.
  91. #include <remtypes.h> // REM_WORD, etc.
  92. #include <string.h> // strlen().
  93. #include <tstring.h> // MEMCPY(), STRLEN().
  94. #include <netlib.h> // NetpMemoryAllocate
  95. #include <prefix.h> // PREFIX_ equates.
  96. #include <timelib.h> // NetpGmtTimeToLocalTime(), etc.
  97. #define RAP_POINTER_SIZE( _isNative, _SetOffsets ) (_isNative ? sizeof(LPVOID) : sizeof(DWORD) )
  98. #define RAP_PUT_POINTER( _SetOffsets, Ptr, Value, Native ) if (Native) {RapPutDword_Ptr( Ptr, Value, Native ); } else { RapPutDword( Ptr, Value, Native );}
  99. PVOID
  100. RapGetPointer(
  101. IN PVOID InStructure,
  102. IN BOOL InNative,
  103. IN UINT_PTR Bias
  104. )
  105. {
  106. UINT_PTR Value;
  107. if ( InNative ) {
  108. // remark: used to call RapGetDword but that truncated
  109. // 64 bit pointers. See bug 104264 for more.
  110. Value = * (UINT_PTR*) (InStructure);
  111. }
  112. else {
  113. Value = SmbGetUlong( (LPDWORD) (InStructure) );
  114. }
  115. #if defined(_WIN64)
  116. //
  117. // For 64-bit, RapSetPointer() stores only the buffer offset. This,
  118. // together with the original address of the buffer (Bias) yields the
  119. // pointer value.
  120. //
  121. if( Value != 0 ) {
  122. Value += Bias;
  123. }
  124. #endif
  125. return (PVOID)Value;
  126. }
  127. NET_API_STATUS
  128. RapConvertSingleEntryEx (
  129. IN LPBYTE InStructure,
  130. IN LPDESC InStructureDesc,
  131. IN BOOL MeaninglessInputPointers,
  132. IN LPBYTE OutBufferStart OPTIONAL,
  133. OUT LPBYTE OutStructure OPTIONAL,
  134. IN LPDESC OutStructureDesc,
  135. IN BOOL SetOffsets,
  136. IN OUT LPBYTE *StringLocation OPTIONAL,
  137. IN OUT LPDWORD BytesRequired,
  138. IN RAP_TRANSMISSION_MODE TransmissionMode,
  139. IN RAP_CONVERSION_MODE ConversionMode,
  140. IN UINT_PTR Bias
  141. )
  142. /*++
  143. Routine Description:
  144. This routine converts a single structure from one representation to
  145. another. The representations are described by the descriptor strings
  146. (see the "OS/2 Lanman Remote Admin Protocol" spec).
  147. If there isn't enough space in the buffer for the entire structure,
  148. this routine simply updates the BytesRequired parameter. Therefore,
  149. callers have a convenient mechanism for determining the total buffer
  150. size required to get all the information without special-casing for
  151. buffer overflow.
  152. Arguments:
  153. InStructure - a pointer to the input structure.
  154. InStructureDesc - the descriptor string for the input string.
  155. MeaninglessInputPointers - if TRUE, then all pointers in the input
  156. structure are meaningless. This routine should assume that
  157. the first variable data immediately follows the input structure,
  158. and the rest of the variable data follows in order.
  159. OutBufferStart - the first byte in the output buffer. For Enum APIs,
  160. this is used to calculate offsets from the start of the buffer
  161. for string pointers. (This pointer may be null, to allow length
  162. computations only.)
  163. OutStructure - a pointer to where to put the actual output structure.
  164. (This pointer may be null, to allow length computations only.)
  165. OutStructureDesc - the descriptor string for the output structure.
  166. SetOffsets - TRUE if pointer values in the output structure should
  167. actually be set to the offset from the beginning of the structure.
  168. FALSE if the actual addresses should be used.
  169. StringLocation - the *last* location for variable-length data. The
  170. data will be placed before this location and the pointer will
  171. be updated to reflect the data added.
  172. BytesRequired - the total number of bytes that would be required to
  173. store the complete output structure. This allows the calling
  174. routine to track the total required for all information without
  175. worrying about buffer overflow.
  176. Transmission Mode - Indicates whether this array is part of a response,
  177. a request, or both.
  178. Conversion Mode - Indicates whether this is a RAP-to-native, native-to-RAP,
  179. or native-to-native conversion.
  180. Bias - Indicates the bias that must be applied to embedded pointers
  181. before dereferencing them.
  182. Return Value:
  183. None.
  184. --*/
  185. {
  186. BOOL inNative, outNative;
  187. BOOL inUNICODE, outUNICODE;
  188. DWORD outStructureSize;
  189. LPBYTE nextStructureLocation;
  190. BOOL fixedWrite;
  191. BOOL outputBufferSupplied;
  192. LPBYTE variableInputData;
  193. DESC_CHAR currentInStructureDesc;
  194. NetpAssert( sizeof(CHAR) == sizeof(BYTE) );
  195. switch (ConversionMode) {
  196. case NativeToNative : inNative=TRUE ; outNative=TRUE ; break;
  197. case NativeToRap : inNative=TRUE ; outNative=FALSE; break;
  198. case RapToNative : inNative=FALSE; outNative=TRUE ; break;
  199. case RapToRap : inNative=FALSE; outNative=FALSE; break;
  200. default :
  201. NetpKdPrint(( PREFIX_NETRAP
  202. "RapConvertSingleEntry: invalid conversion mode!\n"));
  203. NetpAssert(FALSE);
  204. return ERROR_INVALID_PARAMETER;
  205. }
  206. //
  207. // Make sure there's actually some data to convert
  208. //
  209. if ( *InStructureDesc != '\0' && InStructure == NULL )
  210. {
  211. return ERROR_INVALID_PARAMETER;
  212. }
  213. // Policy: native format implies TCHARs, RAP format imples default codepage.
  214. inUNICODE = inNative;
  215. outUNICODE = outNative;
  216. if (OutStructure != NULL) {
  217. NetpAssert(OutBufferStart != NULL);
  218. NetpAssert(StringLocation != NULL);
  219. outputBufferSupplied = TRUE;
  220. } else {
  221. NetpAssert(OutBufferStart == NULL);
  222. outputBufferSupplied = FALSE;
  223. }
  224. //
  225. // If the input doesn't have good pointers, the variable data is
  226. // stored after the fixed structure. Set up to handle this.
  227. //
  228. if ( MeaninglessInputPointers ) {
  229. variableInputData = InStructure
  230. + RapStructureSize(
  231. InStructureDesc, TransmissionMode, inNative );
  232. }
  233. //
  234. // Find the size of the output structure and update variables with it.
  235. //
  236. outStructureSize =
  237. RapStructureSize( OutStructureDesc, TransmissionMode, outNative );
  238. *BytesRequired += outStructureSize;
  239. if (OutStructure != NULL) {
  240. nextStructureLocation = OutStructure + outStructureSize;
  241. } else {
  242. nextStructureLocation = NULL;
  243. }
  244. IF_DEBUG(CONVERT) {
  245. NetpKdPrint(( PREFIX_NETRAP
  246. "RapConvertSingleEntry: bytes required starts at "
  247. FORMAT_DWORD "\n", *BytesRequired ));
  248. }
  249. //
  250. // Determine whether the fixed structure will fit. If it won't, we'll
  251. // still loop through the descriptor strings in order to determine
  252. // how much space the converted structure will take (to fill in the
  253. // proper value in BytesRequired).
  254. //
  255. if ( OutStructure != NULL) {
  256. if ( OutStructure + outStructureSize > *StringLocation ) {
  257. fixedWrite = FALSE;
  258. IF_DEBUG(CONVERT) {
  259. NetpKdPrint(( PREFIX_NETRAP
  260. "RapConvertSingleEntry: NOT WRITING FIXED AREA.\n" ));
  261. }
  262. } else {
  263. fixedWrite = TRUE;
  264. }
  265. } else {
  266. fixedWrite = FALSE;
  267. }
  268. //
  269. // Loop through the input descriptor string, converting entries as
  270. // we go.
  271. //
  272. while ( *InStructureDesc != '\0' ) {
  273. IF_DEBUG(CONVERT) {
  274. NetpKdPrint(( PREFIX_NETRAP "InStruct at " FORMAT_LPVOID
  275. ", desc at " FORMAT_LPVOID " (" FORMAT_DESC_CHAR ")"
  276. ", outStruct at " FORMAT_LPVOID ", "
  277. "desc at " FORMAT_LPVOID " (" FORMAT_DESC_CHAR ")\n",
  278. (LPVOID) InStructure, (LPVOID) InStructureDesc,
  279. *InStructureDesc,
  280. (LPVOID) OutStructure, (LPVOID) OutStructureDesc,
  281. *OutStructureDesc ));
  282. }
  283. NetpAssert( *OutStructureDesc != '\0' );
  284. switch ( currentInStructureDesc = *InStructureDesc++ ) {
  285. case REM_BYTE:
  286. switch ( *OutStructureDesc++ ) {
  287. case REM_BYTE: {
  288. //
  289. // Convert a byte or bytes to bytes.
  290. //
  291. DWORD inLength, outLength;
  292. // Get lengths and update descriptor pointers.
  293. inLength = RapDescArrayLength( InStructureDesc );
  294. outLength = RapDescArrayLength( OutStructureDesc );
  295. //
  296. // Assumption - the array sizes should match. If one length
  297. // is twice the other, do the appropriate Ansi/Unicode conversion.
  298. //
  299. NetpAssert( inLength > 0 );
  300. NetpAssert( outLength > 0 );
  301. if ( outLength == inLength ) {
  302. for( ; inLength > 0; inLength-- ) {
  303. if ( fixedWrite ) {
  304. *OutStructure = *InStructure;
  305. OutStructure++;
  306. }
  307. InStructure++;
  308. }
  309. } else if (outLength == (DWORD) (2*inLength)) {
  310. NetpAssert( sizeof(TCHAR) == (2*sizeof(CHAR)) );
  311. if ( fixedWrite ) {
  312. NetpCopyStrToWStr(
  313. (LPWSTR) OutStructure, // dest
  314. (LPSTR) InStructure); // src
  315. OutStructure += outLength;
  316. }
  317. InStructure += inLength;
  318. } else if (inLength == (DWORD) (2*outLength)) {
  319. NetpAssert( sizeof(TCHAR) == (2*sizeof(CHAR)) );
  320. if ( fixedWrite ) {
  321. NetpCopyWStrToStrDBCS(
  322. (LPSTR) OutStructure, // dest
  323. (LPWSTR) InStructure); // src
  324. OutStructure += outLength;
  325. }
  326. InStructure += inLength;
  327. } else {
  328. NetpAssert( FALSE );
  329. }
  330. break;
  331. }
  332. case REM_BYTE_PTR: {
  333. DWORD inLength, outLength;
  334. LPDWORD offset;
  335. LPBYTE bytePtr;
  336. //
  337. // Convert a fixed byte array to an indirect array of
  338. // bytes.
  339. //
  340. inLength = RapDescArrayLength( InStructureDesc );
  341. outLength = RapDescArrayLength( OutStructureDesc );
  342. //
  343. // Assumption - the array sizes should match.
  344. //
  345. NetpAssert( inLength == outLength );
  346. //
  347. // Update input pointer.
  348. //
  349. bytePtr = InStructure;
  350. InStructure += inLength;
  351. //
  352. // Align output pointer if necessary.
  353. //
  354. if ( fixedWrite ) {
  355. OutStructure = RapPossiblyAlignPointer(
  356. OutStructure, ALIGN_LPBYTE, outNative );
  357. }
  358. //
  359. // Update bytes required.
  360. //
  361. *BytesRequired += outLength;
  362. IF_DEBUG(CONVERT) {
  363. NetpKdPrint(( PREFIX_NETRAP
  364. "RapConvertSingleEntry: bytes required now "
  365. FORMAT_DWORD "\n", *BytesRequired ));
  366. }
  367. //
  368. // Determine whether the data will fit in the available
  369. // buffer space.
  370. //
  371. if ( outputBufferSupplied ) {
  372. offset = (LPDWORD) OutStructure;
  373. if ( fixedWrite ) {
  374. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  375. }
  376. IF_DEBUG(CONVERT) {
  377. NetpKdPrint(( PREFIX_NETRAP
  378. "RapConvertSingleEntry: B->b, "
  379. "offset after alignment is " FORMAT_LPVOID "\n",
  380. (LPVOID) offset ));
  381. }
  382. if ( (ULONG_PTR)*StringLocation <
  383. (ULONG_PTR)nextStructureLocation + outLength ) {
  384. //
  385. // There isn't enough space to hold the data--it
  386. // would go into the last fixed structure. Put a
  387. // NULL in the offset and don't copy over the
  388. // data.
  389. //
  390. if ( fixedWrite ) {
  391. RAP_PUT_POINTER( SetOffsets, offset, 0, outNative );
  392. }
  393. break;
  394. }
  395. //
  396. // Determine where the bytes will go.
  397. //
  398. IF_DEBUG(CONVERT) {
  399. NetpKdPrint(( PREFIX_NETRAP
  400. "RapConvertSingleEntry: B->b, "
  401. "*StringLocation=" FORMAT_LPVOID "\n",
  402. (LPVOID) *StringLocation ));
  403. }
  404. *StringLocation = *StringLocation - outLength;
  405. //
  406. // Set the offset value or the actual address in the
  407. // fixed structure. Update the fixed structure
  408. // pointer.
  409. //
  410. if ( fixedWrite ) {
  411. if ( SetOffsets ) {
  412. IF_DEBUG(CONVERT) {
  413. NetpKdPrint(( PREFIX_NETRAP
  414. "RapConvertSingleEntry: B->b, "
  415. "setting offset " FORMAT_HEX_DWORD "\n",
  416. (DWORD)( *StringLocation - OutBufferStart )));
  417. }
  418. RapPutDword( offset,
  419. (DWORD)( *StringLocation - OutBufferStart),
  420. outNative );
  421. } else {
  422. IF_DEBUG(CONVERT) {
  423. NetpKdPrint(( PREFIX_NETRAP
  424. "RapConvertSingleEntry: B->b, "
  425. "setting pointer " FORMAT_POINTER
  426. "\n", (DWORD_PTR) (*StringLocation) ));
  427. }
  428. RapPutDword_Ptr( offset,
  429. (DWORD_PTR)( *StringLocation ),
  430. outNative);
  431. }
  432. //
  433. // Copy over the bytes.
  434. //
  435. memcpy(
  436. (LPBYTE)*StringLocation,
  437. bytePtr,
  438. inLength
  439. );
  440. }
  441. } // if ( outputBufferSupplied )
  442. break;
  443. }
  444. case REM_WORD : {
  445. //
  446. // Convert an unsigned byte to an 16-bit unsigned word.
  447. //
  448. NetpAssert( !DESC_CHAR_IS_DIGIT( *InStructureDesc ) );
  449. NetpAssert( !DESC_CHAR_IS_DIGIT( *OutStructureDesc ) );
  450. if ( fixedWrite ) {
  451. LPWORD outData = RapPossiblyAlignPointer(
  452. (LPWORD)(LPVOID)OutStructure,
  453. ALIGN_WORD, outNative );
  454. RapPutWord( outData, (WORD) *InStructure, outNative );
  455. OutStructure = ((LPBYTE)outData) + sizeof(WORD);
  456. }
  457. InStructure++;
  458. break;
  459. }
  460. case REM_DWORD : {
  461. //
  462. // Convert a byte to a 32-bit unsigned value.
  463. //
  464. NetpAssert( !DESC_CHAR_IS_DIGIT( *InStructureDesc ));
  465. if ( fixedWrite ) {
  466. LPDWORD outData = RapPossiblyAlignPointer(
  467. (LPDWORD)(LPVOID)OutStructure,
  468. ALIGN_DWORD, outNative );
  469. RapPutDword( outData, (DWORD)*InStructure, outNative );
  470. OutStructure = ((LPBYTE)outData) + sizeof(DWORD);
  471. }
  472. InStructure++;
  473. break;
  474. }
  475. case REM_SIGNED_DWORD :
  476. //
  477. // Convert a byte to a 32-bit sign extended value.
  478. //
  479. NetpAssert( !DESC_CHAR_IS_DIGIT( *InStructureDesc ));
  480. if ( fixedWrite ) {
  481. LPDWORD outData = RapPossiblyAlignPointer(
  482. (LPDWORD)OutStructure, ALIGN_DWORD, outNative );
  483. DWORD data = (DWORD) *(LPDWORD)RapPossiblyAlignPointer(
  484. (LPDWORD)InStructure, ALIGN_DWORD, inNative );
  485. if ( data & 0x80 ) {
  486. data |= 0xFFFFFF00;
  487. }
  488. RapPutDword( outData, data, outNative );
  489. OutStructure = OutStructure + sizeof(DWORD);
  490. }
  491. InStructure++;
  492. break;
  493. case REM_IGNORE :
  494. //
  495. // The input is an ignored pad. Just update pointers.
  496. //
  497. InStructure += RapDescArrayLength( InStructureDesc );
  498. break;
  499. case REM_ASCIZ:
  500. case REM_ASCIZ_TRUNCATABLE: {
  501. //
  502. // Convert a byte array to an ASCIIZ.
  503. //
  504. LPDWORD offset;
  505. DWORD inLength, outLength;
  506. DWORD stringSize;
  507. LPBYTE stringPtr = InStructure;
  508. //
  509. // Determine how long the string is and whether it will
  510. // fit in the available buffer space. Note that the
  511. // stringLength variable includes the zero terminator.
  512. //
  513. // Get lengths and update descriptor pointers.
  514. inLength = RapDescArrayLength( InStructureDesc );
  515. outLength = RapDescStringLength( OutStructureDesc );
  516. //
  517. // Assumption - Byte arrays are never copied into strings
  518. // which cannot hold them.
  519. //
  520. NetpAssert( outLength == 0
  521. || inLength <= outLength );
  522. //
  523. // Update the in structure pointer to point after the
  524. // byte array. Determine the true length of the string
  525. // and update the number of bytes required to reflect
  526. // the variable data necessary.
  527. //
  528. InStructure += inLength;
  529. if (inUNICODE)
  530. {
  531. if( outUNICODE )
  532. {
  533. stringSize = STRLEN( (LPTSTR) stringPtr );
  534. }
  535. else
  536. {
  537. stringSize = NetpUnicodeToDBCSLen( (LPTSTR)stringPtr ) + 1;
  538. }
  539. }
  540. else
  541. {
  542. stringSize = strlen( (LPSTR) stringPtr ) + 1;
  543. }
  544. if (outUNICODE) {
  545. stringSize = STRING_SPACE_REQD( stringSize );
  546. if ( outputBufferSupplied && *StringLocation !=
  547. ROUND_DOWN_POINTER( *StringLocation, ALIGN_TCHAR )) {
  548. stringSize += sizeof(TCHAR);
  549. }
  550. if ( fixedWrite ) {
  551. OutStructure = RapPossiblyAlignPointer(
  552. OutStructure, ALIGN_LPTSTR, outNative );
  553. }
  554. } else {
  555. if ( fixedWrite ) {
  556. OutStructure = RapPossiblyAlignPointer(
  557. OutStructure, ALIGN_LPSTR, outNative );
  558. }
  559. }
  560. *BytesRequired += stringSize;
  561. IF_DEBUG(CONVERT) {
  562. NetpKdPrint(( PREFIX_NETRAP
  563. "RapConvertSingleEntry: bytes required now "
  564. FORMAT_DWORD "\n", *BytesRequired ));
  565. }
  566. if ( outputBufferSupplied ) {
  567. //
  568. // Set the location where a pointer to the output string
  569. // will be placed and update the output structure pointer
  570. // to point after the pointer to the string.
  571. //
  572. offset = (LPDWORD)OutStructure;
  573. if ( fixedWrite ) {
  574. OutStructure += RAP_POINTER_SIZE(outNative, SetOffsets);
  575. }
  576. if ( (ULONG_PTR)*StringLocation <
  577. (ULONG_PTR)nextStructureLocation + stringSize ) {
  578. //
  579. // There isn't enough space to hold the string--it
  580. // would go into the last fixed structure. Put a
  581. // NULL in the offset and don't copy over the
  582. // string.
  583. //
  584. if ( fixedWrite ) {
  585. RAP_PUT_POINTER( SetOffsets, offset, 0, outNative );
  586. }
  587. break;
  588. }
  589. //
  590. // Determine where the string will go.
  591. //
  592. *StringLocation = *StringLocation - stringSize;
  593. //
  594. // Set the offset value or the actual address in the
  595. // fixed structure. Update the fixed structure
  596. // pointer.
  597. //
  598. if ( fixedWrite ) {
  599. if ( SetOffsets ) {
  600. RapPutDword( offset,
  601. (DWORD)( *StringLocation - OutBufferStart),
  602. outNative );
  603. } else {
  604. RapPutDword_Ptr( offset, (DWORD_PTR)*StringLocation,
  605. outNative );
  606. }
  607. }
  608. //
  609. // Copy over the string.
  610. //
  611. if ( inUNICODE && outUNICODE ) {
  612. STRCPY( (LPTSTR)*StringLocation, (LPTSTR)stringPtr );
  613. } else if ( inUNICODE ) {
  614. NetpCopyWStrToStrDBCS( (LPSTR)*StringLocation,
  615. (LPTSTR)stringPtr );
  616. } else if ( outUNICODE ) {
  617. NetpCopyStrToTStr( (LPTSTR)*StringLocation,
  618. (LPSTR)stringPtr );
  619. } else {
  620. strcpy( (LPSTR)*StringLocation, (LPSTR)stringPtr );
  621. }
  622. } // if ( outputBufferSupplied )
  623. break;
  624. }
  625. default:
  626. UNSUPPORTED_COMBINATION( REM_BYTE, *(OutStructureDesc-1) );
  627. }
  628. break;
  629. case REM_BYTE_PTR: {
  630. LPBYTE bytePtr;
  631. DWORD inLength;
  632. inLength = RapDescArrayLength( InStructureDesc );
  633. NetpAssert( inLength > 0 );
  634. InStructure = RapPossiblyAlignPointer(
  635. InStructure, ALIGN_LPBYTE, inNative);
  636. //
  637. // Set up a pointer to the bytes. If the pointer stored in
  638. // the input structure is bad, find out where the bytes are
  639. // really stored.
  640. //
  641. bytePtr = RapGetPointer( InStructure, inNative, Bias );
  642. if ( MeaninglessInputPointers && bytePtr != NULL ) {
  643. bytePtr = variableInputData;
  644. variableInputData += inLength;
  645. }
  646. IF_DEBUG(CONVERT) {
  647. NetpKdPrint(( PREFIX_NETRAP
  648. "RapConvertSingleEntry: b->stuff, bytePtr="
  649. FORMAT_LPVOID "\n", (LPVOID) bytePtr ));
  650. }
  651. //
  652. // Update the InStructure pointer.
  653. //
  654. InStructure += RAP_POINTER_SIZE( inNative, FALSE );
  655. switch ( *OutStructureDesc++ ) {
  656. case REM_BYTE: {
  657. DWORD outLength;
  658. //
  659. // Convert a indirect array of bytes to a fixed byte
  660. // array.
  661. //
  662. outLength = RapDescArrayLength( OutStructureDesc );
  663. //
  664. // Assumption - the array sizes should match.
  665. //
  666. NetpAssert( inLength == outLength );
  667. //
  668. // Copy the buffer. If the source pointer is NULL, we can
  669. // just fill the output with zeroes.
  670. //
  671. if ( fixedWrite ) {
  672. for ( ; outLength > 0; outLength-- ) {
  673. *OutStructure++ = ( bytePtr ? *bytePtr++ : (BYTE)0 );
  674. }
  675. }
  676. break;
  677. }
  678. case REM_BYTE_PTR: {
  679. //
  680. // The input has a pointer to a number of bytes, the output
  681. // is the same. Copy the bytes.
  682. //
  683. DWORD outLength;
  684. LPDWORD offset;
  685. outLength = RapDescArrayLength( OutStructureDesc );
  686. //
  687. // Assumption - the array sizes should match.
  688. //
  689. NetpAssert( inLength == outLength );
  690. //
  691. // Align output pointer if necessary.
  692. //
  693. if ( fixedWrite ) {
  694. OutStructure = RapPossiblyAlignPointer(
  695. OutStructure, ALIGN_LPBYTE, outNative );
  696. }
  697. //
  698. // If the byte pointer is NULL, just copy the NULL
  699. // pointer and update other pointers.
  700. //
  701. if ( bytePtr == NULL ) {
  702. if ( fixedWrite ) {
  703. RAP_PUT_POINTER(
  704. SetOffsets,
  705. (LPDWORD)OutStructure,
  706. 0,
  707. outNative );
  708. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  709. }
  710. break;
  711. }
  712. //
  713. // Update bytes required.
  714. //
  715. *BytesRequired += outLength;
  716. IF_DEBUG(CONVERT) {
  717. NetpKdPrint(( PREFIX_NETRAP
  718. "RapConvertSingleEntry: bytes required now "
  719. FORMAT_DWORD "\n", *BytesRequired ));
  720. }
  721. //
  722. // Determine whether the data will fit in the available
  723. // buffer space.
  724. //
  725. if ( outputBufferSupplied ) {
  726. offset = (LPDWORD) OutStructure;
  727. if ( fixedWrite ) {
  728. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  729. }
  730. IF_DEBUG(CONVERT) {
  731. NetpKdPrint(( PREFIX_NETRAP
  732. "RapConvertSingleEntry: b->b, "
  733. "offset after alignment is " FORMAT_LPVOID "\n",
  734. (LPVOID) offset ));
  735. }
  736. if ( (ULONG_PTR)*StringLocation <
  737. (ULONG_PTR)nextStructureLocation + outLength ) {
  738. //
  739. // There isn't enough space to hold the data--it
  740. // would go into the last fixed structure. Put a
  741. // NULL in the offset and don't copy over the
  742. // data.
  743. //
  744. if ( fixedWrite ) {
  745. RAP_PUT_POINTER( SetOffsets, offset, 0, outNative );
  746. }
  747. break;
  748. }
  749. //
  750. // Determine where the bytes will go.
  751. //
  752. IF_DEBUG(CONVERT) {
  753. NetpKdPrint(( PREFIX_NETRAP
  754. "RapConvertSingleEntry: b->b, "
  755. "*StringLocation=" FORMAT_LPVOID "\n",
  756. (LPVOID) *StringLocation ));
  757. }
  758. *StringLocation = *StringLocation - outLength;
  759. //
  760. // Set the offset value or the actual address in the
  761. // fixed structure. Update the fixed structure
  762. // pointer.
  763. //
  764. if ( fixedWrite ) {
  765. if ( SetOffsets ) {
  766. IF_DEBUG(CONVERT) {
  767. NetpKdPrint(( PREFIX_NETRAP
  768. "RapConvertSingleEntry: b->b, "
  769. "setting offset " FORMAT_HEX_DWORD "\n",
  770. (DWORD)( *StringLocation - OutBufferStart )));
  771. }
  772. RapPutDword( offset,
  773. (DWORD)( *StringLocation - OutBufferStart),
  774. outNative );
  775. } else {
  776. IF_DEBUG(CONVERT) {
  777. NetpKdPrint(( PREFIX_NETRAP
  778. "RapConvertSingleEntry: b->b, "
  779. "setting pointer " FORMAT_POINTER
  780. "\n", (DWORD_PTR) (*StringLocation) ));
  781. }
  782. RapPutDword_Ptr( offset,
  783. (DWORD_PTR)( *StringLocation ),
  784. outNative);
  785. }
  786. //
  787. // Copy over the bytes.
  788. //
  789. memcpy(
  790. (LPBYTE)*StringLocation,
  791. bytePtr,
  792. inLength
  793. );
  794. }
  795. } // if ( outputBufferSupplied )
  796. break;
  797. }
  798. case REM_IGNORE :
  799. //
  800. // The input is an ignored pad.
  801. //
  802. break;
  803. default:
  804. UNSUPPORTED_COMBINATION( REM_BYTE_PTR, *(OutStructureDesc-1) );
  805. }
  806. break;
  807. }
  808. case REM_ASCIZ:
  809. case REM_ASCIZ_TRUNCATABLE: {
  810. LPSTR stringPtr;
  811. InStructure = RapPossiblyAlignPointer(
  812. InStructure, ALIGN_LPSTR, inNative);
  813. //
  814. // Set up a pointer to the string. If the pointer stored in
  815. // the input structure is nonzero and we have meaningless input,
  816. // pointers, find out where the string is really stored.
  817. // Even if the input pointers are "meaningless" a value
  818. // of NULL is relevant.
  819. //
  820. stringPtr = RapGetPointer( InStructure, inNative, Bias );
  821. if ( MeaninglessInputPointers && stringPtr != NULL ) {
  822. stringPtr = variableInputData;
  823. variableInputData += strlen( (LPSTR) variableInputData ) + 1;
  824. }
  825. IF_DEBUG(CONVERT) {
  826. NetpKdPrint(( PREFIX_NETRAP
  827. "RapConvertSingleEntry: z->stuff, stringPtr="
  828. FORMAT_LPVOID "\n", (LPVOID) stringPtr ));
  829. }
  830. //
  831. // Update the InStructure pointer
  832. // Take into account the fact that on Win64, pointers are 8 bytes, but Non-Native ones are 4 bytes
  833. //
  834. InStructure += RAP_POINTER_SIZE( inNative, FALSE );
  835. //
  836. // Fill in the output based on the descriptor.
  837. //
  838. switch ( *OutStructureDesc++ ) {
  839. case REM_BYTE: {
  840. DWORD inSize, outSize, stringSize;
  841. //
  842. // Align output structure.
  843. //
  844. if (fixedWrite && outUNICODE) {
  845. OutStructure = RapPossiblyAlignPointer(
  846. OutStructure, ALIGN_TCHAR, inNative );
  847. }
  848. //
  849. // Convert a zero-terminated string to a set number of
  850. // bytes.
  851. //
  852. inSize = RapDescStringLength( InStructureDesc );
  853. outSize = RapDescArrayLength( OutStructureDesc );
  854. //
  855. // Make sure that if the string is not truncatable,
  856. // the destination is large enough to hold it.
  857. //
  858. if ( stringPtr != NULL ) {
  859. if (inUNICODE) {
  860. stringSize = STRSIZE( (LPTSTR)stringPtr );
  861. if (!outUNICODE) {
  862. stringSize = NetpUnicodeToDBCSLen( (LPTSTR)stringPtr )+1;
  863. }
  864. } else {
  865. stringSize = strlen( (LPSTR)stringPtr ) + 1;
  866. if (outUNICODE) {
  867. stringSize = stringSize * sizeof(WCHAR);
  868. }
  869. }
  870. } else {
  871. stringSize = 0;
  872. }
  873. if ( stringSize > outSize ) {
  874. if ( currentInStructureDesc == REM_ASCIZ ) {
  875. IF_DEBUG(CONVERT) {
  876. NetpKdPrint(( PREFIX_NETRAP
  877. "RapConvertSingleEntry: "
  878. "String too long\n" ));
  879. }
  880. return ERROR_INVALID_PARAMETER;
  881. } else {
  882. IF_DEBUG(CONVERT) {
  883. NetpKdPrint(( PREFIX_NETRAP
  884. "RapConvertSingleEntry: "
  885. "String truncated\n" ));
  886. }
  887. }
  888. }
  889. //
  890. // Copy either the entire string or the number of bytes
  891. // that will fit, whichever is less. Make sure that
  892. // we leave at least one byte for a zero terminator.
  893. //
  894. if ( fixedWrite && stringPtr != NULL ) {
  895. if ( outUNICODE ) {
  896. LPTSTR Source;
  897. if ( !inUNICODE ) {
  898. Source = NetpMemoryAllocate(
  899. STRING_SPACE_REQD( stringSize ));
  900. if ( Source == NULL ) {
  901. return NERR_NoRoom;
  902. }
  903. NetpCopyStrToTStr( Source,
  904. (LPSTR)stringPtr );
  905. stringPtr = (LPBYTE)Source;
  906. }
  907. for ( ;
  908. outSize > 1 && *(TCHAR *)stringPtr != TCHAR_EOS;
  909. outSize -= sizeof(TCHAR) ) {
  910. *(TCHAR *)OutStructure = *(TCHAR *)stringPtr;
  911. OutStructure += sizeof(TCHAR);
  912. stringPtr += sizeof(TCHAR);
  913. }
  914. if ( !inUNICODE) {
  915. NetpMemoryFree( Source );
  916. }
  917. } else {
  918. LPSTR Source;
  919. if ( inUNICODE ) {
  920. Source = NetpMemoryAllocate( stringSize );
  921. if ( Source == NULL ) {
  922. return NERR_NoRoom;
  923. }
  924. NetpCopyWStrToStrDBCS( Source,
  925. (LPTSTR)stringPtr );
  926. stringPtr = (LPBYTE)Source;
  927. }
  928. for ( ;
  929. outSize > 1 && *stringPtr != '\0';
  930. outSize-- ) {
  931. *OutStructure++ = (BYTE) *stringPtr++;
  932. }
  933. if ( inUNICODE ) {
  934. NetpMemoryFree( Source );
  935. }
  936. }
  937. }
  938. //
  939. // Fill out the remaining bytes with zeros.
  940. //
  941. if ( fixedWrite ) {
  942. while ( outSize-- > 0 ) {
  943. *OutStructure++ = '\0';
  944. }
  945. }
  946. break;
  947. }
  948. case REM_IGNORE:
  949. //
  950. // The input is an ignored field. Instructure is already
  951. // updated, so just skip over the string length limit.
  952. //
  953. (void) RapDescStringLength( InStructureDesc );
  954. break;
  955. case REM_ASCIZ:
  956. case REM_ASCIZ_TRUNCATABLE: {
  957. //
  958. // The input has a string pointer, the output gets an
  959. // offset in the fixed structure to a later location
  960. // which gets the actual string.
  961. //
  962. LPDWORD offset;
  963. DWORD inLength, outLength;
  964. DWORD stringLength;
  965. DWORD stringSize;
  966. // Get lengths and update descriptor pointers.
  967. inLength = RapDescStringLength( InStructureDesc );
  968. outLength = RapDescStringLength( OutStructureDesc );
  969. if ( fixedWrite ) {
  970. OutStructure = RapPossiblyAlignPointer(
  971. OutStructure, ALIGN_LPSTR, outNative );
  972. }
  973. //
  974. // If the string pointer is NULL, just copy the NULL
  975. // pointer and update other pointers.
  976. //
  977. if ( stringPtr == NULL ) {
  978. if ( fixedWrite ) {
  979. RAP_PUT_POINTER(
  980. SetOffsets,
  981. (LPDWORD)OutStructure,
  982. 0,
  983. outNative );
  984. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  985. }
  986. break;
  987. }
  988. //
  989. // If the string does not fit in the destination and the
  990. // string in not truncatable, then fail.
  991. //
  992. if (inUNICODE) {
  993. if( outUNICODE )
  994. {
  995. stringLength = STRLEN( (LPTSTR)stringPtr ) + 1;
  996. }
  997. else
  998. {
  999. stringLength = NetpUnicodeToDBCSLen( (LPTSTR)stringPtr ) + 1;
  1000. }
  1001. } else {
  1002. stringLength = strlen( (LPSTR)stringPtr ) + 1;
  1003. }
  1004. if ( outLength > 0
  1005. && stringLength > outLength ) {
  1006. if ( currentInStructureDesc == REM_ASCIZ ) {
  1007. IF_DEBUG(CONVERT) {
  1008. NetpKdPrint(( PREFIX_NETRAP
  1009. "RapConvertSingleEntry: "
  1010. "String too long\n" ));
  1011. }
  1012. return ERROR_INVALID_PARAMETER;
  1013. } else {
  1014. IF_DEBUG(CONVERT) {
  1015. NetpKdPrint(( PREFIX_NETRAP
  1016. "RapConvertSingleEntry: "
  1017. "String truncated\n" ));
  1018. }
  1019. }
  1020. stringLength = outLength;
  1021. }
  1022. //
  1023. // Determine how long the string is and whether it will
  1024. // fit in the available buffer space. Note that the
  1025. // stringLength variable includes the zero terminator.
  1026. //
  1027. if (outUNICODE) {
  1028. stringSize = STRING_SPACE_REQD(stringLength);
  1029. if ( outputBufferSupplied && *StringLocation !=
  1030. ROUND_DOWN_POINTER( *StringLocation, ALIGN_TCHAR )) {
  1031. stringSize++;
  1032. }
  1033. } else {
  1034. stringSize = stringLength;
  1035. }
  1036. *BytesRequired += stringSize;
  1037. IF_DEBUG(CONVERT) {
  1038. NetpKdPrint(( PREFIX_NETRAP
  1039. "RapConvertSingleEntry: bytes required now "
  1040. FORMAT_DWORD "\n", *BytesRequired ));
  1041. }
  1042. if ( outputBufferSupplied ) {
  1043. offset = (LPDWORD) OutStructure;
  1044. if ( fixedWrite ) {
  1045. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  1046. }
  1047. IF_DEBUG(CONVERT) {
  1048. NetpKdPrint(( PREFIX_NETRAP
  1049. "RapConvertSingleEntry: z->z, "
  1050. "offset after alignment is " FORMAT_LPVOID "\n",
  1051. (LPVOID) offset ));
  1052. }
  1053. if ( (ULONG_PTR)*StringLocation <
  1054. (ULONG_PTR)nextStructureLocation + stringSize ) {
  1055. //
  1056. // There isn't enough space to hold the string--it
  1057. // would go into the last fixed structure. Put a
  1058. // NULL in the offset and don't copy over the
  1059. // string.
  1060. //
  1061. if ( fixedWrite ) {
  1062. RAP_PUT_POINTER( SetOffsets, offset, 0, outNative );
  1063. }
  1064. break;
  1065. }
  1066. //
  1067. // Determine where the string will go.
  1068. //
  1069. IF_DEBUG(CONVERT) {
  1070. NetpKdPrint(( PREFIX_NETRAP
  1071. "RapConvertSingleEntry: z->z, "
  1072. "*StringLocation=" FORMAT_LPVOID "\n",
  1073. (LPVOID) *StringLocation ));
  1074. }
  1075. *StringLocation = *StringLocation - stringSize;
  1076. //
  1077. // Set the offset value or the actual address in the
  1078. // fixed structure. Update the fixed structure
  1079. // pointer.
  1080. //
  1081. if ( fixedWrite ) {
  1082. if ( SetOffsets ) {
  1083. IF_DEBUG(CONVERT) {
  1084. NetpKdPrint(( PREFIX_NETRAP
  1085. "RapConvertSingleEntry: z->z, "
  1086. "setting offset " FORMAT_HEX_DWORD "\n",
  1087. (DWORD)( *StringLocation - OutBufferStart )));
  1088. }
  1089. RapPutDword( offset,
  1090. (DWORD)( *StringLocation - OutBufferStart),
  1091. outNative );
  1092. } else {
  1093. IF_DEBUG(CONVERT) {
  1094. NetpKdPrint(( PREFIX_NETRAP
  1095. "RapConvertSingleEntry: z->z, "
  1096. "setting pointer " FORMAT_POINTER
  1097. "\n", (DWORD_PTR) (*StringLocation) ));
  1098. }
  1099. RapPutDword_Ptr( offset,
  1100. (DWORD_PTR)( *StringLocation ),
  1101. outNative);
  1102. }
  1103. //
  1104. // Copy over the string, truncating if necessary.
  1105. //
  1106. if ( inUNICODE && outUNICODE ) {
  1107. STRNCPY( (LPTSTR)*StringLocation, (LPTSTR)stringPtr,
  1108. stringLength - 1 );
  1109. *(LPTSTR)( StringLocation
  1110. + stringSize - sizeof(TCHAR)) = TCHAR_EOS;
  1111. } else if ( inUNICODE ) {
  1112. LPTSTR Source;
  1113. Source = NetpMemoryAllocate(
  1114. STRING_SPACE_REQD( stringLength ));
  1115. if ( Source == NULL ) {
  1116. return NERR_NoRoom;
  1117. }
  1118. STRNCPY( Source, (LPTSTR)stringPtr,
  1119. stringLength - 1 );
  1120. Source[stringLength - 1] = TCHAR_EOS;
  1121. NetpCopyWStrToStrDBCS( (LPSTR)*StringLocation,
  1122. Source );
  1123. NetpMemoryFree( Source );
  1124. } else if ( outUNICODE ) {
  1125. LPSTR Source;
  1126. Source = NetpMemoryAllocate( stringLength );
  1127. if ( Source == NULL ) {
  1128. return NERR_NoRoom;
  1129. }
  1130. strncpy( Source, (LPSTR)stringPtr,
  1131. stringLength - 1 );
  1132. Source[stringLength - 1] = '\0';
  1133. NetpCopyStrToTStr( (LPTSTR)*StringLocation,
  1134. Source );
  1135. NetpMemoryFree( Source );
  1136. } else {
  1137. strncpy( (LPSTR)*StringLocation, (LPSTR)stringPtr,
  1138. stringLength - 1 );
  1139. (*StringLocation)[stringLength - 1] = '\0';
  1140. }
  1141. }
  1142. } // if ( outputBufferSupplied )
  1143. break;
  1144. }
  1145. case REM_BYTE_PTR: {
  1146. //
  1147. // The input has a byte pointer, the output gets an offset
  1148. // in the fixed structure to a later location which gets
  1149. // the actual bytes.
  1150. //
  1151. LPDWORD offset;
  1152. DWORD inLength, outLength;
  1153. DWORD stringLength;
  1154. // Get lengths and update descriptor pointers.
  1155. inLength = RapDescStringLength( InStructureDesc );
  1156. outLength = RapDescArrayLength( OutStructureDesc );
  1157. if ( fixedWrite ) {
  1158. OutStructure = RapPossiblyAlignPointer(
  1159. OutStructure, ALIGN_LPSTR, outNative );
  1160. }
  1161. //
  1162. // If the string does not fit in the destination and the
  1163. // string is not truncatable, then fail.
  1164. //
  1165. stringLength = strlen( (LPSTR)stringPtr ) + 1;
  1166. if ( stringLength > outLength ) {
  1167. if ( currentInStructureDesc == REM_ASCIZ ) {
  1168. IF_DEBUG(CONVERT) {
  1169. NetpKdPrint(( PREFIX_NETRAP
  1170. "RapConvertSingleEntry: "
  1171. "String too long\n" ));
  1172. }
  1173. return ERROR_INVALID_PARAMETER;
  1174. } else {
  1175. IF_DEBUG(CONVERT) {
  1176. NetpKdPrint(( PREFIX_NETRAP
  1177. "RapConvertSingleEntry: "
  1178. "String truncated\n" ));
  1179. }
  1180. }
  1181. stringLength = outLength;
  1182. }
  1183. //
  1184. //
  1185. // If the string pointer is NULL, just copy the NULL value
  1186. // and update pointers.
  1187. //
  1188. if ( stringPtr == NULL ) {
  1189. if ( fixedWrite ) {
  1190. RAP_PUT_POINTER(
  1191. SetOffsets,
  1192. (LPDWORD)OutStructure,
  1193. 0,
  1194. outNative );
  1195. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  1196. }
  1197. break;
  1198. }
  1199. //
  1200. // Determine how long the string and array are, and whether
  1201. // the array will fit in the available buffer space.
  1202. // The stringLength variable includes the zero terminator.
  1203. //
  1204. *BytesRequired += outLength;
  1205. IF_DEBUG(CONVERT) {
  1206. NetpKdPrint(( PREFIX_NETRAP
  1207. "RapConvertSingleEntry: bytes required now "
  1208. FORMAT_DWORD "\n", *BytesRequired ));
  1209. }
  1210. if ( outputBufferSupplied ) {
  1211. offset = (LPDWORD)OutStructure;
  1212. if ( fixedWrite ) {
  1213. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  1214. }
  1215. if ( (ULONG_PTR)*StringLocation <
  1216. (ULONG_PTR)nextStructureLocation + outLength ) {
  1217. //
  1218. // There isn't enough space to hold the array--it
  1219. // would go into the last fixed structure. Put a
  1220. // NULL in the offset and don't copy over the
  1221. // string.
  1222. //
  1223. if ( fixedWrite ) {
  1224. RAP_PUT_POINTER( SetOffsets, offset, 0, outNative );
  1225. }
  1226. break;
  1227. }
  1228. //
  1229. // Determine where the array will go.
  1230. //
  1231. *StringLocation = *StringLocation - outLength;
  1232. //
  1233. // Set the offset value or the actual address in the
  1234. // fixed structure. Update the fixed structure
  1235. // pointer.
  1236. //
  1237. if ( fixedWrite ) {
  1238. if ( SetOffsets ) {
  1239. RapPutDword(
  1240. offset,
  1241. (DWORD)( *StringLocation - OutBufferStart ),
  1242. outNative );
  1243. } else {
  1244. RapPutDword_Ptr(
  1245. offset,
  1246. (DWORD_PTR)( *StringLocation ),
  1247. outNative );
  1248. }
  1249. }
  1250. //
  1251. // Copy over the string. If the source string is smaller
  1252. // than the target array, only copy the string length.
  1253. // Otherwise, copy as many bytes as necessary to fill the
  1254. // array. Note that truncated strings will not be
  1255. // null terminated.
  1256. //
  1257. (void)MEMCPY(
  1258. *StringLocation,
  1259. stringPtr,
  1260. stringLength );
  1261. } // if ( outputBufferSupplied )
  1262. break;
  1263. }
  1264. default:
  1265. UNSUPPORTED_COMBINATION( REM_ASCIZ, *(OutStructureDesc-1) );
  1266. }
  1267. break;
  1268. }
  1269. case REM_AUX_NUM:
  1270. //
  1271. // 16-bit auxiliary data count.
  1272. //
  1273. switch ( *OutStructureDesc++ ) {
  1274. case REM_AUX_NUM:
  1275. //
  1276. // No conversion required.
  1277. //
  1278. if ( fixedWrite ) {
  1279. RapPutWord(
  1280. (LPWORD)OutStructure,
  1281. RapGetWord( InStructure, inNative ),
  1282. outNative );
  1283. OutStructure += sizeof(WORD);
  1284. }
  1285. InStructure += sizeof(WORD);
  1286. break;
  1287. case REM_AUX_NUM_DWORD:
  1288. //
  1289. // Convert 16-bit to 32-bit
  1290. //
  1291. if ( fixedWrite ) {
  1292. RapPutDword(
  1293. (LPDWORD)OutStructure,
  1294. (DWORD)RapGetWord( InStructure, inNative ),
  1295. outNative );
  1296. OutStructure += sizeof(DWORD);
  1297. }
  1298. InStructure += sizeof(WORD);
  1299. break;
  1300. default:
  1301. UNSUPPORTED_COMBINATION( REM_AUX_NUM, *(OutStructureDesc-1) );
  1302. }
  1303. break;
  1304. case REM_AUX_NUM_DWORD:
  1305. //
  1306. // 32-bit auxiliary data count.
  1307. //
  1308. switch ( *OutStructureDesc++ ) {
  1309. case REM_AUX_NUM_DWORD:
  1310. //
  1311. // No conversion required.
  1312. //
  1313. if ( fixedWrite ) {
  1314. RapPutWord(
  1315. (LPWORD)OutStructure,
  1316. RapGetWord( InStructure, inNative ),
  1317. outNative );
  1318. OutStructure += sizeof(DWORD);
  1319. }
  1320. InStructure += sizeof(DWORD);
  1321. break;
  1322. case REM_AUX_NUM:
  1323. //
  1324. // Convert 32-bit to 16-bit
  1325. //
  1326. if ( fixedWrite ) {
  1327. RapPutWord(
  1328. (LPWORD)OutStructure,
  1329. (WORD)RapGetWord( InStructure, inNative ),
  1330. outNative );
  1331. OutStructure += sizeof(WORD);
  1332. }
  1333. InStructure += sizeof(DWORD);
  1334. break;
  1335. default:
  1336. UNSUPPORTED_COMBINATION( REM_AUX_NUM_DWORD,
  1337. *(OutStructureDesc-1) );
  1338. }
  1339. break;
  1340. case REM_NULL_PTR:
  1341. //
  1342. // Convert a null pointer to another type.
  1343. //
  1344. switch ( *OutStructureDesc++ ) {
  1345. case REM_NULL_PTR:
  1346. case REM_ASCIZ: {
  1347. //
  1348. // Convert a null pointer to a string pointer.
  1349. //
  1350. (void) RapDescStringLength(
  1351. OutStructureDesc ); // updated by this call
  1352. if ( fixedWrite ) {
  1353. RAP_PUT_POINTER(
  1354. SetOffsets,
  1355. (LPDWORD)OutStructure,
  1356. 0,
  1357. outNative );
  1358. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  1359. }
  1360. InStructure += RAP_POINTER_SIZE( inNative, FALSE );
  1361. break;
  1362. }
  1363. case REM_IGNORE:
  1364. //
  1365. // The input is an ignored field. Do nothing.
  1366. //
  1367. break;
  1368. default:
  1369. UNSUPPORTED_COMBINATION( REM_NULL_PTR, *(OutStructureDesc-1) );
  1370. }
  1371. break;
  1372. case REM_WORD: {
  1373. //
  1374. // Convert a word to another numerical data type.
  1375. //
  1376. WORD inData = RapGetWord( InStructure, inNative );
  1377. InStructure += sizeof(WORD);
  1378. NetpAssert( !DESC_CHAR_IS_DIGIT( *OutStructureDesc ) );
  1379. switch ( *OutStructureDesc++ ) {
  1380. case REM_BYTE:
  1381. if ( fixedWrite ) {
  1382. *OutStructure++ = (BYTE)(inData & 0xFF);
  1383. }
  1384. break;
  1385. case REM_WORD: {
  1386. if ( fixedWrite ) {
  1387. LPWORD outData = (LPWORD)OutStructure;
  1388. RapPutWord( outData, inData, outNative );
  1389. OutStructure = OutStructure + sizeof(WORD);
  1390. }
  1391. break;
  1392. }
  1393. case REM_DWORD: {
  1394. if ( fixedWrite ) {
  1395. LPDWORD outData = (LPDWORD)OutStructure;
  1396. RapPutDword( outData, (DWORD)inData, outNative );
  1397. OutStructure = OutStructure + sizeof(DWORD);
  1398. }
  1399. break;
  1400. }
  1401. case REM_SIGNED_DWORD: {
  1402. if ( fixedWrite ) {
  1403. LPDWORD outData = (LPDWORD)OutStructure;
  1404. DWORD data = (DWORD)inData;
  1405. if ( data & 0x8000 ) {
  1406. data |= 0xFFFF0000;
  1407. }
  1408. RapPutDword( outData, data, outNative );
  1409. OutStructure = OutStructure + sizeof(DWORD);
  1410. }
  1411. break;
  1412. }
  1413. case REM_IGNORE :
  1414. //
  1415. // The input is an ignored pad. Just update pointers.
  1416. //
  1417. break;
  1418. default:
  1419. UNSUPPORTED_COMBINATION( REM_WORD, *(OutStructureDesc-1) );
  1420. }
  1421. break;
  1422. }
  1423. case REM_DWORD:
  1424. case REM_SIGNED_DWORD: {
  1425. //
  1426. // The input is a longword (four bytes), the output will be
  1427. // a numerical data type.
  1428. //
  1429. // !!! may need support for doubleword arrays
  1430. DWORD inData;
  1431. InStructure = RapPossiblyAlignPointer(
  1432. InStructure, ALIGN_DWORD, inNative);
  1433. inData = RapGetDword( InStructure, inNative );
  1434. NetpAssert( !DESC_CHAR_IS_DIGIT( *OutStructureDesc ) );
  1435. InStructure += sizeof(DWORD);
  1436. switch ( *OutStructureDesc++ ) {
  1437. case REM_BYTE:
  1438. if ( fixedWrite ) {
  1439. *OutStructure++ = (BYTE)(inData & 0xFF);
  1440. }
  1441. break;
  1442. case REM_WORD: {
  1443. if ( fixedWrite ) {
  1444. LPWORD outData = RapPossiblyAlignPointer(
  1445. (LPWORD)OutStructure, ALIGN_WORD, outNative);
  1446. RapPutWord( outData, (WORD)(inData & 0xFFFF), outNative );
  1447. OutStructure = OutStructure + sizeof(WORD);
  1448. }
  1449. break;
  1450. }
  1451. case REM_DWORD:
  1452. case REM_SIGNED_DWORD: {
  1453. if ( fixedWrite ) {
  1454. LPDWORD outData = RapPossiblyAlignPointer(
  1455. (LPDWORD)OutStructure, ALIGN_DWORD, outNative);
  1456. RapPutDword( outData, inData, outNative );
  1457. OutStructure = OutStructure + sizeof(DWORD);
  1458. }
  1459. break;
  1460. }
  1461. case REM_IGNORE :
  1462. //
  1463. // The input is an ignored pad. Just update pointers.
  1464. //
  1465. break;
  1466. default:
  1467. UNSUPPORTED_COMBINATION( REM_DWORD, *(OutStructureDesc-1) );
  1468. }
  1469. break;
  1470. }
  1471. case REM_IGNORE :
  1472. //
  1473. // The next location in the output is an irrelevant field.
  1474. // Skip over it.
  1475. //
  1476. switch( *OutStructureDesc++ ) {
  1477. case REM_BYTE:
  1478. if (OutStructure != NULL && fixedWrite) {
  1479. OutStructure += RapDescArrayLength( OutStructureDesc );
  1480. } else {
  1481. //
  1482. // We need this so that it skips the numbers
  1483. //
  1484. (void) RapDescArrayLength( OutStructureDesc );
  1485. }
  1486. break;
  1487. case REM_WORD:
  1488. if (OutStructure != NULL && fixedWrite) {
  1489. OutStructure += sizeof(WORD) *
  1490. RapDescArrayLength( OutStructureDesc );
  1491. }
  1492. break;
  1493. case REM_DWORD:
  1494. if (OutStructure != NULL && fixedWrite) {
  1495. OutStructure += sizeof(DWORD) *
  1496. RapDescArrayLength( OutStructureDesc );
  1497. }
  1498. break;
  1499. case REM_IGNORE:
  1500. break;
  1501. case REM_BYTE_PTR:
  1502. (void) RapAsciiToDecimal( &OutStructureDesc );
  1503. /* FALLTHROUGH */
  1504. case REM_NULL_PTR:
  1505. if (OutStructure != NULL && fixedWrite) {
  1506. OutStructure += sizeof(LPSTR);
  1507. }
  1508. break;
  1509. case REM_ASCIZ:
  1510. (void) RapDescStringLength(
  1511. OutStructureDesc ); // will be updated
  1512. if (OutStructure != NULL && fixedWrite) {
  1513. OutStructure += sizeof(LPSTR);
  1514. }
  1515. break;
  1516. case REM_EPOCH_TIME_LOCAL:
  1517. if (OutStructure != NULL && fixedWrite) {
  1518. OutStructure += sizeof(DWORD);
  1519. }
  1520. break;
  1521. default:
  1522. UNSUPPORTED_COMBINATION( REM_IGNORE, *(OutStructureDesc-1) );
  1523. }
  1524. break;
  1525. case REM_SEND_LENBUF: {
  1526. LPBYTE bytePtr;
  1527. DWORD length;
  1528. InStructure = RapPossiblyAlignPointer(
  1529. InStructure, ALIGN_LPBYTE, inNative);
  1530. //
  1531. // Set up a pointer to the bytes. If the pointer stored in
  1532. // the input structure is bad, find out where the bytes are
  1533. // really stored.
  1534. //
  1535. bytePtr = RapGetPointer( InStructure, inNative, Bias );
  1536. if ( MeaninglessInputPointers && bytePtr != NULL ) {
  1537. bytePtr = variableInputData;
  1538. }
  1539. IF_DEBUG(CONVERT) {
  1540. NetpKdPrint(( PREFIX_NETRAP
  1541. "RapConvertSingleEntry: b->stuff, bytePtr="
  1542. FORMAT_LPVOID "\n", (LPVOID) bytePtr ));
  1543. }
  1544. //
  1545. // Get the length of the buffer, if we can. Also update pointers
  1546. // if necessary.
  1547. //
  1548. if ( bytePtr != NULL ) {
  1549. length = (DWORD)SmbGetUshort( (LPWORD)bytePtr );
  1550. if ( MeaninglessInputPointers ) {
  1551. variableInputData += length;
  1552. }
  1553. } else {
  1554. length = 0;
  1555. }
  1556. //
  1557. // Update the InStructure pointer.
  1558. //
  1559. InStructure += RAP_POINTER_SIZE( inNative, FALSE );
  1560. switch ( *OutStructureDesc++ ) {
  1561. case REM_SEND_LENBUF: {
  1562. //
  1563. // The input has a pointer to a variable size buffer, the
  1564. // output is the same. Copy the bytes.
  1565. //
  1566. LPDWORD offset;
  1567. //
  1568. // Align output pointer if necessary.
  1569. //
  1570. if ( fixedWrite ) {
  1571. OutStructure = RapPossiblyAlignPointer(
  1572. OutStructure, ALIGN_LPBYTE, outNative );
  1573. }
  1574. //
  1575. // If the byte pointer is NULL, just copy the NULL
  1576. // pointer and update other pointers.
  1577. //
  1578. if ( bytePtr == NULL ) {
  1579. if ( fixedWrite ) {
  1580. RAP_PUT_POINTER(
  1581. SetOffsets,
  1582. (LPDWORD)OutStructure,
  1583. 0,
  1584. outNative );
  1585. OutStructure += RAP_POINTER_SIZE( outNative, SetOffsets );
  1586. }
  1587. break;
  1588. }
  1589. //
  1590. // Update bytes required.
  1591. //
  1592. *BytesRequired += length;
  1593. IF_DEBUG(CONVERT) {
  1594. NetpKdPrint(( PREFIX_NETRAP
  1595. "RapConvertSingleEntry: bytes required now "
  1596. FORMAT_DWORD "\n", *BytesRequired ));
  1597. }
  1598. //
  1599. // Determine whether the data will fit in the available
  1600. // buffer space.
  1601. //
  1602. if ( outputBufferSupplied ) {
  1603. offset = (LPDWORD) OutStructure;
  1604. if ( fixedWrite ) {
  1605. OutStructure += sizeof(LPBYTE);
  1606. }
  1607. IF_DEBUG(CONVERT) {
  1608. NetpKdPrint(( PREFIX_NETRAP
  1609. "RapConvertSingleEntry: l->l, "
  1610. "offset after alignment is " FORMAT_LPVOID "\n",
  1611. (LPVOID) offset ));
  1612. }
  1613. if ( (ULONG_PTR)*StringLocation <
  1614. (ULONG_PTR)nextStructureLocation + length ) {
  1615. //
  1616. // There isn't enough space to hold the data--it
  1617. // would go into the last fixed structure. Put a
  1618. // NULL in the offset and don't copy over the
  1619. // data.
  1620. //
  1621. if ( fixedWrite ) {
  1622. RAP_PUT_POINTER( SetOffsets, offset, 0, outNative );
  1623. }
  1624. break;
  1625. }
  1626. //
  1627. // Determine where the buffer will go.
  1628. //
  1629. IF_DEBUG(CONVERT) {
  1630. NetpKdPrint(( PREFIX_NETRAP
  1631. "RapConvertSingleEntry: l->l, "
  1632. "*StringLocation=" FORMAT_LPVOID "\n",
  1633. (LPVOID) *StringLocation ));
  1634. }
  1635. *StringLocation = *StringLocation - length;
  1636. //
  1637. // Set the offset value or the actual address in the
  1638. // fixed structure. Update the fixed structure
  1639. // pointer.
  1640. //
  1641. if ( fixedWrite ) {
  1642. if ( SetOffsets ) {
  1643. IF_DEBUG(CONVERT) {
  1644. NetpKdPrint(( PREFIX_NETRAP
  1645. "RapConvertSingleEntry: l->l, "
  1646. "setting offset " FORMAT_HEX_DWORD "\n",
  1647. (DWORD)( *StringLocation - OutBufferStart )));
  1648. }
  1649. RapPutDword( offset,
  1650. (DWORD)( *StringLocation - OutBufferStart),
  1651. outNative );
  1652. } else {
  1653. IF_DEBUG(CONVERT) {
  1654. NetpKdPrint(( PREFIX_NETRAP
  1655. "RapConvertSingleEntry: l->l, "
  1656. "setting pointer " FORMAT_POINTER
  1657. "\n", (DWORD_PTR) (*StringLocation) ));
  1658. }
  1659. RapPutDword_Ptr( offset,
  1660. (DWORD_PTR)( *StringLocation ),
  1661. outNative);
  1662. }
  1663. //
  1664. // Copy over the bytes.
  1665. //
  1666. memcpy(
  1667. (LPBYTE)*StringLocation,
  1668. bytePtr,
  1669. length
  1670. );
  1671. }
  1672. } // if ( outputBufferSupplied )
  1673. break;
  1674. }
  1675. case REM_IGNORE :
  1676. //
  1677. // The input is an ignored pad.
  1678. //
  1679. break;
  1680. default:
  1681. UNSUPPORTED_COMBINATION( REM_SEND_LENBUF,
  1682. *(OutStructureDesc-1) );
  1683. }
  1684. break;
  1685. }
  1686. case REM_EPOCH_TIME_GMT: {
  1687. //
  1688. // The input is a longword (four bytes), the output will be
  1689. // a numerical data type.
  1690. //
  1691. DWORD gmtTime, localTime;
  1692. InStructure = RapPossiblyAlignPointer(
  1693. InStructure, ALIGN_DWORD, inNative);
  1694. gmtTime = RapGetDword( InStructure, inNative );
  1695. NetpAssert( !DESC_CHAR_IS_DIGIT( *OutStructureDesc ) );
  1696. InStructure += sizeof(DWORD);
  1697. switch ( *OutStructureDesc++ ) {
  1698. case REM_EPOCH_TIME_GMT:
  1699. if ( fixedWrite ) {
  1700. LPDWORD outData = RapPossiblyAlignPointer(
  1701. (LPDWORD)OutStructure, ALIGN_DWORD, outNative);
  1702. RapPutDword( outData, gmtTime, outNative );
  1703. OutStructure = OutStructure + sizeof(DWORD);
  1704. }
  1705. break;
  1706. case REM_EPOCH_TIME_LOCAL:
  1707. if ( fixedWrite ) {
  1708. LPDWORD outData = RapPossiblyAlignPointer(
  1709. (LPDWORD)OutStructure, ALIGN_DWORD, outNative);
  1710. NetpGmtTimeToLocalTime( gmtTime, & localTime );
  1711. RapPutDword( outData, localTime, outNative );
  1712. OutStructure = OutStructure + sizeof(DWORD);
  1713. }
  1714. break;
  1715. case REM_IGNORE :
  1716. //
  1717. // The input is an ignored pad. Just update pointers.
  1718. //
  1719. break;
  1720. default:
  1721. UNSUPPORTED_COMBINATION(
  1722. REM_EPOCH_TIME_GMT,
  1723. *(OutStructureDesc-1) );
  1724. }
  1725. break;
  1726. }
  1727. case REM_EPOCH_TIME_LOCAL: {
  1728. //
  1729. // The input is a longword (four bytes) in seconds since
  1730. // 1970 (local timezone).
  1731. //
  1732. DWORD gmtTime, localTime;
  1733. InStructure = RapPossiblyAlignPointer(
  1734. InStructure, ALIGN_DWORD, inNative);
  1735. localTime = RapGetDword( InStructure, inNative );
  1736. NetpAssert( !DESC_CHAR_IS_DIGIT( *OutStructureDesc ) );
  1737. InStructure += sizeof(DWORD);
  1738. switch ( *OutStructureDesc++ ) {
  1739. case REM_EPOCH_TIME_GMT:
  1740. if ( fixedWrite ) {
  1741. LPDWORD outData = RapPossiblyAlignPointer(
  1742. (LPDWORD)OutStructure, ALIGN_DWORD, outNative);
  1743. NetpLocalTimeToGmtTime( localTime, & gmtTime );
  1744. RapPutDword( outData, gmtTime, outNative );
  1745. OutStructure = OutStructure + sizeof(DWORD);
  1746. }
  1747. break;
  1748. case REM_EPOCH_TIME_LOCAL:
  1749. if ( fixedWrite ) {
  1750. LPDWORD outData = RapPossiblyAlignPointer(
  1751. (LPDWORD)OutStructure, ALIGN_DWORD, outNative);
  1752. RapPutDword( outData, localTime, outNative );
  1753. OutStructure = OutStructure + sizeof(DWORD);
  1754. }
  1755. break;
  1756. case REM_IGNORE :
  1757. //
  1758. // The input is an ignored pad. Just update pointers.
  1759. //
  1760. break;
  1761. default:
  1762. UNSUPPORTED_COMBINATION(
  1763. REM_EPOCH_TIME_LOCAL,
  1764. *(OutStructureDesc-1) );
  1765. }
  1766. break;
  1767. }
  1768. default:
  1769. NetpKdPrint(( PREFIX_NETRAP
  1770. "RapConvertSingleEntry: Unsupported input character"
  1771. " at " FORMAT_LPVOID ": " FORMAT_DESC_CHAR "\n",
  1772. (LPVOID) (InStructureDesc-1), *(InStructureDesc-1) ));
  1773. NetpAssert(FALSE);
  1774. }
  1775. }
  1776. return NERR_Success;
  1777. } // RapConvertSingleEntryEx
  1778. NET_API_STATUS
  1779. RapConvertSingleEntry (
  1780. IN LPBYTE InStructure,
  1781. IN LPDESC InStructureDesc,
  1782. IN BOOL MeaninglessInputPointers,
  1783. IN LPBYTE OutBufferStart OPTIONAL,
  1784. OUT LPBYTE OutStructure OPTIONAL,
  1785. IN LPDESC OutStructureDesc,
  1786. IN BOOL SetOffsets,
  1787. IN OUT LPBYTE *StringLocation OPTIONAL,
  1788. IN OUT LPDWORD BytesRequired,
  1789. IN RAP_TRANSMISSION_MODE TransmissionMode,
  1790. IN RAP_CONVERSION_MODE ConversionMode
  1791. )
  1792. /*++
  1793. Routine Description:
  1794. This routine converts a single structure from one representation to
  1795. another. The representations are described by the descriptor strings
  1796. (see the "OS/2 Lanman Remote Admin Protocol" spec).
  1797. If there isn't enough space in the buffer for the entire structure,
  1798. this routine simply updates the BytesRequired parameter. Therefore,
  1799. callers have a convenient mechanism for determining the total buffer
  1800. size required to get all the information without special-casing for
  1801. buffer overflow.
  1802. Arguments:
  1803. InStructure - a pointer to the input structure.
  1804. InStructureDesc - the descriptor string for the input string.
  1805. MeaninglessInputPointers - if TRUE, then all pointers in the input
  1806. structure are meaningless. This routine should assume that
  1807. the first variable data immediately follows the input structure,
  1808. and the rest of the variable data follows in order.
  1809. OutBufferStart - the first byte in the output buffer. For Enum APIs,
  1810. this is used to calculate offsets from the start of the buffer
  1811. for string pointers. (This pointer may be null, to allow length
  1812. computations only.)
  1813. OutStructure - a pointer to where to put the actual output structure.
  1814. (This pointer may be null, to allow length computations only.)
  1815. OutStructureDesc - the descriptor string for the output structure.
  1816. SetOffsets - TRUE if pointer values in the output structure should
  1817. actually be set to the offset from the beginning of the structure.
  1818. FALSE if the actual addresses should be used.
  1819. StringLocation - the *last* location for variable-length data. The
  1820. data will be placed before this location and the pointer will
  1821. be updated to reflect the data added.
  1822. BytesRequired - the total number of bytes that would be required to
  1823. store the complete output structure. This allows the calling
  1824. routine to track the total required for all information without
  1825. worrying about buffer overflow.
  1826. Transmission Mode - Indicates whether this array is part of a response,
  1827. a request, or both.
  1828. Conversion Mode - Indicates whether this is a RAP-to-native, native-to-RAP,
  1829. or native-to-native conversion.
  1830. Return Value:
  1831. None.
  1832. --*/
  1833. {
  1834. NET_API_STATUS netStatus;
  1835. netStatus = RapConvertSingleEntryEx (InStructure,
  1836. InStructureDesc,
  1837. MeaninglessInputPointers,
  1838. OutBufferStart,
  1839. OutStructure,
  1840. OutStructureDesc,
  1841. SetOffsets,
  1842. StringLocation,
  1843. BytesRequired,
  1844. TransmissionMode,
  1845. ConversionMode,
  1846. 0 );
  1847. return netStatus;
  1848. }