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.

534 lines
19 KiB

  1. /*++
  2. Copyright (c) 1987-1993 Microsoft Corporation
  3. Module Name:
  4. Remote.c
  5. Abstract:
  6. Provides a support routine, RxRemoteAPI, for transporting
  7. an API request to a remote API worker and translating its response.
  8. Author:
  9. John Rogers (JohnRo) and a cast of thousands.
  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. Created portable LanMan (NT) version from LanMan 2.x.
  16. 03-May-1991 JohnRo
  17. Really pass COPY of parm desc to convert args, like it expects.
  18. Also pass it UNC server name (\\stuff) for ease of use.
  19. Add check for valid computer name.
  20. Use Unicode transitional types.
  21. Changed to use three data descs: 16-bit, 32-bit and SMB versions.
  22. Fixed receive buffer length problem.
  23. RcvDataPresent flag is not needed.
  24. Use RxpFatalErrorCode() rather than checking for specific errors.
  25. Quiet debug output by default.
  26. Reduced recompile hits from header files.
  27. Don't use NET_API_FUNCTION for non-APIs.
  28. 07-May-1991 JohnRo
  29. Made changes to reflect CliffV's code review.
  30. Add validation of parm desc.
  31. 09-May-1991 JohnRo
  32. Made LINT-suggested changes.
  33. 14-May-1991 JohnRo
  34. Pass 3 aux descriptors to RxRemoteApi.
  35. 29-May-1991 JohnRo
  36. Handle SendDataPtr16 and SendDataSize16 correctly for setinfo.
  37. Print status if ConvertArgs failed.
  38. 13-Jun-1991 JohnRo
  39. RxpConvertArgs needs DataDesc16 and AuxDesc16 to fix server set info
  40. for level 102.
  41. 16-Jul-1991 JohnRo
  42. Allow receive data buffer to be zero bytes long with nonnull pointer.
  43. 17-Jul-1991 JohnRo
  44. Extracted RxpDebug.h from Rxp.h.
  45. 16-Aug-1991 rfirth
  46. Changed interface (NoPermissionRequired => Flags)
  47. 25-Sep-1991 JohnRo
  48. Quiet normal debug messages.
  49. 21-Nov-1991 JohnRo
  50. Removed NT dependencies to reduce recompiles.
  51. 27-Nov-1991 JohnRo
  52. Do some checking of ApiNumber.
  53. 31-Mar-1992 JohnRo
  54. Prevent too large size requests.
  55. 06-May-1993 JohnRo
  56. RAID 8849: Export RxRemoteApi for DEC and others.
  57. Use NetpKdPrint() where possible.
  58. Use PREFIX_ equates.
  59. --*/
  60. // These must be included first:
  61. #include <windef.h> // IN, DWORD, LPTSTR, etc.
  62. #include <rxp.h> // Private header file.
  63. // These may be included in any order:
  64. #include <apiworke.h> // REM_MAX_PARMS.
  65. #include <limits.h> // CHAR_BIT.
  66. #include <lmerr.h> // NERR_ and ERROR_ equates.
  67. #include <names.h> // NetpIsComputerNameValid().
  68. #include <netdebug.h> // NetpKdPrint(), FORMAT_ equates, etc.
  69. #include <netlib.h> // NetpMemoryFree(), etc.
  70. #include <prefix.h> // PREFIX_ equates.
  71. #include <rap.h> // RapIsValidDescriptorSmb().
  72. #include <rx.h> // My prototype, etc.
  73. #include <rxpdebug.h> // IF_DEBUG().
  74. NET_API_STATUS
  75. RxRemoteApi(
  76. IN DWORD ApiNumber,
  77. IN LPCWSTR UncServerName, // this is not OPTIONAL!
  78. IN LPDESC ParmDescString,
  79. IN LPDESC DataDesc16 OPTIONAL,
  80. IN LPDESC DataDesc32 OPTIONAL,
  81. IN LPDESC DataDescSmb OPTIONAL,
  82. IN LPDESC AuxDesc16 OPTIONAL,
  83. IN LPDESC AuxDesc32 OPTIONAL,
  84. IN LPDESC AuxDescSmb OPTIONAL,
  85. IN DWORD Flags,
  86. ... // rest of API's arguments
  87. )
  88. // Define equate for last named (non-variable) argument, for use with
  89. // va_start macro.
  90. #define LAST_NAMED_ARGUMENT Flags
  91. /*++
  92. Routine Description:
  93. RxRemoteApi (which is analogous to LanMan's NetIRemoteAPI) formats
  94. parameter and data buffers for transporting a local API request to a
  95. remote API worker and translates the remote response into the local
  96. equivalent.
  97. Arguments:
  98. ApiNumber - Function number of the API required.
  99. ServerName - Points to the name of server this API is to be executed on.
  100. This MUST begin with "\\".
  101. ParmDescString - A pointer to a ASCIIZ string describing the API call
  102. parameters (other than server name).
  103. DataDesc16 - A pointer to a ASCIIZ string describing the
  104. structure of the data in the call, i.e. the return data structure
  105. for a Enum or GetInfo call. This string is used for adjusting pointers
  106. to data in the local buffers after transfer across the net. If there
  107. is no structure involved in the call then DataDesc16 must be
  108. a NULL pointer. DataDesc16 is a "modified" 16-bit descriptor,
  109. which may contain "internal use only" characters.
  110. DataDesc32 - A pointer to the 32-bit version of DataDesc16. Must be NULL
  111. iff DataDesc16 is NULL.
  112. DataDescSmb - An optional pointer to the SMB version of DataDesc16.
  113. This must not contain any "internal use only" characters. Must be NULL
  114. iff DataDesc16 is NULL.
  115. AuxDesc16, AuxDesc32, AuxDescSmb - Will be NULL in most cases unless a
  116. REM_AUX_COUNT descriptor char is present in the data descriptors in
  117. which case these descriptors define a secondary data format as
  118. DataDesc16/DataDescSmb define the primary.
  119. Flags - bitmap of various control flags. Currently defined are:
  120. NO_PERMISSION_REQUIRED (0x1) - This flag is TRUE if this API does not
  121. require any permission on the remote machine, and that a null session
  122. is to be used for this request.
  123. ALLOCATE_RESPONSE (0x2) - Set if this routine and its subordinates
  124. (viz RxpConvertArgs, RxpConvertBlock) allocate a response buffer.
  125. We do this because at this level we know how much data is returned
  126. from the down-level server in an Enum or GetInfo call. We can therefore
  127. better estimate the size of buffer to allocate and return to the caller
  128. with 32-bit data than can the individual RxNet routines. The upshot of
  129. this is that we waste less space
  130. ... - The remainder of the parameters for the API call as given by the
  131. application. (The "..." notation is from ANSI C, and refers to a
  132. variable argument list. These arguments will be processing using the
  133. ANSI <stdarg.h> macros.)
  134. Return Value:
  135. NET_API_STATUS.
  136. --*/
  137. {
  138. BYTE parm_buf[REM_MAX_PARMS]; // Parameter buffer
  139. LPDESC ParmDescCopy; // Copy of parm desc in buffer.
  140. LPBYTE parm_pos; // Pointer into parm_buf
  141. va_list ParmPtr; // Pointer to stack parms.
  142. DWORD parm_len; // Length of send parameters
  143. DWORD ret_parm_len; // Length of expected parms
  144. DWORD rcv_data_length; // Length of caller's rcv buf
  145. LPVOID rcv_data_ptr; // Pointer to callers rcv buf
  146. LPVOID SendDataPtr16; // Ptr to send buffer to use
  147. DWORD SendDataSize16; // Size of caller's send buf
  148. LPBYTE SmbRcvBuffer = NULL; // Rcv buffer, 16-bit version.
  149. DWORD SmbRcvBufferLength; // Length of the above.
  150. NET_API_STATUS Status; // Return status from remote.
  151. LPTSTR TransportName = NULL; // Optional transport name.
  152. IF_DEBUG(REMOTE) {
  153. NetpKdPrint(( PREFIX_NETAPI
  154. "RxRemoteApi: entered, api num " FORMAT_DWORD "...\n",
  155. ApiNumber ));
  156. }
  157. //
  158. // Make sure API number doesn't get truncated.
  159. // Note that we can't check against the MAX_API equate anymore, as
  160. // that only includes APIs which we know about. Now that RxRemoteApi is
  161. // being exported for use by anyone, we don't know the maximum API number
  162. // which the app might be using.
  163. //
  164. if ( ((DWORD)(WORD)ApiNumber) != ApiNumber ) {
  165. NetpKdPrint(( PREFIX_NETAPI
  166. "RxpStartBuildingTransaction: API NUMBER "
  167. "(" FORMAT_HEX_DWORD ") TOO LARGE, "
  168. "returning ERROR_INVALID_PARAMETER.\n",
  169. ApiNumber ));
  170. return (ERROR_INVALID_PARAMETER);
  171. }
  172. #if DBG
  173. // Code in this file depends on 16-bit words; the Remote Admin Protocol
  174. // demands it.
  175. NetpAssert( ( (sizeof(WORD)) * CHAR_BIT) == 16);
  176. // We are removing these for the time being because the delay load handler for this
  177. // function returns FALSE by default, so the ASSERT will fire incorrectly. For a future
  178. // release, we should change our delayload handler.
  179. //NetpAssert(RapIsValidDescriptorSmb(ParmDescString));
  180. if (DataDescSmb != NULL) {
  181. //NetpAssert(RapIsValidDescriptorSmb(DataDescSmb));
  182. NetpAssert(DataDesc16 != NULL);
  183. NetpAssert(DataDesc32 != NULL);
  184. } else {
  185. NetpAssert(DataDesc16 == NULL);
  186. NetpAssert(DataDesc32 == NULL);
  187. }
  188. if (AuxDescSmb != NULL) {
  189. //NetpAssert(RapIsValidDescriptorSmb(AuxDescSmb));
  190. NetpAssert(AuxDesc16 != NULL);
  191. NetpAssert(AuxDesc32 != NULL);
  192. } else {
  193. NetpAssert(AuxDesc16 == NULL);
  194. NetpAssert(AuxDesc32 == NULL);
  195. }
  196. #endif
  197. if (! NetpIsUncComputerNameValid((LPWSTR)UncServerName)) {
  198. return (NERR_InvalidComputer);
  199. }
  200. //
  201. // Set found parameter flags to FALSE and pointers to NULL.
  202. //
  203. rcv_data_length = 0;
  204. rcv_data_ptr = NULL;
  205. //
  206. // First build the parameter block which will be sent to the API
  207. // worker. This consists of the two descriptor strings, ParmDescString
  208. // and DataDescSmb, followed by the parameters (or the data pointed
  209. // to by the parameters) that were passed to RxRemoteApi.
  210. //
  211. parm_pos = parm_buf; // Start of parameter buffer.
  212. parm_len = 0;
  213. ret_parm_len = 2* sizeof(WORD); // Allow for return status & converter.
  214. Status = RxpStartBuildingTransaction(
  215. parm_buf, // buffer start
  216. REM_MAX_PARMS, // buffer len
  217. ApiNumber, // API number
  218. ParmDescString, // parm desc (original)
  219. DataDescSmb, // data desc (SMB version)
  220. (LPVOID *)&parm_pos, // roving output ptr
  221. & parm_len, // curr output len (updated)
  222. NULL, // last string ptr (don't care)
  223. & ParmDescCopy); // ptr to parm desc copy
  224. if (Status != NERR_Success) {
  225. //
  226. // Consider increasing REM_MAX_PARMS...
  227. //
  228. NetpKdPrint(( PREFIX_NETAPI
  229. "RxRemoteApi: Buffer overflow!\n" ));
  230. NetpBreakPoint();
  231. return (Status);
  232. }
  233. //
  234. // Set up ParmPtr to point to first of the caller's parameters.
  235. //
  236. va_start(ParmPtr, LAST_NAMED_ARGUMENT);
  237. //
  238. // If this API has specified a transport name, load the transport
  239. // name from the first parameter.
  240. //
  241. if (Flags & USE_SPECIFIC_TRANSPORT) {
  242. //
  243. // Set up ParmPtr to point to first of the caller's parameters.
  244. //
  245. TransportName = va_arg(ParmPtr, LPTSTR);
  246. }
  247. //
  248. // Build the rest of the transaction by converting the rest of the
  249. // 32-bit arguments.
  250. //
  251. Status = RxpConvertArgs(
  252. ParmDescCopy, // copy of desc, in SMB buf, will be updated.
  253. DataDesc16,
  254. DataDesc32,
  255. DataDescSmb,
  256. AuxDesc16,
  257. AuxDesc32,
  258. AuxDescSmb,
  259. REM_MAX_PARMS, // MaximumInputBlockLength
  260. REM_MAX_PARMS, // MaximumOutputBlockLength
  261. & ret_parm_len, // curr inp blk len (updated)
  262. & parm_len, // curr output len (updated)
  263. & parm_pos, // curr output ptr (updated)
  264. & ParmPtr, // rest of API's arguments (after server name)
  265. & SendDataSize16, // caller's send buff siz (set)
  266. (LPBYTE *) & SendDataPtr16, // caller's send buff (set)
  267. & rcv_data_length, // caller's rcv buff len (set)
  268. //
  269. // WARNING: Added complexity. Unfortunate, but there you go.
  270. // If we are to allocate the 32-bit received data buffer for
  271. // the caller then the value passed back in rcv_data_ptr will
  272. // be the address of the caller's pointer to the buffer.
  273. // Although this makes things more difficult to understand
  274. // down here, it simplifies life for the caller. Such is the
  275. // lot of the (put upon) systems programmer...
  276. //
  277. (LPBYTE *)&rcv_data_ptr, // caller's rcv buff (set)
  278. Flags
  279. );
  280. va_end(ParmPtr);
  281. //NetpAssert(RapIsValidDescriptorSmb(ParmDescCopy));
  282. if (Status != NERR_Success) {
  283. NetpKdPrint(( PREFIX_NETAPI
  284. "RxRemoteApi: RxpConvertArgs failed, status="
  285. FORMAT_API_STATUS "\n", Status ));
  286. return (Status);
  287. }
  288. IF_DEBUG(REMOTE) {
  289. NetpKdPrint(( PREFIX_NETAPI
  290. "RxRemoteApi: RxpConvertArgs says r.data.len=" FORMAT_DWORD
  291. "\n", rcv_data_length ));
  292. NetpKdPrint(( PREFIX_NETAPI
  293. "RxRemoteApi: RxpConvertArgs says r.parm.len=" FORMAT_DWORD
  294. "\n", ret_parm_len ));
  295. }
  296. //
  297. // Set SmbRcvBuffer, and SmbRcvBufferLength to some appropriate values.
  298. // Because we now allow the final 32-bit receive buffer to be allocated
  299. // somewhere along the codepath of this routine, it is legal to have a
  300. // non-zero receive data length with a meaningless receive data pointer
  301. // (which could be NULL)
  302. //
  303. if (rcv_data_length != 0) {
  304. //
  305. // Allocate the SMB receive buffer.
  306. //
  307. SmbRcvBufferLength = rcv_data_length;
  308. SmbRcvBuffer = NetpMemoryAllocate( SmbRcvBufferLength );
  309. if (SmbRcvBuffer == NULL) {
  310. return ERROR_NOT_ENOUGH_MEMORY;
  311. }
  312. #if DBG
  313. IF_DEBUG(REMOTE) {
  314. NetpKdPrint(( PREFIX_NETAPI
  315. "RxRemoteApi: allocated " FORMAT_DWORD
  316. " bytes as SmbRcvBuffer @ " FORMAT_LPVOID "\n",
  317. SmbRcvBufferLength, (LPVOID) SmbRcvBuffer ));
  318. }
  319. #endif
  320. } else {
  321. //
  322. // Allow zero-length receive data buffer with nonnull addr.
  323. //
  324. SmbRcvBufferLength = 0;
  325. SmbRcvBuffer = NULL;
  326. //
  327. // Don't understand the commentary here: its not a nonnull addr., and
  328. // as far as I can tell never has been. JR?
  329. // RLF 8-19
  330. //
  331. IF_DEBUG(REMOTE) {
  332. NetpKdPrint(( PREFIX_NETAPI
  333. "RxRemoteApi: using 0 len buffer w/ nonnull addr.\n" ));
  334. }
  335. }
  336. //
  337. // The parameter buffers and data buffers are now set up for
  338. // sending to the API worker so call RxpTransactSmb to send them.
  339. //
  340. NetpAssert( parm_len <= MAX_TRANSACT_SEND_PARM_SIZE );
  341. NetpAssert( SendDataSize16 <= MAX_TRANSACT_SEND_DATA_SIZE );
  342. NetpAssert( ret_parm_len <= MAX_TRANSACT_RET_PARM_SIZE );
  343. NetpAssert( SmbRcvBufferLength <= MAX_TRANSACT_RET_DATA_SIZE );
  344. Status = RxpTransactSmb(
  345. (LPWSTR)UncServerName, // computer name
  346. TransportName,
  347. parm_buf, // Send parm buffer
  348. parm_len, // Send parm length
  349. SendDataPtr16, // Send data buffer
  350. SendDataSize16, // Send data size
  351. parm_buf, // Rcv prm buffer
  352. ret_parm_len, // Rcv parm length
  353. SmbRcvBuffer, // Rcv data buffer
  354. &SmbRcvBufferLength, // Rcv data length (returned actual bytes read)
  355. //
  356. // NoPermissionRequired is now a bit in the Flags word
  357. //
  358. (BOOL)(Flags & NO_PERMISSION_REQUIRED)
  359. );
  360. #if DBG
  361. IF_DEBUG(REMOTE) {
  362. NetpKdPrint(( PREFIX_NETAPI
  363. "RxRemoteApi: back from RxpTransactSmb, status="
  364. FORMAT_API_STATUS "\n", Status ));
  365. }
  366. NetpAssert( SmbRcvBufferLength <= rcv_data_length );
  367. if (SmbRcvBuffer == NULL) {
  368. NetpAssert( SmbRcvBufferLength == 0 );
  369. }
  370. #endif
  371. if (Status != NERR_Success) {
  372. switch (Status) {
  373. case NERR_BufTooSmall: // No data returned from API worker
  374. rcv_data_length = 0;
  375. break;
  376. case ERROR_MORE_DATA: // Just a warning for the caller
  377. break;
  378. case NERR_TooMuchData: // Just a warning for the caller
  379. break;
  380. default:
  381. rcv_data_length = 0;
  382. break;
  383. }
  384. }
  385. NetpAssert( SmbRcvBufferLength <= MAX_TRANSACT_RET_DATA_SIZE );
  386. // The API call was successful. Now translate the return buffers
  387. // into the local API format.
  388. //
  389. // If we didn't have some fatal error (e.g. unable to talk to the remote
  390. // machine at all), then convert back... Note that fatal errors don't
  391. // include statuses returned by the remote machine.
  392. //
  393. if (! RxpFatalErrorCode(Status)) {
  394. //
  395. // Set up ParmPtr to point to first of the caller's parameters.
  396. //
  397. va_start(ParmPtr, LAST_NAMED_ARGUMENT);
  398. if (Flags & USE_SPECIFIC_TRANSPORT) {
  399. //
  400. // Skip over the first argument - it's the transport.
  401. //
  402. (VOID) va_arg(ParmPtr, LPTSTR);
  403. }
  404. Status = RxpConvertBlock(
  405. ApiNumber,
  406. parm_buf, // response blk
  407. ParmDescString, // parm desc (original)
  408. DataDesc16,
  409. DataDesc32,
  410. AuxDesc16,
  411. AuxDesc32,
  412. & ParmPtr, // rest of API's args
  413. SmbRcvBuffer, // 16-bit version of rcv buff
  414. SmbRcvBufferLength, // amount of BYTES in SmbRcvBuffer
  415. //
  416. // WARNING: Increased complexity. If the ALLOCATE_RESPONSE
  417. // flag is set, then the caller supplied us with the address
  418. // of the pointer to the buffer (which is about to be
  419. // allocated in RxpConvertBlock). Else, rcv_data_ptr is
  420. // the address of the buffer that the caller has already
  421. // allocated before calling this routine
  422. //
  423. rcv_data_ptr, // native version of rcv buff
  424. rcv_data_length, // length of the above
  425. Flags // allocate a 32-bit response buffer?
  426. );
  427. va_end(ParmPtr);
  428. //
  429. // Don't check Status; we'll just return it to caller.
  430. //
  431. }
  432. if (SendDataPtr16 != NULL) {
  433. NetpMemoryFree(SendDataPtr16); // If add'l mem alloc'ed, free it.
  434. }
  435. if (SmbRcvBuffer != NULL) {
  436. NetpMemoryFree(SmbRcvBuffer);
  437. }
  438. return(Status); // Return status from RxpConvertBlock or
  439. // RxpTransactSmb.
  440. } // RxRemoteApi