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.

418 lines
14 KiB

  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. convdata.c
  5. Abstract:
  6. RxpConvertDataStructures routine which converts 16- to 32-bit arrays of
  7. structures and vice versa.
  8. Author:
  9. Richard Firth (rfirth) 03-Jul-1991
  10. Revision History:
  11. 03-Jul-1991 rfirth
  12. created
  13. 15-Jul-1991 JohnRo
  14. Align each structure (e.g. in an array) if necessary. This will,
  15. for instance, help print dest info level 1 handling. Changed
  16. RxpConvertDataStructures to allow ERROR_MORE_DATA, e.g. for print APIs.
  17. Also, use DBG instead of DEBUG equate.
  18. 17-Jul-1991 JohnRo
  19. Extracted RxpDebug.h from Rxp.h.
  20. 07-Sep-1991 JohnRo
  21. Made changes suggested by PC-LINT.
  22. 20-Nov-1991 JohnRo
  23. Clarify which routine an error message is from.
  24. 21-Nov-1991 JohnRo
  25. Removed NT dependencies to reduce recompiles.
  26. 18-May-1993 JohnRo
  27. DosPrintQGetInfoW underestimates number of bytes needed.
  28. Made changes suggested by PC-LINT 5.0
  29. 21-Jun-1993 JohnRo
  30. RAID 14180: NetServerEnum never returns (alignment bug in
  31. RxpConvertDataStructures).
  32. --*/
  33. #include <windef.h>
  34. #include <align.h>
  35. #include <lmerr.h>
  36. #include <rxp.h> // My prototype.
  37. #include <rxpdebug.h> // IF_DEBUG().
  38. #include <rap.h>
  39. #include <netdebug.h>
  40. NET_API_STATUS
  41. RxpConvertDataStructures(
  42. IN LPDESC InputDescriptor,
  43. IN LPDESC OutputDescriptor,
  44. IN LPDESC InputAuxDescriptor OPTIONAL,
  45. IN LPDESC OutputAuxDescriptor OPTIONAL,
  46. IN LPBYTE InputBuffer,
  47. OUT LPBYTE OutputBuffer,
  48. IN DWORD OutputBufferSize,
  49. IN DWORD PrimaryCount,
  50. OUT LPDWORD EntriesConverted OPTIONAL,
  51. IN RAP_TRANSMISSION_MODE TransmissionMode,
  52. IN RAP_CONVERSION_MODE ConversionMode
  53. )
  54. /*++
  55. Routine Description:
  56. A buffer containing 16- or 32-bit structures is converted to 32- or 16-bit
  57. structures resp. in a separate buffer. The structures may or may not have
  58. associated auxiliary structures. The output buffer is expected to be large
  59. enough to contain all the input data structures plus any variable length
  60. data items. Therefore, in the worst case, there must be enough space to
  61. convert all 16-bit items to 32-bits and convert ASCII strings to UNICODE.
  62. There may not be any auxiliary structures associated with the primaries,
  63. in which case the auxiliary descriptor pointers should BOTH BE NULL.
  64. Assumptions:
  65. IMPORTANT: The input buffer is assumed to have MEANINGFUL pointers.
  66. Arguments:
  67. InputDescriptor - Pointer to string describing input primary data structure.
  68. OutputDescriptor - Pointer to string describing output primary data
  69. structure.
  70. InputAuxDescriptor - Pointer to string describing input auxiliary data
  71. structure. May be NULL.
  72. OutputAuxDescriptor - Pointer to string describing output auxiliary data
  73. structure. May be NULL.
  74. InputBuffer - Pointer to data area containing input structures.
  75. OutputBuffer - Pointer to data area where output structures will be placed.
  76. If the OutputBufferSize is too small, the contents of the output area
  77. is undefined.
  78. OutputBufferSize - Size of output buffer.
  79. PrimaryCount - Number of primary structures in InputBuffer.
  80. EntriesConverted - optionally points to a DWORD which will be filled-in
  81. with the number of entries actually converted. This will be the same
  82. as PrimaryCount if we return NO_ERROR, but will be less if we return
  83. ERROR_MORE_DATA.
  84. TransmissionMode - Parameter to RapConvertSingleEntry.
  85. ConversionMode - Which 16- to 32-bit conversion to use.
  86. Return Value:
  87. NET_API_STATUS - NERR_Success or ERROR_MORE_DATA.
  88. ( The callers of this routine assume these are the only two error codes.)
  89. --*/
  90. {
  91. NET_API_STATUS status;
  92. DWORD input_structure_size;
  93. DWORD output_structure_size;
  94. DWORD input_aux_structure_size = 0;
  95. DWORD output_aux_structure_size = 0;
  96. DWORD input_alignment;
  97. DWORD output_alignment;
  98. DWORD input_aux_alignment = 0;
  99. DWORD output_aux_alignment = 0;
  100. LPBYTE aligned_input_buffer_start;
  101. LPBYTE aligned_output_buffer_start;
  102. BOOL auxiliaries = (InputAuxDescriptor != NULL);
  103. DWORD aux_count_offset = 0;
  104. DWORD aux_count = 0;
  105. DWORD entries_fully_converted = 0;
  106. LPBYTE next_input_structure;
  107. LPBYTE next_output_structure;
  108. //
  109. // These next two variables are used by RapConvertSingleEntry which copies
  110. // stuff to the output buffer and informs us of the amount of space used or
  111. // required, depending on whether it has enough space to write the data; we
  112. // assume it will. RapConvertSingleEntry stores the fixed structures at the
  113. // head of the buffer and starts writing the variable parts (strings) at the
  114. // bottom. It uses variable_data_pointer as the next writable location for
  115. // the strings, and updates this variable as it writes to the area pointed to
  116. //
  117. LPBYTE variable_data_pointer;
  118. DWORD space_occupied = 0;
  119. //
  120. // if the conversion mode is NativeToRap or NativeToNative then the input
  121. // data is 32-bit. Same for output data
  122. //
  123. BOOL input_is_32_bit = ConversionMode == NativeToRap || ConversionMode == NativeToNative;
  124. BOOL output_is_32_bit = ConversionMode == RapToNative || ConversionMode == NativeToNative;
  125. #if DBG
  126. //
  127. // the auxiliary data descriptors must be both NULL or both non-NULL
  128. //
  129. BOOL aux_in, aux_out;
  130. aux_in = (InputAuxDescriptor != NULL);
  131. aux_out = (OutputAuxDescriptor != NULL);
  132. if (aux_in ^ aux_out)
  133. {
  134. NetpKdPrint(("RxpConvertDataStructures: "
  135. "InputAuxDescriptor & OutputAuxDescriptor out of sync\n"));
  136. NetpAssert(FALSE);
  137. }
  138. #endif
  139. input_structure_size = RapStructureSize(InputDescriptor,
  140. TransmissionMode,
  141. input_is_32_bit
  142. );
  143. output_structure_size = RapStructureSize(OutputDescriptor,
  144. TransmissionMode,
  145. output_is_32_bit
  146. );
  147. input_alignment = RapStructureAlignment(InputDescriptor,
  148. TransmissionMode,
  149. input_is_32_bit
  150. );
  151. output_alignment = RapStructureAlignment(OutputDescriptor,
  152. TransmissionMode,
  153. output_is_32_bit
  154. );
  155. if (auxiliaries)
  156. {
  157. input_aux_structure_size = RapStructureSize(InputAuxDescriptor,
  158. TransmissionMode,
  159. input_is_32_bit
  160. );
  161. output_aux_structure_size = RapStructureSize(OutputAuxDescriptor,
  162. TransmissionMode,
  163. output_is_32_bit
  164. );
  165. input_aux_alignment = RapStructureAlignment(InputAuxDescriptor,
  166. TransmissionMode,
  167. input_is_32_bit
  168. );
  169. output_aux_alignment = RapStructureAlignment(OutputAuxDescriptor,
  170. TransmissionMode,
  171. output_is_32_bit
  172. );
  173. aux_count_offset = RapAuxDataCountOffset(InputDescriptor,
  174. TransmissionMode,
  175. input_is_32_bit
  176. );
  177. }
  178. //
  179. // Make sure first (only?) input and output structures are aligned. (This
  180. // won't do anything for the RAP formats, but is critical for native.)
  181. //
  182. aligned_input_buffer_start = RapPossiblyAlignPointer(
  183. InputBuffer,
  184. input_alignment,
  185. input_is_32_bit);
  186. aligned_output_buffer_start = RapPossiblyAlignPointer(
  187. OutputBuffer,
  188. output_alignment,
  189. output_is_32_bit);
  190. //
  191. // We can't use the space we just skipped over, so update size accordingly.
  192. //
  193. OutputBufferSize -= (DWORD)(aligned_output_buffer_start - OutputBuffer);
  194. NetpAssert( OutputBufferSize >= 1 );
  195. //
  196. // Initialize roving pointers.
  197. //
  198. next_input_structure = aligned_input_buffer_start;
  199. next_output_structure = aligned_output_buffer_start;
  200. variable_data_pointer = aligned_output_buffer_start + OutputBufferSize;
  201. //
  202. // For each primary structure, copy the input primary to the output buffer,
  203. // changing format as we go; copy any associated variable data at the end
  204. // of the output buffer. Then, if there is an aux count associated with
  205. // the primary, do the same action for the auxiliary structures and
  206. // associated strings/variable data
  207. //
  208. while (PrimaryCount--)
  209. {
  210. //
  211. // Convert the data for this instance of the primary structure.
  212. //
  213. status = RapConvertSingleEntryEx(
  214. next_input_structure,
  215. InputDescriptor, // input desc
  216. FALSE, // input ptrs NOT meaningless
  217. aligned_output_buffer_start,
  218. next_output_structure,
  219. OutputDescriptor,
  220. FALSE, // don't set offsets (want ptrs)
  221. &variable_data_pointer,
  222. &space_occupied,
  223. TransmissionMode, // as supplied in parameters
  224. ConversionMode, // as supplied in parameters
  225. (ULONG_PTR)InputBuffer
  226. );
  227. NetpAssert( status == NERR_Success );
  228. if (space_occupied > OutputBufferSize)
  229. {
  230. IF_DEBUG(CONVDATA) {
  231. NetpKdPrint(("RxpConvertDataStructures: "
  232. "output buffer size blown by primary\n"));
  233. }
  234. status = ERROR_MORE_DATA;
  235. goto Cleanup;
  236. }
  237. //
  238. // if we have auxiliary structs, pull out the number associated
  239. // with this primary struct from the primary struct itself
  240. // before pointing to the next copy location (this allows us to
  241. // handle the case where there are a variable number of aux
  242. // structs per each primary. There may not be such a case, but
  243. // this is defensive programming)
  244. //
  245. if (auxiliaries)
  246. {
  247. if (input_is_32_bit)
  248. {
  249. aux_count = *(LPDWORD)(next_input_structure + aux_count_offset);
  250. }
  251. else
  252. {
  253. aux_count = *(LPWORD)(next_input_structure + aux_count_offset);
  254. }
  255. }
  256. //
  257. // Bump to next element of each array (or just beyond end, if we're
  258. // done).
  259. //
  260. next_input_structure += input_structure_size;
  261. next_output_structure += output_structure_size;
  262. //
  263. // Make sure each primary structure is aligned. (This won't do anything
  264. // for the RAP formats, but is critical for native.)
  265. //
  266. next_input_structure = RapPossiblyAlignPointer(
  267. next_input_structure, input_alignment, input_is_32_bit);
  268. {
  269. DWORD NextOutputAlignment =
  270. (DWORD)((LPBYTE) (RapPossiblyAlignPointer(
  271. next_output_structure,
  272. output_alignment,
  273. output_is_32_bit))
  274. - next_output_structure);
  275. NetpAssert( NextOutputAlignment < ALIGN_WORST );
  276. if (NextOutputAlignment > 0) {
  277. next_output_structure += NextOutputAlignment;
  278. space_occupied += NextOutputAlignment;
  279. }
  280. }
  281. //
  282. // use aux_count to determine whether loop should be performed
  283. //
  284. while (aux_count)
  285. {
  286. //
  287. // Convert the data for this instance of the secondary structure.
  288. //
  289. status = RapConvertSingleEntryEx(
  290. next_input_structure,
  291. InputAuxDescriptor,
  292. FALSE, // input ptrs NOT meaningless
  293. aligned_output_buffer_start,
  294. next_output_structure,
  295. OutputAuxDescriptor,
  296. FALSE, // don't set offsets (want ptrs)
  297. &variable_data_pointer,
  298. &space_occupied,
  299. TransmissionMode, // as supplied in parameters
  300. ConversionMode, // as supplied in parameters
  301. (ULONG_PTR)InputBuffer
  302. );
  303. NetpAssert( status == NERR_Success );
  304. if (space_occupied > OutputBufferSize)
  305. {
  306. IF_DEBUG(CONVDATA) {
  307. NetpKdPrint(("RxpConvertDataStructures: "
  308. "output buffer size blown by secondary\n"));
  309. }
  310. status = ERROR_MORE_DATA;
  311. goto Cleanup;
  312. }
  313. next_input_structure += input_aux_structure_size;
  314. next_output_structure += output_aux_structure_size;
  315. --aux_count;
  316. //
  317. // Make sure next structure (if any) is aligned. (This won't do
  318. // anything for the RAP formats, but is critical for native.)
  319. //
  320. next_input_structure = RapPossiblyAlignPointer(
  321. next_input_structure,
  322. input_aux_alignment,
  323. input_is_32_bit);
  324. next_output_structure = RapPossiblyAlignPointer(
  325. next_output_structure,
  326. output_aux_alignment,
  327. output_is_32_bit);
  328. space_occupied = RapPossiblyAlignCount(
  329. space_occupied,
  330. output_aux_alignment,
  331. output_is_32_bit);
  332. } // while (aux_count)
  333. ++entries_fully_converted;
  334. } // while (primary_count--)
  335. status = NERR_Success;
  336. Cleanup:
  337. if (EntriesConverted != NULL) {
  338. *EntriesConverted = entries_fully_converted;
  339. }
  340. return (status);
  341. }