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.

559 lines
20 KiB

  1. /*++
  2. Copyright (c) 1987-91 Microsoft Corporation
  3. Module Name:
  4. Pack.c
  5. Abstract:
  6. This module just contains RxpPackSendBuffer.
  7. Author:
  8. John Rogers (JohnRo) 01-Apr-1991
  9. Environment:
  10. Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
  11. Requires ANSI C extensions: slash-slash comments, long external names.
  12. Revision History:
  13. (various NBU people)
  14. LanMan 2.x code
  15. 01-Apr-1991 JohnRo
  16. Created portable version from LanMan 2.x sources.
  17. 13-Apr-1991 JohnRo
  18. Reduced recompile hits from header files.
  19. 03-May-1991 JohnRo
  20. Don't use NET_API_FUNCTION for non-APIs.
  21. 14-May-1991 JohnRo
  22. Clarify that descriptors are 32-bit versions. Use more typedefs.
  23. 19-May-1991 JohnRo
  24. Make LINT-suggested changes.
  25. 13-Jun-1991 JohnRo
  26. Allow setinfo when pointers point to current structure.
  27. Added debug code. Descriptors are really 16-bit versions.
  28. 03-Jul-1991 rfirth
  29. Extensive reworking to get variable data area copy working correctly
  30. and also remove some code which resulted from bogus assumptions
  31. 17-Jul-1991 JohnRo
  32. Extracted RxpDebug.h from Rxp.h.
  33. 13-Sep-1991 JohnRo
  34. Made changes suggested by PC-LINT.
  35. 01-Oct-1991 JohnRo
  36. More work toward UNICODE.
  37. 21-Nov-1991 JohnRo
  38. Removed NT dependencies to reduce recompiles.
  39. 06-Dec-1991 JohnRo
  40. Avoid alignment error on MIPS.
  41. --*/
  42. // These must be included first:
  43. #include <windef.h> // IN, DWORD, LPTSTR, etc.
  44. #include <rxp.h> // RpcXlate private header file.
  45. // These may be included in any order:
  46. #include <apiworke.h> // RANGE_F(), BUF_INC.
  47. #include <lmerr.h> // NERR_ and ERROR_ equates.
  48. #include <netdebug.h> // NetpAssert(), FORMAT_ equates.
  49. #include <netlib.h> // NetpMemoryAllocate(), etc.
  50. #include <remtypes.h> // REM_BYTE, etc.
  51. #include <rxpdebug.h> // IF_DEBUG().
  52. #include <smbgtpt.h> // SmbGetUlong(), SmbGetUshort().
  53. #include <string.h> // strlen()
  54. // LPVOID
  55. // RxpGetUnalignedPointer(
  56. // IN LPVOID * Input
  57. // );
  58. //
  59. // This macro may have to change if we run on a big-endian machine.
  60. #if defined(_WIN64)
  61. LPVOID RxpGetUnalignedPointer( LPBYTE Input )
  62. {
  63. LARGE_INTEGER pointer;
  64. pointer.LowPart = SmbGetUlong( (LPDWORD)Input );
  65. pointer.HighPart = SmbGetUlong( (LPDWORD)(Input+4) );
  66. return (LPVOID)pointer.QuadPart;
  67. }
  68. #else
  69. #define RxpGetUnalignedPointer(Input) \
  70. ( (LPVOID) SmbGetUlong( (LPDWORD) (Input) ) )
  71. #endif
  72. NET_API_STATUS
  73. RxpPackSendBuffer(
  74. IN OUT LPVOID *SendBufferPointerPointer,
  75. IN OUT LPDWORD SendBufferLengthPointer,
  76. OUT LPBOOL AllocFlagPointer,
  77. IN LPDESC DataDesc16,
  78. IN LPDESC AuxDesc16,
  79. IN DWORD FixedSize16,
  80. IN DWORD AuxOffset,
  81. IN DWORD AuxLength,
  82. IN BOOL SetInfo
  83. )
  84. /*++
  85. Routine Description:
  86. RxpPackSendBuffer - set up the send buffer for transport across the net.
  87. This routine exists specifically to 'undo' some of the work done by
  88. RapConvertSingleEntry. The input buffer contains structures and variable
  89. data which are to be transmitted to a down-level server. The buffer
  90. contains 16-bit data with 32-bit pointers to variable data items WHICH ARE
  91. CONTAINED IN THE SAME BUFFER. RapConvertSingleEntry puts variable data in
  92. the buffer in the wrong order (see picture). Down-level servers expect
  93. variable data to be in the same order as described in the data descriptor
  94. strings. They assume this because they fix-up the pointers to the variable
  95. data based on knowing the start of the variable data, its type and length.
  96. It is for this reason that we must put the strings in the right order and
  97. it is this reason which mandates that WE DO NOT HAVE TO SUPPLY GOOD
  98. POINTERS OR OFFSETS in the pointer fields, since after this routine, nobody
  99. else cares about them
  100. We may get this: But down-level needs this:
  101. ---------------------- ----------------------
  102. | Primary structure | | Primary structure |
  103. | string pointer ------- | string pointer -------
  104. | string pointer ------| | string pointer ------|
  105. |--------------------| || |--------------------| ||
  106. | aux structure | || | aux structure | ||
  107. | string pointer -----|| | string pointer -----||
  108. | string pointer ----||| | string pointer ----|||
  109. |--------------------| |||| |--------------------| ||||
  110. | string # 4 | <-||| | string # 1 | <----
  111. |--------------------| ||| |--------------------| |||
  112. | string # 3 | <--|| | string # 2 | <---
  113. |--------------------| || |--------------------| ||
  114. | string # 2 | <---| | string # 3 | <--
  115. |--------------------| | |--------------------| |
  116. | string # 1 | <---- | string # 4 | <-
  117. ---------------------- ----------------------
  118. Assumes:
  119. 1. Only 1 primary structure in the send buffer
  120. 2. The down-level code DOES NOT ACTUALLY USE the pointer fields, but
  121. rather, performs its own-fixups & pointer generation based on the
  122. data descriptor and RELATIVE POSITION of variable data within the
  123. buffer, hence the need for re-ordering
  124. * IF THIS ASSUMPTION IS NOT VALID, THIS CODE IS POTENTIALLY BROKEN *
  125. 3. The action this routine performs is SPECIFICALLY to re-order the
  126. strings in the buffer as shown above. The routine
  127. RapConvertSingleEntry was used to pack the structures and variable
  128. data into the buffer. There is no spare space in the buffer
  129. 4. No other routines after this expect the pointer fields to be valid
  130. 5. Strings have already been converted from TCHARs to the correct
  131. codepage.
  132. 6. The pointers in the structure need not be on DWORD boundaries.
  133. Arguments:
  134. SendBufferPointerPointer - Points to pointer to the send data. This area
  135. will be reallocated if necessary, and the pointer updated.
  136. SendBufferLengthPointer - Points to the send data length. The caller sets
  137. this to the length of the area at SendBufferPointerPointer. If
  138. RxPackSendBuffer reallocates that memory, SendBufferLengthPointer will
  139. be updated to reflect the new length.
  140. AllocFlagPointer - Points to a BOOL which is set by this routine. To
  141. indicate that the send buffer memory has been reallocated.
  142. DataDesc16 - Gives descriptor string for data.
  143. AuxDesc16 - Gives descriptor string for aux structure.
  144. FixedSize16 - Gives size of fixed data structure, in bytes.
  145. AuxOffset - Gives position (offset) of N in data structure. (May be
  146. NO_AUX_DATA.)
  147. AuxLength - Gives size of aux structure in bytes.
  148. SetInfo - Indicates whether the API is a setinfo-type (or add-type).
  149. Return Value:
  150. NET_API_STATUS.
  151. --*/
  152. {
  153. LPBYTE struct_ptr;
  154. LPBYTE c_send_buf; // Caller's (original) send buffer.
  155. DWORD c_send_len; // Caller's (original) send buffer size.
  156. DWORD buf_length;
  157. DWORD to_send_len;
  158. DWORD num_aux;
  159. LPBYTE data_ptr;
  160. BOOL Reallocated;
  161. DWORD i,j;
  162. LPDESC l_dsc; // Pointer to each field's desc.
  163. LPDESC l_str; // Pointer to each desc (DataDesc16, then AuxDesc16).
  164. DWORD num_struct;
  165. DWORD len;
  166. DWORD num_its;
  167. DESC_CHAR c;
  168. //
  169. // we can't perform the string/variable data re-ordering in situ because
  170. // one or more of the strings will get trampled. We try and create a copy
  171. // of the input buffer to copy the variable data out of
  172. //
  173. LPBYTE duplicate_buffer = NULL;
  174. LPBYTE source_address; // source for copy
  175. DBG_UNREFERENCED_PARAMETER(SetInfo);
  176. //
  177. // Make local copies of the original start and length of the caller's
  178. // buffer as the originals may change if NetpMemoryReallocate is used but
  179. // they will still be needed for the RANGE_F check.
  180. //
  181. c_send_buf = *SendBufferPointerPointer; // caller's original buffer
  182. c_send_len = *SendBufferLengthPointer; // caller's original buffer length
  183. Reallocated = FALSE;
  184. //
  185. // Due to the specific nature of this routine, these checks should be
  186. // redundant since we have already worked out beforehand the requirements
  187. // for buffer size. PROVE THIS THEN DELETE THIS CODE
  188. //
  189. if ((c_send_len < FixedSize16) || (AuxOffset == FixedSize16)) {
  190. return NERR_BufTooSmall;
  191. }
  192. if (AuxOffset != NO_AUX_DATA) {
  193. num_aux = (WORD) SmbGetUshort( (LPWORD) (c_send_buf + AuxOffset) );
  194. to_send_len = FixedSize16 + (num_aux * AuxLength);
  195. //
  196. // see above about redundant code
  197. //
  198. if (c_send_len < to_send_len) {
  199. return NERR_BufTooSmall;
  200. }
  201. num_its = 2;
  202. } else {
  203. to_send_len = FixedSize16;
  204. num_aux = AuxLength = 0;
  205. num_its = 1; /* One structure type to look at */
  206. }
  207. IF_DEBUG(PACK) {
  208. NetpKdPrint(( "RxpPackSendBuffer: initial (fixed) buffer at "
  209. FORMAT_LPVOID ":\n", (LPVOID)c_send_buf));
  210. NetpDbgHexDump(c_send_buf, to_send_len);
  211. }
  212. //
  213. // get a duplicate copy of the original buffer. We will use this to copy
  214. // the variable data into. This buffer will be returned to the caller, not
  215. // the original!
  216. //
  217. buf_length = c_send_len; // buf_length may be reallocated (?)
  218. duplicate_buffer = NetpMemoryAllocate(buf_length);
  219. if (duplicate_buffer == NULL) {
  220. return ERROR_NOT_ENOUGH_MEMORY; // gasp!
  221. }
  222. //
  223. // Now copy the contents of the original buffer to the duplicate. The
  224. // duplicate will have pointers to the data in the original data buffer
  225. // that's why we copy from the original to the duplicate, fix up pointers
  226. // in the duplicate (even though we don't need to?) and return the
  227. // duplicate to the caller
  228. //
  229. NetpMoveMemory(duplicate_buffer, c_send_buf, c_send_len);
  230. //
  231. // struct_ptr point into duplicate_buffer. struct_ptr is updated to point
  232. // to the next field in the structure for every descriptor token in the
  233. // descriptor string
  234. //
  235. struct_ptr = duplicate_buffer;
  236. //
  237. // Set up the data pointer to point past fixed length structures. Note this
  238. // is in the duplicate structure - that's where we're going to copy the
  239. // data
  240. //
  241. data_ptr = duplicate_buffer + to_send_len;
  242. //
  243. // for the primary and aux structures, check any pointer designations
  244. // in the respective descriptor string and if not NULL copy the data
  245. // into the duplicate buffer
  246. //
  247. l_str = DataDesc16;
  248. num_struct = 1; /* Only one primary structure allowed */
  249. for (i = 0; i < num_its; l_str = AuxDesc16, num_struct = num_aux, i++) {
  250. for (j = 0 , l_dsc = l_str; j < num_struct; j++, l_dsc = l_str) {
  251. for (; (c = *l_dsc) != '\0'; l_dsc++) {
  252. IF_DEBUG(PACK) {
  253. NetpKdPrint(( "RxpPackSendBuffer: processing desc char '"
  254. FORMAT_DESC_CHAR "', struct ptr="
  255. FORMAT_LPVOID ".\n", c, struct_ptr ));
  256. }
  257. //
  258. // if the next field in the structure is a pointer type then
  259. // if it is not NULL, copy the data into the buffer
  260. //
  261. if (RapIsPointer(c)) {
  262. //
  263. // Get pointer value. Note that it may not be aligned!
  264. //
  265. source_address =
  266. (LPBYTE) RxpGetUnalignedPointer( struct_ptr );
  267. IF_DEBUG(PACK) {
  268. NetpKdPrint(( "RxpPackSendBuffer: "
  269. "got source address " FORMAT_LPVOID "\n",
  270. (LPVOID) source_address ));
  271. }
  272. //
  273. // Check for NULL pointer. If so then skip over this
  274. // field and continue
  275. //
  276. if (source_address == NULL) {
  277. struct_ptr += sizeof(LPBYTE *);
  278. IF_DEBUG(PACK) {
  279. NetpKdPrint(( "RxpPackSendBuffer: "
  280. "getting array len\n" ));
  281. }
  282. //
  283. // wind descriptor string forward to next field or
  284. // end of string
  285. //
  286. (void) RapArrayLength(l_dsc, &l_dsc, Both);
  287. IF_DEBUG(PACK) {
  288. NetpKdPrint(( "RxpPackSendBuffer: "
  289. "done getting array len\n" ));
  290. }
  291. } else {
  292. //
  293. // here if non-NULL pointer
  294. //
  295. switch( c ) {
  296. case REM_ASCIZ :
  297. case REM_ASCIZ_TRUNCATABLE:
  298. IF_DEBUG(PACK) {
  299. NetpKdPrint(( "RxpPackSendBuffer: "
  300. "getting string len\n" ));
  301. }
  302. //
  303. // Note: we don't have to handle UNICODE here,
  304. // as our caller has already done that.
  305. //
  306. len = strlen( (LPSTR) source_address ) + 1;
  307. //
  308. // Skip over maximum length count.
  309. //
  310. (void) RapArrayLength(l_dsc, &l_dsc, Both);
  311. IF_DEBUG(PACK) {
  312. NetpKdPrint(( "RxpPackSendBuffer: "
  313. "done getting string len\n" ));
  314. }
  315. break;
  316. case REM_SEND_LENBUF :
  317. len = *(LPWORD)source_address;
  318. break;
  319. default:
  320. len = RapArrayLength(l_dsc, &l_dsc, Both);
  321. }
  322. /* There is data to be copied into the send
  323. * buffer so check that it will fit.
  324. */
  325. //
  326. // This shouldn't happen (I think). If it does,
  327. // it suggests we made a miscalculation somewhere. IF
  328. // THAT'S THE CASE, FIND THE MISCALCULATION AND REMOVE
  329. // THIS CODE
  330. //
  331. if ((to_send_len += len) > buf_length) {
  332. LPBYTE ptr;
  333. #ifdef DBG
  334. //
  335. // let me know what's going on. Again, if this
  336. // happens then we should check other code to
  337. // ensure it can't be helped. In theory, before
  338. // we got here (this routine), we calculated all
  339. // the data requirements and allocated a buffer
  340. // sufficient to hold everything. Hence we should
  341. // not need to re-allocate
  342. //
  343. NetpKdPrint(("WARNING: attempting re-allocation of "
  344. "data buffer. Shouldn't be doing this?\n"
  345. ));
  346. NetpBreakPoint();
  347. #endif
  348. buf_length = to_send_len + BUF_INC;
  349. //
  350. // note: if this fails then I assume the
  351. // original pointer in *SendBufferPointerPointer
  352. // is still valid and the caller will still
  353. // free it
  354. //
  355. ptr = (LPBYTE)NetpMemoryReallocate(duplicate_buffer,
  356. buf_length);
  357. if (!ptr) {
  358. NetpMemoryFree(duplicate_buffer);
  359. return ERROR_NOT_ENOUGH_MEMORY; // gasp!
  360. }
  361. //
  362. // let caller know buffer he gets back may not
  363. // be same as that passed in. Although, this
  364. // shouldn't be a problem.
  365. // Footnote: *Why* do we indicate this fact?
  366. //
  367. Reallocated = TRUE;
  368. //
  369. // re-fix various pointers. We can't make any
  370. // assumptions about ptr (can we?)
  371. //
  372. duplicate_buffer = ptr;
  373. struct_ptr = ptr + (struct_ptr - duplicate_buffer);
  374. data_ptr = ptr + (data_ptr - duplicate_buffer);
  375. }
  376. /* There is room for new data in buffer so copy
  377. * it and and update the struct and data ptrs
  378. */
  379. IF_DEBUG(PACK) {
  380. NetpKdPrint(( "RxpPackSendBuffer: moving...\n"));
  381. }
  382. NetpMoveMemory(data_ptr, source_address, len);
  383. IF_DEBUG(PACK) {
  384. NetpKdPrint(( "RxpPackSendBuffer: moved.\n"));
  385. }
  386. //
  387. // update data_ptr to point to the next place to copy
  388. // data in duplicate_buffer. Bump the fixed structure
  389. // pointer to the next field
  390. //
  391. data_ptr += len;
  392. struct_ptr += sizeof(LPBYTE*);
  393. }
  394. } else {
  395. //
  396. // here if the next thing in the descriptor does not identify
  397. // a pointer
  398. //
  399. //
  400. // adjust the structure pointer to the next field
  401. //
  402. struct_ptr += RapGetFieldSize(l_dsc, &l_dsc, Both);
  403. }
  404. }
  405. }
  406. }
  407. /* Finished process send data, avoid sending the free space at
  408. * the end of the buffer by reducing send_data_length to
  409. * send_length.
  410. */
  411. IF_DEBUG(PACK) {
  412. NetpKdPrint(( "RxpPackSendBuffer: final buffer at "
  413. FORMAT_LPVOID ":\n", (LPVOID) struct_ptr ));
  414. NetpDbgHexDump(duplicate_buffer, to_send_len );
  415. }
  416. //
  417. // return to the caller the new address of his buffer - this will always
  418. // be duplicate_buffer. If we had to reallocate (and we shouldn't!) return
  419. // the size of the new buffer
  420. //
  421. *SendBufferPointerPointer = duplicate_buffer; // May have been reallocated.
  422. *SendBufferLengthPointer = to_send_len;
  423. *AllocFlagPointer = Reallocated; // caller doesn't need to know this!
  424. //
  425. // free the caller's original buffer. We now have a buffer which has the
  426. // strings in the correct order. However, it is not the same buffer as that
  427. // which the user passed in, nor are any of the pointer fields valid. See
  428. // assumption 2 above
  429. //
  430. NetpMemoryFree(c_send_buf);
  431. return NERR_Success;
  432. } // RxpPackSendBuffer