Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

767 lines
30 KiB

  1. /*++
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. ConvBlk.c
  5. Abstract:
  6. This module contains RxpConvertBlock, a support routine for RxRemoteApi.
  7. Author:
  8. John Rogers (JohnRo) 01-Apr-1991
  9. (Created portable LanMan (NT) version from LanMan 2.0)
  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. 01-Apr-1991 JohnRo
  15. Converted from LanMan 2.x sources.
  16. 03-May-1991 JohnRo
  17. Handle enum (array) correctly.
  18. Get 32-bit data desc and convert to receive buffer with it.
  19. Handle receive word correctly.
  20. Lots of cleanup to comments.
  21. RcvDataPointer and RcvDataPresent are redundant.
  22. Fixed receive buffer length problem.
  23. Added (quiet) debug output.
  24. Reduced recompile hits from header files.
  25. 09-May-1991 JohnRo
  26. Made changes to reflect CliffV's code review.
  27. 11-May-1991 JohnRo
  28. Convert pointers, and then tell convert single entry that input
  29. pointers are OK. Also, let's treat Converter as DWORD locally.
  30. Force SmbGetUshort to get a word instead of a single byte.
  31. 14-May-1991 JohnRo
  32. Pass 2 aux descriptors to RxpConvertBlock.
  33. Added debug print of NumStruct as it changes.
  34. Use FORMAT_LPVOID instead of FORMAT_POINTER (max portability).
  35. 15-May-1991 JohnRo
  36. Added various "native" flags.
  37. 17-May-1991 JohnRo
  38. Handle array of aux structs.
  39. 20-May-1991 JohnRo
  40. Make data descriptors OPTIONAL for RxpConvertBlock.
  41. 11-Jun-1991 rfirth
  42. Added extra parameter: SmbRcvByteLen which specifies the amount of
  43. bytes in SmbRcvBuffer
  44. 14-Jun-1991 JohnRo
  45. Got rid of extraneous debug hex dump of buffer at end.
  46. Use NetpDbgReasonable().
  47. 15-Jul-1991 JohnRo
  48. Changed RxpConvertDataStructures to allow ERROR_MORE_DATA, e.g. for
  49. print APIs. Also got rid of a few unreferenced local variables.
  50. 17-Jul-1991 JohnRo
  51. Extracted RxpDebug.h from Rxp.h.
  52. 01-Aug-1991 RFirth
  53. Removed #if 0 block and variables which were put into convdata.c
  54. (RxpConvertDataStructures)
  55. 19-Aug-1991 rfirth
  56. Added Flags parameter and support for ALLOCATE_RESPONSE flag
  57. 26-Aug-1991 JohnRo
  58. Minor changes suggested by PC-LINT.
  59. 20-Sep-1991 JohnRo
  60. Downlevel NetService APIs. (Make sure *RcvDataBuffer gets set if
  61. ALLOCATE_RESPONSE is passed and *SmbRcvByteLen==0.)
  62. 21-Nov-1991 JohnRo
  63. Removed NT dependencies to reduce recompiles.
  64. 04-Nov-1992 JohnRo
  65. RAID 9355: Event viewer: won't focus on LM UNIX machine.
  66. (Added REM_DATA_BLOCK support for error log return data.)
  67. Use PREFIX_ equates.
  68. 04-May-1993 JohnRo
  69. RAID 6167: avoid access violation or assert with WFW print server.
  70. Use NetpKdPrint() where possible.
  71. 18-May-1993 JohnRo
  72. DosPrintQGetInfoW underestimates number of bytes needed.
  73. --*/
  74. // These must be included first:
  75. #include <windef.h> // IN, OUT, DWORD, LPBYTE, etc.
  76. #include <lmcons.h> // NET_API_STATUS.
  77. // These may be included in any order:
  78. #include <align.h> // ALIGN_WORST
  79. #include <apinums.h> // API_ equates.
  80. #include <limits.h> // CHAR_BIT.
  81. #include <lmapibuf.h> // NetapipBufferAllocate, NetApiBufferFree
  82. #include <lmerr.h> // NERR_ and ERROR_ equates.
  83. #include <netdebug.h> // NetpAssert(), NetpDbg routines, FORMAT_ equates.
  84. #include <netlib.h> // NetpMoveMemory(), etc.
  85. #include <prefix.h> // PREFIX_ equates.
  86. #include <remtypes.h> // REM_BYTE, etc.
  87. #include <rap.h> // LPDESC, RapConvertSingleEntry(), etc.
  88. #include <rx.h> // Flags parameter definitions
  89. #include <rxp.h> // My prototype.
  90. #include <rxpdebug.h> // IF_DEBUG().
  91. #define DESC_IS_UNSTRUCTURED( descPtr ) \
  92. ( ( (descPtr)==NULL) || ( (*(descPtr)) == REM_DATA_BLOCK ) )
  93. NET_API_STATUS
  94. RxpConvertBlock(
  95. IN DWORD ApiNumber,
  96. IN LPBYTE ResponseBlockPointer,
  97. IN LPDESC ParmDescriptorString,
  98. IN LPDESC DataDescriptor16 OPTIONAL,
  99. IN LPDESC DataDescriptor32 OPTIONAL,
  100. IN LPDESC AuxDesc16 OPTIONAL,
  101. IN LPDESC AuxDesc32 OPTIONAL,
  102. IN va_list *FirstArgumentPointer, // rest of API's arguments
  103. IN LPBYTE SmbRcvBuffer OPTIONAL,
  104. IN DWORD SmbRcvByteLen,
  105. OUT LPBYTE RcvDataBuffer OPTIONAL,
  106. IN DWORD RcvDataLength,
  107. IN DWORD Flags
  108. )
  109. /*++
  110. Routine Description:
  111. RxpConvertBlock translates the remote response (of a remoted API) into
  112. the local equivalent. This involves converting the response (which is in
  113. the form of 16-bit data in the transaction response buffer) to local
  114. data formats, and setting them in the argument list.
  115. Arguments:
  116. ApiNumber - Function number of the API required.
  117. ResponseBlockPointer - Points to the transaction SMB response block.
  118. ParmDescriptorString - A pointer to a ASCIIZ string describing the API call
  119. parameters (other than server name).
  120. DataDescriptor16 - A pointer to a ASCIIZ string describing the
  121. structure of the data in the call, i.e. the return data structure
  122. for a Enum or GetInfo call. This string is used for adjusting pointers
  123. to data in the local buffers after transfer across the net. If there
  124. is no structure involved in the call then DataDescriptor16 must
  125. be a null pointer.
  126. DataDescriptor32 - An optional pointer to a ASCIIZ string describing the
  127. 32-bit structure of the return data structure.
  128. AuxDesc16, AuxDesc32 - Will be NULL in most cases unless a REM_AUX_COUNT
  129. descriptor char is present in DataDescriptor16 in which case the
  130. aux descriptors define a secondary data format as DataDescriptor16
  131. defines the primary.
  132. FirstArgumentPointer - Points to the va_list (variable arguments list)
  133. containing the API arguments (after the server name). The caller
  134. must call va_start and va_end.
  135. SmbRcvBuffer - Optionally points to 16-bit format receive data buffer.
  136. SmbRcvByteLen - the number of bytes contained in SmbRcvBuffer (if not NULL)
  137. RcvDataBuffer - Points to the data area for the received data. For
  138. instance, this may be a server info structure from NetServerGetInfo.
  139. This pointer will be NULL for many APIs.
  140. If (Flags & ALLOCATE_RESPONSE) then this pointer actually points to
  141. the pointer to the eventual buffer. We allocate a buffer in this routine
  142. and set *RcvDataBuffer to it. If we fail to get the buffer then
  143. *RcvDataBuffer will be set to NULL
  144. RcvDataLength - Length of the data area that RcvDataBuffer points to.
  145. If (Flags & ALLOCATE_RESPONSE) then this value will be the size that the
  146. caller of RxRemoteApi originally decided that the down-level server
  147. should use and incidentally was the original size of SmbRcvBuffer
  148. Flags - bit-mapped flags word. Currently defined flags are:
  149. NO_PERMISSION_REQUIRED - used by RxpTransactSmb to determine whether
  150. a NULL session may be used
  151. ALLOCATE_RESPONSE - used by this routine to allocate the final
  152. 32-bit response data buffer based on the size
  153. of the SMB data received, multiplied by the
  154. RAP_CONVERSION_FACTOR
  155. Return Value:
  156. NET_API_STATUS - return value from remote API.
  157. --*/
  158. {
  159. DWORD Converter; // For pointer fixups.
  160. LPBYTE CurrentBlockPointer;
  161. LPDWORD EntriesReadPtr = NULL;
  162. DWORD NumStruct; // Loop count for ptr fixup.
  163. va_list ParmPtr;
  164. LPBYTE pDataBuffer = NULL; // pointer to returned data
  165. NET_API_STATUS Status; // Return status from remote.
  166. DWORD TempLength; // General purpose length.
  167. #if DBG
  168. //
  169. // Code in this file depends on 16-bit words; the Remote Admin Protocol
  170. // demands it.
  171. //
  172. NetpAssert( ( (sizeof(WORD)) * CHAR_BIT) == 16);
  173. if (DataDescriptor16 != NULL) {
  174. NetpAssert(DataDescriptor32 != NULL);
  175. } else {
  176. NetpAssert(DataDescriptor32 == NULL);
  177. }
  178. if (AuxDesc16 != NULL) {
  179. NetpAssert(AuxDesc32 != NULL);
  180. } else {
  181. NetpAssert(AuxDesc32 == NULL);
  182. }
  183. #endif
  184. ParmPtr = *FirstArgumentPointer;
  185. // The API call was successful. Now translate the return buffers
  186. // into the local API format.
  187. //
  188. // First copy any data from the return parameter buffer into the
  189. // fields pointed to by the original call parameters.
  190. // The return parameter buffer contains;
  191. // Status, (16 bits)
  192. // Converter, (16 bits)
  193. // ... fields described by rcv ptr types in
  194. // ParmDescriptorString
  195. CurrentBlockPointer = ResponseBlockPointer;
  196. Status = (NET_API_STATUS) SmbGetUshort( (LPWORD) CurrentBlockPointer );
  197. CurrentBlockPointer += sizeof(WORD);
  198. Converter = ((DWORD) SmbGetUshort( (LPWORD) CurrentBlockPointer )) & 0xffff;
  199. IF_DEBUG(CONVBLK) {
  200. NetpKdPrint(( PREFIX_NETAPI
  201. "RxpConvertBlock: Converter=" FORMAT_HEX_DWORD ".\n",
  202. Converter ));
  203. }
  204. CurrentBlockPointer += sizeof(WORD);
  205. // Set default value of NumStruct to 1, if data, 0 if no data.
  206. if ( (DataDescriptor16 != NULL) && (*DataDescriptor16 != '\0') ) {
  207. NumStruct = 1;
  208. } else {
  209. NumStruct = 0;
  210. }
  211. for( ; *ParmDescriptorString != '\0'; ParmDescriptorString++) {
  212. IF_DEBUG(CONVBLK) {
  213. NetpKdPrint(( PREFIX_NETAPI
  214. "RxpConvertBlock: *parm='" FORMAT_LPDESC_CHAR
  215. "', ParmPtr is:\n", *ParmDescriptorString ));
  216. NetpDbgHexDump((LPVOID) & ParmPtr, sizeof(va_list));
  217. }
  218. switch( *ParmDescriptorString) {
  219. case REM_WORD : // Word in old APIs (DWORD in 32-bit).
  220. case REM_DWORD : // DWord.
  221. (void) va_arg(ParmPtr, DWORD); // Step over this arg.
  222. break;
  223. case REM_ASCIZ :
  224. (void) va_arg(ParmPtr, LPSTR); // Step over this arg.
  225. break;
  226. case REM_BYTE_PTR :
  227. (void) va_arg(ParmPtr, LPBYTE); // Step over this arg.
  228. (void) RapArrayLength(
  229. ParmDescriptorString,
  230. &ParmDescriptorString,
  231. Response);
  232. break;
  233. case REM_WORD_PTR : // (WORD *) in old APIs.
  234. case REM_DWORD_PTR : // (DWORD *)
  235. (void) va_arg(ParmPtr, LPDWORD); // Step over this arg.
  236. break;
  237. case REM_RCV_WORD_PTR : // pointer to rcv word(s) (DWORD in 32-bit)
  238. {
  239. LPDWORD Temp;
  240. DWORD ArrayCount;
  241. Temp = va_arg(ParmPtr, LPDWORD);
  242. ++ParmDescriptorString; // point to first (possible) digit...
  243. ArrayCount = RapDescArrayLength(
  244. ParmDescriptorString); // updated past last.
  245. --ParmDescriptorString; // point back at last digit for loop.
  246. IF_DEBUG(CONVBLK) {
  247. NetpKdPrint(( PREFIX_NETAPI
  248. "RxpConvertBlock: rcv.word.ptr, temp="
  249. FORMAT_LPVOID ", ArrayCount=" FORMAT_DWORD ".\n",
  250. (LPVOID) Temp, ArrayCount ));
  251. }
  252. // if the rcv buffer given to us by the user is NULL,
  253. // (one currently can be - it is an MBZ parameter for
  254. // now in the log read apis...), don't attempt to
  255. // copy anything. TempLength will be garbage in this
  256. // case, so don't update CurrentBlockPointer either. All we
  257. // use RapArrayLength for is to update ParmDescriptorString if
  258. // the parameter was NULL.
  259. if ( Temp == NULL ) {
  260. ; /* NULLBODY */
  261. } else {
  262. // Copy one or more words (expanding to DWORDS as we go).
  263. DWORD WordsLeft = ArrayCount;
  264. do {
  265. DWORD Data;
  266. // Convert byte order if necessary, and expand.
  267. Data = (DWORD) SmbGetUshort(
  268. (LPWORD) CurrentBlockPointer );
  269. *Temp = Data;
  270. Temp += 1;
  271. --WordsLeft;
  272. } while (WordsLeft > 0);
  273. // This gross hack is to fix the problem that a
  274. // down level spooler (Lan Server 1.2)
  275. // do not perform level checking
  276. // on the w functions of the api(s):
  277. // DosPrintQGetInfo
  278. // and thus can return NERR_Success
  279. // and bytesavail == 0. This combination
  280. // is technically illegal, and results in
  281. // us attempting to unpack a buffer full of
  282. // garbage. The following code detects this
  283. // condition and resets the amount of returned
  284. // data to zero so we do not attempt to unpack
  285. // the buffer. Since we know the reason for the
  286. // mistake at the server end is that we passed
  287. // them a new level, we return ERROR_INVALID_LEVEL
  288. // in this case.
  289. // ERICPE, 5/16/90.
  290. if ((ApiNumber == API_WPrintQGetInfo)
  291. && (Status == NERR_Success)
  292. && (*(LPWORD)CurrentBlockPointer == 0)
  293. && (*ParmDescriptorString == REM_RCV_WORD_PTR)) {
  294. Status = ERROR_INVALID_LEVEL;
  295. goto ErrorExit;
  296. }
  297. // END OF GROSS HACK
  298. CurrentBlockPointer += (ArrayCount * sizeof(WORD));
  299. }
  300. break;
  301. }
  302. case REM_RCV_BYTE_PTR : // pointer to rcv byte(s)
  303. {
  304. LPBYTE Temp;
  305. Temp = va_arg(ParmPtr, LPBYTE);
  306. TempLength = RapArrayLength(
  307. ParmDescriptorString,
  308. &ParmDescriptorString,
  309. Response);
  310. // if the rcv buffer given to us by the user is NULL,
  311. // (one currently can be - it is an MBZ parameter for
  312. // now in the log read apis...), don't attempt to
  313. // copy anything. TempLength will be garbage in this
  314. // case, so don't update CurrentBlockPointer either. All we
  315. // use RapArrayLength for is to update ParmDescriptorString if
  316. // the parameter was NULL.
  317. if ( Temp != NULL ) {
  318. NetpMoveMemory(
  319. Temp, // dest
  320. CurrentBlockPointer, // src
  321. TempLength); // len
  322. CurrentBlockPointer += TempLength;
  323. }
  324. }
  325. break;
  326. case REM_RCV_DWORD_PTR : // pointer to rcv Dword(s)
  327. {
  328. LPDWORD Temp;
  329. Temp = va_arg(ParmPtr, LPDWORD);
  330. TempLength = RapArrayLength(
  331. ParmDescriptorString,
  332. &ParmDescriptorString,
  333. Response);
  334. // if the rcv buffer given to us by the user is NULL,
  335. // (one currently can be - it is an MBZ parameter for
  336. // now in the log read apis...), don't attempt to
  337. // copy anything. TempLength will be garbage in this
  338. // case, so don't update CurrentBlockPointer either. All we
  339. // use RapArrayLength for is to update ParmDescriptorString if
  340. // the parameter was NULL.
  341. if ( Temp == NULL ) {
  342. ; /* NULLBODY */
  343. } else {
  344. NetpMoveMemory(
  345. Temp, // dest
  346. CurrentBlockPointer, // src
  347. TempLength); // len
  348. CurrentBlockPointer += TempLength;
  349. }
  350. }
  351. break;
  352. case REM_SEND_BUF_PTR :
  353. (void) va_arg(ParmPtr, LPVOID); // Step over arg.
  354. break;
  355. case REM_SEND_BUF_LEN :
  356. (void) va_arg(ParmPtr, DWORD); // Step over (32-bit) buf len.
  357. break;
  358. case REM_RCV_BUF_PTR :
  359. (void) va_arg(ParmPtr, LPVOID);
  360. break;
  361. case REM_RCV_BUF_LEN :
  362. (void) va_arg(ParmPtr, DWORD); // Step over (32-bit) buf len.
  363. break;
  364. case REM_PARMNUM :
  365. (void) va_arg(ParmPtr, DWORD); // Step over (32-bit) parm num.
  366. break;
  367. case REM_ENTRIES_READ : // Used for NumStruct
  368. {
  369. EntriesReadPtr = va_arg(ParmPtr, LPDWORD);
  370. NumStruct = (DWORD) SmbGetUshort((LPWORD) CurrentBlockPointer);
  371. if (RapValueWouldBeTruncated(NumStruct))
  372. {
  373. Status = ERROR_INVALID_PARAMETER;
  374. return Status;
  375. }
  376. IF_DEBUG(CONVBLK) {
  377. NetpKdPrint(( PREFIX_NETAPI
  378. "RxpConvertBlock: NumStruct is now "
  379. FORMAT_DWORD ".\n", NumStruct ));
  380. }
  381. // Assume all entries will fit; we'll correct this later if not.
  382. *EntriesReadPtr = NumStruct;
  383. CurrentBlockPointer += sizeof(WORD);
  384. break;
  385. }
  386. case REM_FILL_BYTES :
  387. // Special case, this was not really an input parameter so ParmPtr
  388. // does not get changed. However, the ParmDescriptorString
  389. // pointer must be advanced past the descriptor field so
  390. // use get RapArrayLength to do this but ignore the
  391. // return length.
  392. (void) RapArrayLength(
  393. ParmDescriptorString,
  394. &ParmDescriptorString,
  395. Response);
  396. break;
  397. case REM_AUX_NUM : // Can't have aux in parm desc.
  398. case REM_BYTE : // Can't push a byte, so this is bogus?
  399. case REM_DATA_BLOCK : // Not in parm desc.
  400. case REM_DATE_TIME : // Never used
  401. case REM_NULL_PTR : // Never used
  402. case REM_SEND_LENBUF : // Never used
  403. default :
  404. NetpBreakPoint();
  405. Status = NERR_InternalError;
  406. goto ErrorExit;
  407. } // switch
  408. } // for
  409. //
  410. // If no data was returned from the server, then there's no point in
  411. // continuing. Return early with the status code as returned from the
  412. // remoted function
  413. //
  414. if (!SmbRcvByteLen) {
  415. if (Flags & ALLOCATE_RESPONSE) {
  416. //
  417. // We failed to allocate the buffer; this in turn will cause
  418. // RxRemoteApi to fail, in which event, the calling function
  419. // (ie RxNetXxxx) may try to free the buffer allocated on its
  420. // behalf (ie the buffer we just failed to get). Ensure that
  421. // the caller doesn't try to free an invalid pointer by setting
  422. // the returned pointer to NULL
  423. //
  424. NetpAssert(RcvDataBuffer); // address of the callers buffer pointer
  425. *(LPBYTE*)RcvDataBuffer = NULL;
  426. }
  427. return Status;
  428. }
  429. //
  430. // If the caller of RxRemoteApi requested that we allocate the final data
  431. // buffer on their behalf, then allocate it here. We use as the size
  432. // criterion
  433. //
  434. // (RAP_CONVERSION_FACTOR + 1/RAP_CONVERSION_FRACTION) * SmbRcvByteLen
  435. //
  436. // since this has the size of 16-bit data actually received.
  437. //
  438. // RAP_CONVERSION_FACTOR is 2 since that's the ratio for the size of
  439. // WCHAR to CHAR and of DWORD to WORD. However, Lanman data structures
  440. // typically represents text as zero terminated array of CHAR within the
  441. // returned structure. The array itself is of maximum size. However,
  442. // the typical native representation has a 4-byte pointer to a zero
  443. // terminated WCHAR. A factor of 2 wouldn't account for the 4-byte pointer.
  444. // Assuming the smallest lanman array size is 13 bytes (e.g., NNLEN+1), an
  445. // additional factor of 4/13 (about 1/3) is needed. So,
  446. // RAP_CONVERSION_FRACTION is 3.
  447. //
  448. // Round the size to a multiple of the alignment for the system to allow
  449. // data to be packed at the trailing end of the buffer.
  450. //
  451. // NOTE: Since the original API caller expects to use NetApiBufferFree to
  452. // get rid of this buffer, we must use NetapipBufferAllocate
  453. //
  454. if (Flags & ALLOCATE_RESPONSE) {
  455. NET_API_STATUS ConvertStatus;
  456. NetpAssert(RcvDataBuffer); // address of the callers buffer pointer
  457. NetpAssert(SmbRcvByteLen); // size of the data received
  458. RcvDataLength = SmbRcvByteLen * RAP_CONVERSION_FACTOR;
  459. RcvDataLength += (SmbRcvByteLen + RAP_CONVERSION_FRACTION - 1) /
  460. RAP_CONVERSION_FRACTION;
  461. RcvDataLength = ROUND_UP_COUNT( RcvDataLength, ALIGN_WORST );
  462. if (ConvertStatus = NetapipBufferAllocate(RcvDataLength,
  463. (PVOID *) &pDataBuffer)) {
  464. NetpKdPrint(( PREFIX_NETAPI
  465. "Error: RxpConvertBlock cannot allocate memory ("
  466. "error " FORMAT_API_STATUS ").\n", ConvertStatus ));
  467. Status = ConvertStatus;
  468. goto ErrorExit;
  469. }
  470. NetpAssert( pDataBuffer != NULL );
  471. IF_DEBUG(CONVBLK) {
  472. NetpKdPrint(( PREFIX_NETAPI
  473. "RxpConvertBlock: allocated " FORMAT_DWORD " byte buffer "
  474. "at " FORMAT_LPVOID " for caller\n",
  475. RcvDataLength, (LPVOID) pDataBuffer ));
  476. }
  477. *(LPBYTE*)RcvDataBuffer = pDataBuffer;
  478. } else {
  479. pDataBuffer = RcvDataBuffer;
  480. }
  481. //////////////////////////////////////////////////////////////////////////
  482. // //
  483. // NB: From here on down, RcvDataBuffer should not be used to point to //
  484. // the received data buffer. Use pDataBuffer. The reason is that //
  485. // RcvDataBuffer is ambiguous - it may point to a buffer or it may //
  486. // point to a pointer to a buffer. pDataBuffer will always point //
  487. // to a buffer //
  488. // //
  489. //////////////////////////////////////////////////////////////////////////
  490. //
  491. // Done doing arguments, so now we can do the receive buffer.
  492. //
  493. if ((pDataBuffer != NULL) && (RcvDataLength != 0)) {
  494. // DWORD BytesRequired = 0;
  495. LPBYTE EntryPtr16 = SmbRcvBuffer;
  496. // LPBYTE EntryPtr32 = pDataBuffer;
  497. DWORD NumAuxStructs;
  498. // LPBYTE StringAreaEnd = pDataBuffer + RcvDataLength;
  499. // BOOL auxiliaries = AuxDesc32 != NULL;
  500. //
  501. // MOD 06/06/91 RLF
  502. //
  503. // NetpAssert( DataDescriptor16 != NULL );
  504. //
  505. // MOD 06/06/91 RLF
  506. //
  507. IF_DEBUG(CONVBLK) {
  508. NetpKdPrint(( PREFIX_NETAPI
  509. "RxpConvertBlock: "
  510. "SMB rcv buff (before rcv buff conv) (partial):\n" ));
  511. NetpDbgHexDump(SmbRcvBuffer, NetpDbgReasonable(RcvDataLength));
  512. }
  513. // Now convert all pointer fields in the receive buffer to local
  514. // pointers.
  515. //
  516. // MOD 06/06/91 RLF
  517. //
  518. // If we have a receive data buffer, we may or may not be receiving
  519. // structured data. If DataDescriptor16 is NULL assume unstructured data
  520. // else work out sizes of structs etc.
  521. //
  522. // When I say "unstructured data", is it okay to treat this as an array of
  523. // bytes? What about ASCIZ-UC translation? My guess is that at this level
  524. // unstructured data is bytes and any higher-level software which knows
  525. // the format of received/expected data can process it
  526. //
  527. if ( !DESC_IS_UNSTRUCTURED( DataDescriptor16 ) ) {
  528. NET_API_STATUS ConvertStatus;
  529. DWORD NumCopied = 0;
  530. //
  531. // MOD 06/06/91 RLF
  532. //
  533. ConvertStatus = RxpReceiveBufferConvert(
  534. SmbRcvBuffer, // buffer (updated in place)
  535. SmbRcvByteLen, // buffer size in bytes
  536. Converter,
  537. NumStruct,
  538. DataDescriptor16,
  539. AuxDesc16,
  540. & NumAuxStructs);
  541. if (ConvertStatus != NERR_Success) {
  542. Status = ConvertStatus;
  543. goto ErrorExit;
  544. }
  545. ConvertStatus = RxpConvertDataStructures(
  546. DataDescriptor16, // going from 16-bit data
  547. DataDescriptor32, // to 32-bit
  548. AuxDesc16, // same applies for aux data
  549. AuxDesc32,
  550. EntryPtr16, // where the 16-bit data is
  551. pDataBuffer, // where the 32-bit data goes
  552. RcvDataLength, // size of the output buffer (bytes)
  553. NumStruct, // number of primaries
  554. &NumCopied, // number of primaries copied.
  555. Both, // parameter to RapConvertSingleEntry
  556. RapToNative // convert 16-bit data to 32-bit
  557. );
  558. if (ConvertStatus != NERR_Success) {
  559. //
  560. // This only happens when (1) the API allows the application
  561. // to specify the buffer size and (2) the size is too small.
  562. // As part of the "switch" above, we've already set the
  563. // "pcbNeeded" (pointer to count of bytes needed). Actually,
  564. // that value assumes that the RAP and native sizes are the
  565. // same. It's up to RxRemoteApi's caller to correct that,
  566. // if it's even feasible.
  567. //
  568. NetpAssert( ConvertStatus == ERROR_MORE_DATA );
  569. if (EntriesReadPtr != NULL) {
  570. // Some APIs, like DosPrintQEnum, have entries read value.
  571. NetpAssert( NumCopied <= NumStruct );
  572. *EntriesReadPtr = NumCopied;
  573. } else {
  574. // APIs like DosPrintQGetInfo does not have entries read.
  575. // There isn't much we can do for them.
  576. }
  577. Status = ConvertStatus;
  578. // Continue, treating this as "normal" status...
  579. } else {
  580. NetpAssert( NumCopied == NumStruct );
  581. }
  582. IF_DEBUG(CONVBLK) {
  583. NetpKdPrint(( PREFIX_NETAPI
  584. "RxpConvertBlock: rcv buff (after CSE) (partial):\n" ));
  585. NetpDbgHexDump(pDataBuffer, NetpDbgReasonable(RcvDataLength));
  586. }
  587. } else {
  588. //
  589. // There is no 16-bit data descriptor. We take this to mean that
  590. // the data is unstructured - typically a string will be returned
  591. // An example? Why, I_NetNameCanonicalize of course!
  592. //
  593. #if DBG
  594. NetpAssert(RcvDataLength >= SmbRcvByteLen);
  595. #endif
  596. //
  597. // Ascii-Unicode conversion is the responsibility of the caller
  598. //
  599. NetpMoveMemory(pDataBuffer, SmbRcvBuffer, SmbRcvByteLen);
  600. }
  601. } // if pDataBuffer && RcvDataLength
  602. IF_DEBUG(CONVBLK) {
  603. NetpKdPrint(( PREFIX_NETAPI
  604. "RxpConvertBlock: returning (normal) status="
  605. FORMAT_API_STATUS "\n", Status ));
  606. }
  607. return(Status);
  608. ErrorExit:
  609. NetpAssert( Status != NO_ERROR );
  610. if (Flags & ALLOCATE_RESPONSE) {
  611. //
  612. // If we already allocated a buffer on behalf of the caller of
  613. // RxRemoteApi, then free it up.
  614. //
  615. if (pDataBuffer != NULL) {
  616. (VOID) NetApiBufferFree(pDataBuffer);
  617. }
  618. //
  619. // We failed to allocate the buffer; this in turn will cause
  620. // RxRemoteApi to fail, in which event, the calling function
  621. // (ie RxNetXxxx) may try to free the buffer allocated on its
  622. // behalf (ie the buffer we just failed to get). Ensure that
  623. // the caller doesn't try to free an invalid pointer by setting
  624. // the returned pointer to NULL.
  625. //
  626. NetpAssert( RcvDataBuffer != NULL );
  627. *(LPBYTE*)RcvDataBuffer = NULL;
  628. }
  629. NetpKdPrint(( PREFIX_NETAPI
  630. "RxpConvertBlock: returning error status="
  631. FORMAT_API_STATUS "\n", Status ));
  632. return (Status);
  633. } // RxpConvertBlock