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.

444 lines
16 KiB

  1. /*++
  2. Copyright (c) 1987-92 Microsoft Corporation
  3. Module Name:
  4. Transact.c
  5. Abstract:
  6. RxpTransactSmb (analogous to the LanMan 2.x transact routine) performs a
  7. transaction FSCTL to the redirector.
  8. Author:
  9. John Rogers (JohnRo) 01-Apr-1991 (NT version only)
  10. Environment:
  11. Only runs under NT, although the interface is portable (Win/32).
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. various
  15. Original code (from LanMan 2.x).
  16. 01-Apr-91 JohnRo
  17. Converted code from LanMan (OS/2) to NT.
  18. 02-Apr-1991 JohnRo
  19. Moved NetpRdrFsControlTree to <netlibnt.h>.
  20. 17-Apr-1991 JohnRo
  21. Fixed memory leaks (especially with pipe name).
  22. Quiet debug output by default.
  23. Reduced recompile hits from header files.
  24. 03-May-1991 JohnRo
  25. Pass UNC server name for ease of use. Use Unicode transitional types.
  26. Use UNREFERENCED_PARAMETER() macro.
  27. 15-May-1991 JohnRo
  28. Use FORMAT_LPVOID instead of FORMAT_POINTER, for maximum portability.
  29. 22-May-1991 JohnRo
  30. Use correct string handling functions to allow UNICODE.
  31. Use NetpDbgReasonable().
  32. 14-Jul-1991 JohnRo
  33. Don't do assert on server name.
  34. 17-Jul-1991 JohnRo
  35. Extracted RxpDebug.h from Rxp.h.
  36. 04-Oct-1991 JohnRo
  37. Generate NERR_BadTransactConfig when IPC$ isn't shared.
  38. Clarified a debug output message. Use TEXT() macro.
  39. 01-Nov-1991 JohnRo
  40. Don't let the new (paranoid) RxpFatalErrorCode() prevent debug output.
  41. 16-Jan-1992 JohnRo
  42. The redirector always expects UNICODE for the transact parm name.
  43. 31-Mar-1992 JohnRo
  44. Prevent too large size requests.
  45. 22-Sep-1992 JohnRo
  46. RAID 6739: Browser too slow when not logged into browsed domain.
  47. --*/
  48. // These must be included first:
  49. #include <nt.h> // Needed by netlibnt.h.
  50. #include <rxp.h> // RpcXlate's private header file.
  51. // These may be included in any order:
  52. #include <apiworke.h> // REM_APITXT, APIEXTR.
  53. #include <lmerr.h> // NERR_ and ERROR_ equates.
  54. #include <names.h> // NetpIsComputerNameValid().
  55. #include <netdebug.h> // NetpAssert(), NetpKdPrint(()), FORMAT_ equates.
  56. #include <netlib.h> // NetpMoveMemory(), etc.
  57. #include <ntddnfs.h> // TRANSACTION_REQUEST, etc.
  58. #include <prefix.h> // PREFIX_ equates.
  59. #include <rxpdebug.h> // IF_DEBUG().
  60. #include <tstring.h> // STRCAT(), STRCPY(), STRLEN().
  61. #include <lmuse.h>
  62. #ifdef CDEBUG
  63. #include <apinums.h> // API_WServerGetInfo, etc.
  64. #include <netlib.h> // NetpPackString().
  65. #include <smbgtpt.h> // SmbGetUshort().
  66. #include <server.h> // SERVER_INFO_100.
  67. #endif // CDEBUG
  68. #include <netlibnt.h> // NetpRdrFsControlTree().
  69. NET_API_STATUS
  70. RxpTransactSmb(
  71. IN LPTSTR UncServerName,
  72. IN LPTSTR TransportName OPTIONAL,
  73. IN LPVOID SendParmPtr,
  74. IN DWORD SendParmLen,
  75. IN LPVOID SendDataPtr OPTIONAL,
  76. IN DWORD SendDataLen,
  77. OUT LPVOID RetParmPtr OPTIONAL,
  78. IN DWORD RetParmLen,
  79. OUT LPVOID RetDataPtr OPTIONAL,
  80. IN OUT LPDWORD RetDataLen,
  81. IN BOOL NoPermissionRequired
  82. )
  83. /*++
  84. Routine Description:
  85. RxpTransactSmb takes the caller's parameters and builds a transaction
  86. SMB which is sent to a remote machine. This routine waits for the
  87. response to this SMB and returns the status from it.
  88. Arguments:
  89. UncServerName - Server name to transact with (including \\).
  90. SendParmPtr - Pointer to send parameters.
  91. SendParmLen - Length of send parameters.
  92. SendDataPtr - Optional pointer to send data.
  93. SendDataLen - Send data length.
  94. RetParmPtr - Optional pointer to buffer for return parameters.
  95. RetParmLen - Expected length of return parameters.
  96. RetDataPtr - Optional pointer to buffer for return data.
  97. RetDataLen - IN: Expected length of return data.
  98. OUT: Received length of return data.
  99. NoPermissionRequired - TRUE if this is a no permission required API. (I.e.
  100. TRUE if the null session may be used.)
  101. Return Value:
  102. (various values as returned by the remote API, plus values which can
  103. be generated by this routine)
  104. --*/
  105. /*
  106. * Note 1: how the packet is build and sized.
  107. *
  108. * The paramater buffer for the transaction consists of the
  109. * transaction parameter structure, followed by the name of the
  110. * target pipe and the password, which is always NULL. The pipe
  111. * name and password are ASCIZ strings.
  112. *
  113. * We build the pipe by taking the canonicalized server name, and
  114. * appending the text REM_APITXT (see net/inc/apiworke.h). This text
  115. * contains the pipe suffix (\pipe\lanman) plus TWO nulls, one to
  116. * terminate the pipe name and one to terminate the (empty) password.
  117. *
  118. * So, the maximum buffer size is as shown below for the allocation
  119. * of ioctl_buf. UNCLEN is the max len of the canonicalized
  120. * UncServerName and includes the two leading slashes, but not any
  121. * terminating NUL. The terminating NUL, as well as the pipe suffix
  122. * and the emptry password, are accounted for in APIEXTR.
  123. *
  124. * Our actual size is the same, except substitute the length of the
  125. * canonicalized UncServerName for UNCLEN. This is how ParmRktLen is
  126. * calculated.
  127. *
  128. */
  129. {
  130. #ifndef CDEBUG
  131. PLMR_TRANSACTION FsctlParms; // Parms to tell redir what to do.
  132. DWORD FsctlParmSize; // Size of FsctlParms and strings.
  133. LPTSTR TreeConnName; // LM-style server & share name.
  134. #endif // ndef CDEBUG
  135. NET_API_STATUS Status;
  136. //
  137. // MOD 06/11/91 RLF
  138. // Create DWORD variable to avoid indirection every time RetDataLen accessed
  139. //
  140. DWORD InputRetDataLen = *RetDataLen;
  141. //
  142. // MOD 06/11/91 RLF
  143. //
  144. IF_DEBUG(TRANSACT) {
  145. NetpKdPrint(( PREFIX_NETAPI
  146. "RxpTransactSmb: entered, servername='"
  147. FORMAT_LPTSTR "'...\n", UncServerName));
  148. NetpKdPrint(( PREFIX_NETAPI
  149. "RxpTransactSmb: SendParm at " FORMAT_LPVOID
  150. ", len=" FORMAT_DWORD " (partial):\n",
  151. (LPVOID) SendParmPtr, SendParmLen));
  152. if (SendParmPtr != NULL) {
  153. NetpDbgHexDump(SendParmPtr, NetpDbgReasonable(SendParmLen));
  154. }
  155. NetpKdPrint(( PREFIX_NETAPI
  156. "RxpTransactSmb: SendData at " FORMAT_LPVOID
  157. ", len=" FORMAT_DWORD " (partial):\n",
  158. (LPVOID) SendDataPtr, SendDataLen));
  159. if (SendDataPtr != NULL) {
  160. NetpDbgHexDump(SendDataPtr, NetpDbgReasonable(SendDataLen));
  161. }
  162. NetpKdPrint(( PREFIX_NETAPI
  163. "RxpTransactSmb: RetParmPtr at " FORMAT_LPVOID
  164. ", len=" FORMAT_DWORD ".\n", (LPVOID) RetParmPtr, RetParmLen));
  165. NetpKdPrint(( PREFIX_NETAPI
  166. "RxpTransactSmb: (old) RetData at " FORMAT_LPVOID ", "
  167. "len=" FORMAT_DWORD " (partial):\n",
  168. (LPVOID) RetDataPtr, InputRetDataLen));
  169. if (RetDataPtr != NULL) {
  170. NetpDbgHexDump(RetDataPtr, NetpDbgReasonable(InputRetDataLen));
  171. }
  172. }
  173. NetpAssert( SendParmLen <= MAX_TRANSACT_SEND_PARM_SIZE );
  174. NetpAssert( SendDataLen <= MAX_TRANSACT_SEND_DATA_SIZE );
  175. NetpAssert( RetParmLen <= MAX_TRANSACT_RET_PARM_SIZE );
  176. NetpAssert( InputRetDataLen <= MAX_TRANSACT_RET_DATA_SIZE );
  177. // Assumes that isremote(UncServerName) has already checked for
  178. // a NULL and empty string.
  179. if ((UncServerName == NULL) || (UncServerName[0] == 0)) {
  180. NetpBreakPoint();
  181. return (NERR_InternalError);
  182. }
  183. if (! NetpIsUncComputerNameValid(UncServerName)) {
  184. return (NERR_InvalidComputer);
  185. }
  186. IF_DEBUG(TRANSACT) {
  187. NetpKdPrint(( PREFIX_NETAPI
  188. "RxpTransactSmb: pipe name is '" FORMAT_LPWSTR
  189. "'.\n", REM_APITXT));
  190. }
  191. #ifndef CDEBUG
  192. //
  193. // Build NT-style name for what we're connecting to. Note that there is
  194. // NOT a pair of backslashes anywhere in this name.
  195. //
  196. {
  197. DWORD NameSize =
  198. // /Device/LanManRedirector /server /IPC$\0
  199. ( strlen(DD_NFS_DEVICE_NAME) + STRLEN(UncServerName)-1 + 6 )
  200. * sizeof(TCHAR);
  201. TreeConnName = NetpMemoryAllocate( NameSize );
  202. }
  203. if (TreeConnName == NULL) {
  204. return (ERROR_NOT_ENOUGH_MEMORY);
  205. }
  206. //
  207. // Build the tree connect name.
  208. //
  209. (void) STRCPY(TreeConnName, UncServerName); // copy "\\server",
  210. (void) STRCAT(TreeConnName, (LPTSTR) TEXT("\\IPC$")); // then "\share".
  211. IF_DEBUG(TRANSACT) {
  212. NetpKdPrint(( PREFIX_NETAPI
  213. "RxpTransactSmb: TreeConnName is '" FORMAT_LPTSTR
  214. "'.\n", TreeConnName));
  215. }
  216. // Set FsctlParmSize and allocate fsctl structure.
  217. FsctlParmSize = sizeof(LMR_TRANSACTION) + (APIEXTR);
  218. FsctlParms = NetpMemoryAllocate(FsctlParmSize);
  219. if (FsctlParms == NULL) {
  220. NetpMemoryFree(TreeConnName);
  221. return (ERROR_NOT_ENOUGH_MEMORY);
  222. }
  223. IF_DEBUG(TRANSACT) {
  224. NetpKdPrint(( PREFIX_NETAPI
  225. "RxpTransactSmb: allocated " FORMAT_DWORD
  226. " bytes for fsctl parms at "
  227. FORMAT_LPVOID ".\n", FsctlParmSize, (LPVOID) FsctlParms));
  228. }
  229. FsctlParms->Type = TRANSACTION_REQUEST;
  230. FsctlParms->Size = FsctlParmSize;
  231. FsctlParms->Version = TRANSACTION_VERSION;
  232. FsctlParms->NameLength = APIEXTR-sizeof(WCHAR);
  233. FsctlParms->NameOffset = sizeof(LMR_TRANSACTION);
  234. NetpMoveMemory(
  235. NetpPointerPlusSomeBytes(
  236. FsctlParms,
  237. sizeof(LMR_TRANSACTION)), // dest
  238. REM_APITXT, // src (always UNICODE)
  239. APIEXTR-sizeof(WCHAR)); // len (don't copy null)
  240. FsctlParms->ResponseExpected = TRUE;
  241. FsctlParms->Timeout = REM_API_TIMEOUT; // Timeout time in milliseconds.
  242. FsctlParms->SetupWords = 0;
  243. FsctlParms->SetupOffset = 0;
  244. FsctlParms->MaxSetup = 0;
  245. FsctlParms->ParmLength = SendParmLen;
  246. FsctlParms->ParmPtr = SendParmPtr;
  247. FsctlParms->MaxRetParmLength = RetParmLen;
  248. NetpAssert(SendParmPtr == RetParmPtr);
  249. FsctlParms->DataLength = SendDataLen;
  250. FsctlParms->DataPtr = SendDataPtr;
  251. FsctlParms->MaxRetDataLength = InputRetDataLen;
  252. FsctlParms->RetDataPtr = RetDataPtr;
  253. //
  254. // Do the FSCTL!
  255. //
  256. Status = NetpRdrFsControlTree(
  257. TreeConnName, // tree connect name
  258. TransportName, // Transport name.
  259. USE_IPC, // Connection type
  260. FSCTL_LMR_TRANSACT, // fsctl function code
  261. NULL, // security descriptor
  262. FsctlParms, // input buffer
  263. FsctlParmSize, // input buffer length
  264. FsctlParms, // output buffer
  265. FsctlParmSize, // output buffer length
  266. NoPermissionRequired);
  267. if (Status == ERROR_BAD_NET_NAME) {
  268. Status = NERR_BadTransactConfig;
  269. }
  270. if (RxpFatalErrorCode(Status)) {
  271. IF_DEBUG(TRANSACT) {
  272. NetpKdPrint(( PREFIX_NETAPI
  273. "RxpTransactSmb: returning fatal status="
  274. FORMAT_API_STATUS ".\n", Status));
  275. }
  276. NetpMemoryFree(FsctlParms);
  277. NetpMemoryFree(TreeConnName);
  278. return (Status);
  279. }
  280. //
  281. // MOD 06/11/91 RLF
  282. // Return the received data length in *RetDataLen
  283. //
  284. *RetDataLen = FsctlParms->MaxRetDataLength;
  285. NetpAssert( *RetDataLen <= MAX_TRANSACT_RET_DATA_SIZE );
  286. //
  287. // MOD 06/11/91 RLF
  288. //
  289. NetpMemoryFree(FsctlParms);
  290. NetpMemoryFree(TreeConnName);
  291. #else // def CDEBUG
  292. {
  293. DWORD ApiNumber;
  294. ApiNumber = (DWORD) SmbGetUshort((LPWORD) SendParmPtr);
  295. IF_DEBUG(TRANSACT) {
  296. NetpKdPrint(( PREFIX_NETAPI
  297. "RxpTransactSmb: pretending success for API "
  298. FORMAT_DWORD ".\n", ApiNumber));
  299. }
  300. SmbPutUshort((LPWORD) RetParmPtr, (WORD) NERR_Success);
  301. switch (ApiNumber) {
  302. case API_NetRemoteTOD :
  303. {
  304. UCHAR BogusTime[] = {
  305. 0xD0, 0xAE, 0xB2, 0x28, // 21-Aug-1991 (6:20PM)
  306. 0x44, 0x33, 0x22, 0x11, // msec (anything)
  307. 3, // hours
  308. 30, // minutes
  309. 15, // seconds
  310. 55, // hundredths of seconds
  311. 0xFF, 0xFF, // timezone (unknown)
  312. 0xA6, 0x00, // clock interval (60 Hz)
  313. 10, // day
  314. 1, // month
  315. 0xC7, 0x07, // year
  316. 4}; // weekday
  317. NetpAssert(RetDataPtr != NULL);
  318. NetpAssert(InputRetDataLen != 0);
  319. NetpMoveMemory(
  320. RetDataPtr, // dest
  321. BogusTime, // src (bogus)
  322. InputRetDataLen); // len
  323. break;
  324. }
  325. case API_WServerGetInfo :
  326. {
  327. LPVOID FixedDataEnd = NetpPointerPlusSomeBytes(
  328. RetDataPtr,
  329. sizeof(SERVER_INFO_100));
  330. LPBYTE LastString = NetpPointerPlusSomeBytes(
  331. RetDataPtr,
  332. InputRetDataLen);
  333. LPSERVER_INFO_100 p = RetDataPtr;
  334. NetpAssert(RetDataPtr != NULL);
  335. NetpAssert(InputRetDataLen != 0);
  336. p->sv100_name = (LPTSTR) TEXT("\\\\bogus\\name");
  337. if (NetpPackString(
  338. & p->sv100_name, // in out
  339. FixedDataEnd, // in
  340. & LastString) == 0) { // in out
  341. NetpBreakPoint();
  342. return (NERR_InternalError);
  343. }
  344. break;
  345. }
  346. }
  347. }
  348. #endif // def CDEBUG
  349. Status = (DWORD) SmbGetUshort((LPWORD) RetParmPtr);
  350. IF_DEBUG(TRANSACT) {
  351. NetpKdPrint(( PREFIX_NETAPI
  352. "RxpTransactSmb: returning status="
  353. FORMAT_API_STATUS ".\n", Status));
  354. NetpKdPrint(( PREFIX_NETAPI
  355. "RxpTransactSmb: RetParm at " FORMAT_LPVOID
  356. ", len=" FORMAT_DWORD " (partial):\n",
  357. (LPVOID) RetParmPtr, RetParmLen));
  358. if (RetParmPtr != NULL) {
  359. NetpDbgHexDump(RetParmPtr, NetpDbgReasonable(RetParmLen));
  360. }
  361. NetpKdPrint(( PREFIX_NETAPI
  362. "RxpTransactSmb: (new) RetData at " FORMAT_LPVOID ", "
  363. "len=" FORMAT_DWORD " (partial):\n",
  364. (LPVOID) RetDataPtr, InputRetDataLen));
  365. if (RetDataPtr != NULL) {
  366. NetpDbgHexDump(RetDataPtr, NetpDbgReasonable(InputRetDataLen));
  367. }
  368. }
  369. return (Status);
  370. } // RxpTransactSmb