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.

2316 lines
81 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. fsctl.c
  5. Abstract:
  6. This module implements the mini redirector call down routines pertaining to
  7. file system control(FSCTL) and Io Device Control (IOCTL) operations on file
  8. system objects.
  9. Author:
  10. Balan Sethu Raman [SethuR] 7-March-1995
  11. Revision History:
  12. Joe Linn [JoeLi] -- Implemented FSCTL's
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include <dfsfsctl.h>
  17. #include <ntddrdr.h>
  18. #include <wincred.h>
  19. #include <secpkg.h>
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(PAGE, MRxSmbFsCtl)
  22. #pragma alloc_text(PAGE, MRxSmbNotifyChangeDirectory)
  23. #pragma alloc_text(PAGE, MRxSmbNamedPipeFsControl)
  24. #pragma alloc_text(PAGE, MRxSmbFsCtlUserTransact)
  25. #pragma alloc_text(PAGE, MRxSmbMailSlotFsControl)
  26. #pragma alloc_text(PAGE, MRxSmbFsControl)
  27. #pragma alloc_text(PAGE, MRxSmbIoCtl)
  28. #endif
  29. //
  30. // The local debug trace level
  31. //
  32. RXDT_DefineCategory(FSCTRL);
  33. #define Dbg (DEBUG_TRACE_FSCTRL)
  34. extern
  35. NTSTATUS
  36. MRxSmbNamedPipeFsControl(IN OUT PRX_CONTEXT RxContext);
  37. extern
  38. NTSTATUS
  39. MRxSmbMailSlotFsControl(IN OUT PRX_CONTEXT RxContext);
  40. extern
  41. NTSTATUS
  42. MRxSmbDfsFsControl(IN OUT PRX_CONTEXT RxContext);
  43. extern
  44. NTSTATUS
  45. MRxSmbFsControl(IN OUT PRX_CONTEXT RxContext);
  46. extern
  47. NTSTATUS
  48. MRxSmbFsCtlUserTransact(IN OUT PRX_CONTEXT RxContext);
  49. NTSTATUS
  50. MRxSmbGetPrintJobId(
  51. IN OUT PRX_CONTEXT RxContext);
  52. NTSTATUS
  53. MRxSmbCoreIoCtl(
  54. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE);
  55. NTSTATUS
  56. MRxSmbQueryTargetInfo(
  57. PRX_CONTEXT RxContext
  58. );
  59. NTSTATUS
  60. MRxSmbFsCtl(
  61. IN OUT PRX_CONTEXT RxContext)
  62. /*++
  63. Routine Description:
  64. This routine performs an FSCTL operation (remote) on a file across the network
  65. Arguments:
  66. RxContext - the RDBSS context
  67. Return Value:
  68. RXSTATUS - The return status for the operation
  69. Notes:
  70. The FSCTL's handled by a mini rdr can be classified into one of two categories.
  71. In the first category are those FSCTL's whose implementation are shared between
  72. RDBSS and the mini rdr's and in the second category are those FSCTL's which
  73. are totally implemented by the mini rdr's. To this a third category can be
  74. added, i.e., those FSCTL's which should never be seen by the mini rdr's. The
  75. third category is solely intended as a debugging aid.
  76. The FSCTL's handled by a mini rdr can be classified based on functionality
  77. --*/
  78. {
  79. RxCaptureFobx;
  80. RxCaptureFcb;
  81. NTSTATUS Status = STATUS_SUCCESS;
  82. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  83. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  84. PAGED_CODE();
  85. RxDbgTrace(+1, Dbg, ("MRxSmbFsCtl...\n", 0));
  86. RxDbgTrace( 0, Dbg, ("MRxSmbFsCtl = %08lx\n", FsControlCode));
  87. if (capFobx != NULL) {
  88. PMRX_V_NET_ROOT pVNetRoot;
  89. // Avoid device opens for which the FOBX is the VNET_ROOT instance
  90. pVNetRoot = (PMRX_V_NET_ROOT)capFobx;
  91. if (NodeType(pVNetRoot) != RDBSS_NTC_V_NETROOT) {
  92. PUNICODE_STRING AlreadyPrefixedName =
  93. GET_ALREADY_PREFIXED_NAME(capFobx->pSrvOpen,capFcb);
  94. ULONG FcbAlreadyPrefixedNameLength = AlreadyPrefixedName->Length;
  95. ULONG NetRootInnerNamePrefixLength = capFcb->pNetRoot->InnerNamePrefix.Length;
  96. PWCHAR pName = AlreadyPrefixedName->Buffer;
  97. // If an FSCTL is being attempted against the root of a share.
  98. // The AlreadyPrefixedName associated with the FCB is the same as
  99. // the AlreadyPrefixedName length associated with the NET_ROOT instance
  100. // or atmost one character greater than it ( appending a \) try and
  101. // reestablish the connection before attempting the FSCTL.
  102. // This solves thorny issues regarding deletion/creation of shares
  103. // on the server sides, DFS referrals etc.
  104. if ((FcbAlreadyPrefixedNameLength == NetRootInnerNamePrefixLength) ||
  105. ((FcbAlreadyPrefixedNameLength == NetRootInnerNamePrefixLength + sizeof(WCHAR)) &&
  106. (*((PCHAR)pName + FcbAlreadyPrefixedNameLength - sizeof(WCHAR)) ==
  107. L'\\'))) {
  108. if (capFobx->pSrvOpen != NULL) {
  109. Status = SmbCeReconnect(capFobx->pSrvOpen->pVNetRoot);
  110. }
  111. }
  112. }
  113. }
  114. if (Status == STATUS_SUCCESS) {
  115. switch (pLowIoContext->ParamsFor.FsCtl.MinorFunction) {
  116. case IRP_MN_USER_FS_REQUEST:
  117. case IRP_MN_TRACK_LINK :
  118. switch (FsControlCode) {
  119. case FSCTL_PIPE_ASSIGN_EVENT :
  120. case FSCTL_PIPE_DISCONNECT :
  121. case FSCTL_PIPE_LISTEN :
  122. case FSCTL_PIPE_PEEK :
  123. case FSCTL_PIPE_QUERY_EVENT :
  124. case FSCTL_PIPE_TRANSCEIVE :
  125. case FSCTL_PIPE_WAIT :
  126. case FSCTL_PIPE_IMPERSONATE :
  127. case FSCTL_PIPE_SET_CLIENT_PROCESS :
  128. case FSCTL_PIPE_QUERY_CLIENT_PROCESS :
  129. Status = MRxSmbNamedPipeFsControl(RxContext);
  130. break;
  131. case FSCTL_MAILSLOT_PEEK :
  132. Status = MRxSmbMailSlotFsControl(RxContext);
  133. break;
  134. case FSCTL_DFS_GET_REFERRALS:
  135. case FSCTL_DFS_REPORT_INCONSISTENCY:
  136. Status = MRxSmbDfsFsControl(RxContext);
  137. break;
  138. case FSCTL_LMR_TRANSACT :
  139. Status = MRxSmbFsCtlUserTransact(RxContext);
  140. break;
  141. case FSCTL_GET_PRINT_ID :
  142. Status = MRxSmbGetPrintJobId(RxContext);
  143. break;
  144. case FSCTL_LMR_QUERY_TARGET_INFO:
  145. Status = MRxSmbQueryTargetInfo(RxContext);
  146. break;
  147. case FSCTL_MOVE_FILE:
  148. case FSCTL_MARK_HANDLE:
  149. case FSCTL_QUERY_RETRIEVAL_POINTERS:
  150. case FSCTL_GET_VOLUME_BITMAP:
  151. case FSCTL_GET_NTFS_FILE_RECORD:
  152. Status = STATUS_NOT_SUPPORTED;
  153. break;
  154. case FSCTL_SET_REPARSE_POINT:
  155. {
  156. ULONG InputBufferLength = 0; // invalid value as we need an input buffer
  157. PREPARSE_DATA_BUFFER prdBuff = (&RxContext->LowIoContext)->ParamsFor.FsCtl.pInputBuffer;
  158. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  159. InputBufferLength = (&RxContext->LowIoContext)->ParamsFor.FsCtl.InputBufferLength;
  160. if ((prdBuff == NULL)||
  161. (InputBufferLength < REPARSE_DATA_BUFFER_HEADER_SIZE)||
  162. (InputBufferLength > MAXIMUM_REPARSE_DATA_BUFFER_SIZE))
  163. {
  164. Status = STATUS_IO_REPARSE_DATA_INVALID;
  165. break;
  166. }
  167. //
  168. // Verify that the user buffer and the data length in its header are
  169. // internally consistent. We need to have a REPARSE_DATA_BUFFER or a
  170. // REPARSE_GUID_DATA_BUFFER.
  171. //
  172. if((InputBufferLength != (ULONG)(REPARSE_DATA_BUFFER_HEADER_SIZE + prdBuff->ReparseDataLength))
  173. &&
  174. (InputBufferLength != (ULONG)(REPARSE_GUID_DATA_BUFFER_HEADER_SIZE + prdBuff->ReparseDataLength)))
  175. {
  176. Status = STATUS_IO_REPARSE_DATA_INVALID;
  177. break;
  178. }
  179. }
  180. case FSCTL_GET_REPARSE_POINT:
  181. // absence of break intentional
  182. case FSCTL_MARK_AS_SYSTEM_HIVE :
  183. //
  184. // On a remote boot machine, we need to no-op the MARK_AS_SYSTEM_HIVE
  185. // FSCTL. Local filesystems use this to prevent a volume from being
  186. // dismounted.
  187. //
  188. if (MRxSmbBootedRemotely) {
  189. break;
  190. }
  191. default:
  192. Status = MRxSmbFsControl(RxContext);
  193. break;
  194. }
  195. break;
  196. default :
  197. Status = STATUS_INVALID_DEVICE_REQUEST;
  198. break;
  199. }
  200. }
  201. RxDbgTrace(-1, Dbg, ("MRxSmbFsCtl -> %08lx\n", Status ));
  202. return Status;
  203. }
  204. typedef struct _SMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT_ {
  205. LONG ReferenceCount;
  206. PRX_CONTEXT pRxContext;
  207. REQ_NOTIFY_CHANGE NotifyRequest;
  208. SMB_TRANSACTION_OPTIONS Options;
  209. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  210. } SMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT, *PSMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT;
  211. NTSTATUS
  212. MRxSmbNotifyChangeDirectorySynchronousCompletion(
  213. PSMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext)
  214. /*++
  215. Routine Description:
  216. This routine is invoked when a directory change notification operation is
  217. completed
  218. Arguments:
  219. RxContext - the RDBSS context
  220. Return Value:
  221. RXSTATUS - The return status for the operation
  222. Notes:
  223. This routine will always be called. This is true even if the change directory
  224. notification is cancelled. In such cases the memory allocated is freed without
  225. any interaction with the wrapper. In cases of successful directory change
  226. notification completion the appropriate completion routine is invoked and the
  227. RxContext modified to prevent any cancellation from proceeding further.
  228. --*/
  229. {
  230. NTSTATUS Status = STATUS_PENDING;
  231. PMRXSMB_RX_CONTEXT pMRxSmbContext;
  232. PRX_CONTEXT pRxContext;
  233. PSMB_EXCHANGE pExchange = NULL;
  234. BOOLEAN FinalizeNotificationContext = FALSE;
  235. SmbCeAcquireSpinLock();
  236. FinalizeNotificationContext =
  237. (InterlockedDecrement(&pNotificationContext->ReferenceCount) == 0);
  238. if (FinalizeNotificationContext) {
  239. pRxContext = pNotificationContext->pRxContext;
  240. pMRxSmbContext = MRxSmbGetMinirdrContext(pRxContext);
  241. pExchange = pMRxSmbContext->pExchange;
  242. Status = pRxContext->StoredStatus;
  243. }
  244. SmbCeReleaseSpinLock();
  245. // Free the associated exchange.
  246. if (FinalizeNotificationContext) {
  247. if (pExchange != NULL) {
  248. SmbCeDereferenceAndDiscardExchange(pExchange);
  249. }
  250. // Free the notification context.
  251. RxFreePool(pNotificationContext);
  252. ASSERT(Status != STATUS_PENDING);
  253. }
  254. return Status;
  255. }
  256. VOID
  257. MRxSmbNotifyChangeDirectoryCompletion(
  258. PSMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext)
  259. /*++
  260. Routine Description:
  261. This routine is invoked when a directory change notification operation is
  262. completed
  263. Arguments:
  264. RxContext - the RDBSS context
  265. Return Value:
  266. RXSTATUS - The return status for the operation
  267. Notes:
  268. This routine will always be called. This is true even if the change directory
  269. notification is cancelled. In such cases the memory allocated is freed without
  270. any inteaction with the wrapper. In cases of successful directory change
  271. notification completion the appropriate completion routine is invoked and the
  272. RxContext modified to prevent any cancellation from proceeding further.
  273. --*/
  274. {
  275. NTSTATUS Status;
  276. PMRXSMB_RX_CONTEXT pMRxSmbContext;
  277. PRX_CONTEXT pRxContext;
  278. PSMB_EXCHANGE pExchange = NULL;
  279. BOOLEAN FinalizeNotificationContext = FALSE;
  280. SmbCeAcquireSpinLock();
  281. FinalizeNotificationContext =
  282. (InterlockedDecrement(&pNotificationContext->ReferenceCount) == 0);
  283. pRxContext = pNotificationContext->pRxContext;
  284. if (pRxContext != NULL) {
  285. PSMB_TRANSACT_EXCHANGE pTransactExchange;
  286. pMRxSmbContext = MRxSmbGetMinirdrContext(pRxContext);
  287. pExchange = pMRxSmbContext->pExchange;
  288. if (pExchange != NULL) {
  289. PSMBCEDB_SERVER_ENTRY pServerEntry;
  290. pTransactExchange = (PSMB_TRANSACT_EXCHANGE)pExchange;
  291. pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  292. if ((pNotificationContext->ResumptionContext.FinalStatusFromServer ==
  293. STATUS_NOT_SUPPORTED) ||
  294. (pNotificationContext->ResumptionContext.FinalStatusFromServer ==
  295. STATUS_NOT_IMPLEMENTED)) {
  296. pServerEntry->Server.ChangeNotifyNotSupported = TRUE;
  297. }
  298. pRxContext->InformationToReturn = pTransactExchange->ParamBytesReceived;
  299. } else {
  300. pRxContext->InformationToReturn = 0;
  301. }
  302. pRxContext->StoredStatus =
  303. pNotificationContext->ResumptionContext.FinalStatusFromServer;
  304. if( (pRxContext->InformationToReturn == 0) &&
  305. (pRxContext->StoredStatus == STATUS_SUCCESS) )
  306. {
  307. pRxContext->StoredStatus = STATUS_NOTIFY_ENUM_DIR;
  308. }
  309. }
  310. SmbCeReleaseSpinLock();
  311. if (FinalizeNotificationContext) {
  312. if (pRxContext != NULL) {
  313. RxLowIoCompletion(pRxContext);
  314. }
  315. // Free the associated exchange.
  316. if (pExchange != NULL) {
  317. SmbCeDereferenceAndDiscardExchange(pExchange);
  318. }
  319. // Free the notification context.
  320. RxFreePool(pNotificationContext);
  321. }
  322. }
  323. NTSTATUS
  324. MRxSmbNotifyChangeDirectory(
  325. IN OUT PRX_CONTEXT RxContext)
  326. /*++
  327. Routine Description:
  328. This routine performs a directory change notification operation
  329. Arguments:
  330. RxContext - the RDBSS context
  331. Return Value:
  332. RXSTATUS - The return status for the operation
  333. Notes:
  334. A directory change notification opertaion is an asychronous operation. It
  335. consists of sending a SMB requesting change notification whose response is
  336. obtained when the desired change is affected on the server.
  337. Some important points to remember are as follows .....
  338. 1) The SMB response is not obtained till the desired change is affected on
  339. the server. Therefore an additional MID needs to be reserved on those
  340. connections which permit multiple MID's so that a cancel SMB can be sent to
  341. the server when a change notification is active.
  342. 2) The Change notification is typical of a long term ( response time
  343. dictated by factors beyond the servers control). Another example is
  344. the query FSCTL operation in CAIRO. For all these operations we initiate
  345. an asychronous transact exchange.
  346. 3) The corresponding LowIo completion routine is invoked asynchronously.
  347. 4) This is an example of an operation for which the MINI RDR has to
  348. register a context for handling cancellations initiated locally.
  349. --*/
  350. {
  351. NTSTATUS Status;
  352. RxCaptureFcb;
  353. RxCaptureFobx;
  354. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  355. PSMBCEDB_SERVER_ENTRY pServerEntry;
  356. PSMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT pNotificationContext;
  357. PBYTE pInputParamBuffer = NULL;
  358. PBYTE pOutputParamBuffer = NULL;
  359. PBYTE pInputDataBuffer = NULL;
  360. PBYTE pOutputDataBuffer = NULL;
  361. ULONG InputParamBufferLength = 0;
  362. ULONG OutputParamBufferLength = 0;
  363. ULONG InputDataBufferLength = 0;
  364. ULONG OutputDataBufferLength = 0;
  365. RxDbgTrace(+1, Dbg, ("MRxNotifyChangeDirectory...Entry\n", 0));
  366. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  367. // if the server entry is in disconnected state, then let CSC do change notify
  368. // If successful, the CSC routine should return a STATUS_PENDING and
  369. // modify the rxcontext in way that is suitable to the underlying implementation
  370. // In the current incarnation, the CSC routine will
  371. // a) remove the irp from the rxconetxt and b) dereference the rxcontext
  372. if (MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)||
  373. SmbCeIsServerInDisconnectedMode(pServerEntry)) {
  374. return MRxSmbCscNotifyChangeDirectory(RxContext);
  375. }
  376. else if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS) ||
  377. pServerEntry->Server.ChangeNotifyNotSupported) {
  378. return STATUS_NOT_SUPPORTED;
  379. }
  380. #if defined(REMOTE_BOOT)
  381. //
  382. // Reject change notify on the remote boot share. This is necessary to
  383. // prevent overloading the server with long-term requests. (There are
  384. // LOTS of change notifies posted on the boot device!)
  385. //
  386. if (MRxSmbBootedRemotely) {
  387. PSMBCE_SESSION pSession;
  388. pSession = &SmbCeGetAssociatedVNetRootContext(capFobx->pSrvOpen->pVNetRoot)->pSessionEntry->Session;
  389. if (FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  390. return STATUS_NOT_SUPPORTED;
  391. }
  392. }
  393. #endif
  394. pNotificationContext =
  395. (PSMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT)
  396. RxAllocatePoolWithTag(
  397. NonPagedPool,
  398. sizeof(SMB_NOTIFY_CHANGE_DIRECTORY_CONTEXT),
  399. MRXSMB_FSCTL_POOLTAG);
  400. if (pNotificationContext != NULL) {
  401. PREQ_NOTIFY_CHANGE pNotifyRequest;
  402. PSMB_TRANSACTION_OPTIONS pTransactionOptions;
  403. PSMB_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext;
  404. PMRX_SMB_SRV_OPEN pSmbSrvOpen;
  405. BOOLEAN FcbAcquired = FALSE;
  406. RxCaptureFobx;
  407. ASSERT (capFobx != NULL);
  408. if (!RxIsFcbAcquiredExclusive(capFcb)) {
  409. // ASSERT(!RxIsFcbAcquiredShared(capFcb));
  410. Status = RxAcquireExclusiveFcbResourceInMRx( capFcb );
  411. FcbAcquired = (Status == STATUS_SUCCESS);
  412. }
  413. if (FcbAcquired) {
  414. if (FlagOn(capFobx->pSrvOpen->Flags,SRVOPEN_FLAG_CLOSED) ||
  415. FlagOn(capFobx->pSrvOpen->Flags,SRVOPEN_FLAG_ORPHANED)) {
  416. Status = STATUS_FILE_CLOSED;
  417. } else {
  418. Status = MRxSmbDeferredCreate(RxContext);
  419. }
  420. RxReleaseFcbResourceInMRx( capFcb );
  421. }
  422. if (Status==STATUS_SUCCESS) {
  423. pSmbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  424. pNotificationContext->pRxContext = RxContext;
  425. // The reference count is set to 2. one for the async completion routine
  426. // and one for the tail completion routine
  427. pNotificationContext->ReferenceCount = 2;
  428. pNotifyRequest = &(pNotificationContext->NotifyRequest);
  429. pTransactionOptions = &(pNotificationContext->Options);
  430. pResumptionContext = &(pNotificationContext->ResumptionContext);
  431. pNotifyRequest->CompletionFilter = pLowIoContext->ParamsFor.NotifyChangeDirectory.CompletionFilter;
  432. pNotifyRequest->Fid = pSmbSrvOpen->Fid;
  433. pNotifyRequest->WatchTree = pLowIoContext->ParamsFor.NotifyChangeDirectory.WatchTree;
  434. pNotifyRequest->Reserved = 0;
  435. OutputParamBufferLength = pLowIoContext->ParamsFor.NotifyChangeDirectory.NotificationBufferLength;
  436. pOutputParamBuffer = pLowIoContext->ParamsFor.NotifyChangeDirectory.pNotificationBuffer;
  437. *pTransactionOptions = RxDefaultTransactionOptions;
  438. pTransactionOptions->NtTransactFunction = NT_TRANSACT_NOTIFY_CHANGE;
  439. pTransactionOptions->TimeoutIntervalInMilliSeconds = SMBCE_TRANSACTION_TIMEOUT_NOT_USED;
  440. pTransactionOptions->Flags = SMB_XACT_FLAGS_INDEFINITE_DELAY_IN_RESPONSE;
  441. SmbCeInitializeAsynchronousTransactionResumptionContext(
  442. pResumptionContext,
  443. MRxSmbNotifyChangeDirectoryCompletion,
  444. pNotificationContext);
  445. Status = SmbCeAsynchronousTransact(
  446. RxContext, // the RXContext for the transaction
  447. pTransactionOptions, // transaction options
  448. pNotifyRequest, // the setup buffer
  449. sizeof(REQ_NOTIFY_CHANGE), // setup buffer length
  450. NULL,
  451. 0,
  452. pInputParamBuffer, // Input Param Buffer
  453. InputParamBufferLength, // Input param buffer length
  454. pOutputParamBuffer, // Output param buffer
  455. OutputParamBufferLength, // output param buffer length
  456. pInputDataBuffer, // Input data buffer
  457. InputDataBufferLength, // Input data buffer length
  458. pOutputDataBuffer, // output data buffer
  459. OutputDataBufferLength, // output data buffer length
  460. pResumptionContext // the resumption context
  461. );
  462. ASSERT(Status == STATUS_PENDING);
  463. Status = MRxSmbNotifyChangeDirectorySynchronousCompletion(
  464. pNotificationContext);
  465. } else {
  466. NOTHING; //just return the status from the deferred open call
  467. }
  468. } else {
  469. Status = STATUS_INSUFFICIENT_RESOURCES;
  470. }
  471. if (MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)||
  472. SmbCeIsServerInDisconnectedMode(pServerEntry)) {
  473. return MRxSmbCscNotifyChangeDirectory(RxContext);
  474. }
  475. RxDbgTrace(-1, Dbg, ("MRxSmbNotifyChangeDirectory -> %08lx\n", Status ));
  476. return Status;
  477. }
  478. UNICODE_STRING s_NamedPipeTransactionName = { 12,12,L"\\PIPE\\" };
  479. UNICODE_STRING s_MailSlotTransactionName = {20,20,L"\\MAILSLOT\\" };
  480. typedef struct _SMB_NAMED_PIPE_FSCTL_COMPLETION_CONTEXT_ {
  481. LONG ReferenceCount;
  482. PRX_CONTEXT pRxContext;
  483. PWCHAR pTransactionNameBuffer;
  484. SMB_TRANSACTION_OPTIONS Options;
  485. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  486. } SMB_NAMED_PIPE_FSCTL_COMPLETION_CONTEXT,
  487. *PSMB_NAMED_PIPE_FSCTL_COMPLETION_CONTEXT;
  488. VOID
  489. MRxSmbNamedPipeFsControlCompletion(
  490. PSMB_NAMED_PIPE_FSCTL_COMPLETION_CONTEXT pFsCtlCompletionContext)
  491. {
  492. PRX_CONTEXT pRxContext = NULL;
  493. PSMB_EXCHANGE pExchange = NULL;
  494. BOOLEAN FinalizeFsCtlCompletionContext = FALSE;
  495. SmbCeAcquireSpinLock();
  496. FinalizeFsCtlCompletionContext =
  497. (InterlockedDecrement(&pFsCtlCompletionContext->ReferenceCount) == 0);
  498. if (FinalizeFsCtlCompletionContext) {
  499. pRxContext = pFsCtlCompletionContext->pRxContext;
  500. if (pRxContext != NULL) {
  501. PMRXSMB_RX_CONTEXT pMRxSmbContext;
  502. pMRxSmbContext = MRxSmbGetMinirdrContext(pRxContext);
  503. pExchange = pMRxSmbContext->pExchange;
  504. }
  505. }
  506. SmbCeReleaseSpinLock();
  507. if (FinalizeFsCtlCompletionContext) {
  508. if (pRxContext != NULL) {
  509. pRxContext->StoredStatus =
  510. pFsCtlCompletionContext->ResumptionContext.FinalStatusFromServer;
  511. if (pRxContext->StoredStatus == STATUS_INVALID_HANDLE) {
  512. pRxContext->StoredStatus = STATUS_INVALID_NETWORK_RESPONSE;
  513. }
  514. pRxContext->InformationToReturn =
  515. pFsCtlCompletionContext->ResumptionContext.DataBytesReceived;
  516. RxLowIoCompletion(pRxContext);
  517. }
  518. if (pExchange != NULL) {
  519. SmbCeDereferenceAndDiscardExchange(pExchange);
  520. }
  521. if (pFsCtlCompletionContext->pTransactionNameBuffer != NULL) {
  522. RxFreePool(pFsCtlCompletionContext->pTransactionNameBuffer);
  523. }
  524. RxFreePool(pFsCtlCompletionContext);
  525. }
  526. }
  527. NTSTATUS
  528. MRxSmbNamedPipeFsControl(PRX_CONTEXT RxContext)
  529. /*++
  530. Routine Description:
  531. This routine handles all named pipe related FSCTL's
  532. Arguments:
  533. RxContext - the RDBSS context
  534. Return Value:
  535. RXSTATUS - The return status for the operation
  536. --*/
  537. {
  538. RxCaptureFobx;
  539. RxCaptureFcb;
  540. PMRX_SMB_SRV_OPEN pSmbSrvOpen;
  541. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  542. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  543. UNICODE_STRING TransactionName;
  544. BOOLEAN ReestablishConnectionIfRequired = FALSE, fTransactioNameBufferAllocated = FALSE;
  545. NTSTATUS Status;
  546. USHORT Setup[2];
  547. PBYTE pInputParamBuffer = NULL;
  548. PBYTE pOutputParamBuffer = NULL;
  549. PBYTE pInputDataBuffer = NULL;
  550. PBYTE pOutputDataBuffer = NULL;
  551. ULONG InputParamBufferLength = 0;
  552. ULONG OutputParamBufferLength = 0;
  553. ULONG InputDataBufferLength = 0;
  554. ULONG OutputDataBufferLength = 0;
  555. ULONG TimeoutIntervalInMilliSeconds;
  556. RESP_PEEK_NMPIPE PeekResponse;
  557. PAGED_CODE();
  558. RxDbgTrace(+1, Dbg, ("MRxSmbNamedPipeFsControl...\n", 0));
  559. TimeoutIntervalInMilliSeconds = SMBCE_TRANSACTION_TIMEOUT_NOT_USED;
  560. Status = STATUS_MORE_PROCESSING_REQUIRED;
  561. if (NodeType(capFcb) != RDBSS_NTC_STORAGE_TYPE_FILE &&
  562. NodeType(capFcb) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN ||
  563. capFcb->pNetRoot == NULL ||
  564. capFcb->pNetRoot->Type != NET_ROOT_PIPE) {
  565. return STATUS_INVALID_DEVICE_REQUEST;
  566. }
  567. if (capFobx != NULL) {
  568. pSmbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  569. } else {
  570. pSmbSrvOpen = NULL;
  571. }
  572. // The following switch statement serves the dual purpose of validating the parameters
  573. // presented by the user as well as filling in the appropriate information if it is
  574. // available locally.
  575. // Currently there is no local caching strategy in place and consequently a network trip
  576. // is always undertaken.
  577. TransactionName = s_NamedPipeTransactionName;
  578. switch (FsControlCode) {
  579. case FSCTL_PIPE_PEEK :
  580. {
  581. Setup[0] = TRANS_PEEK_NMPIPE;
  582. Setup[1] = pSmbSrvOpen->Fid;
  583. pOutputParamBuffer = (PBYTE)&PeekResponse;
  584. OutputParamBufferLength = sizeof(PeekResponse);
  585. pOutputDataBuffer = (PBYTE)pLowIoContext->ParamsFor.FsCtl.pOutputBuffer +
  586. FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER,Data[0]);
  587. OutputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength -
  588. FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER,Data[0]);
  589. }
  590. break;
  591. case FSCTL_PIPE_TRANSCEIVE :
  592. {
  593. Setup[0] = TRANS_TRANSACT_NMPIPE;
  594. Setup[1] = pSmbSrvOpen->Fid;
  595. pInputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  596. InputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.InputBufferLength;
  597. pOutputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  598. OutputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  599. // CODE.IMPROVEMENT -- Currently the semantics of attempting a TRANSCEIVE
  600. // with zero bytes to be written is not very well defined. The Old Redirector
  601. // succeeds without issuing a TRANSACT request. This needs to be resolved and
  602. // till it is done the old semantics will be retained
  603. //if (InputDataBufferLength == 0) {
  604. // Status = STATUS_SUCCESS;
  605. //}
  606. }
  607. break;
  608. case FSCTL_PIPE_WAIT :
  609. {
  610. PFILE_PIPE_WAIT_FOR_BUFFER pWaitBuffer;
  611. ULONG NameLength;
  612. Setup[0] = TRANS_WAIT_NMPIPE;
  613. Setup[1] = 0;
  614. if ((pLowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL) ||
  615. (pLowIoContext->ParamsFor.FsCtl.InputBufferLength <
  616. sizeof(FILE_PIPE_WAIT_FOR_BUFFER))) {
  617. Status = STATUS_INVALID_PARAMETER;
  618. } else {
  619. // Set up the transaction name to reflect the name of the pipe
  620. // on which the wait operation is being performed.
  621. pWaitBuffer = (PFILE_PIPE_WAIT_FOR_BUFFER)pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  622. if (pWaitBuffer->NameLength + s_NamedPipeTransactionName.Length > MAXUSHORT ||
  623. pWaitBuffer->NameLength - sizeof(WCHAR) >
  624. pLowIoContext->ParamsFor.FsCtl.InputBufferLength - sizeof(FILE_PIPE_WAIT_FOR_BUFFER)) {
  625. // if the name is too long to be put on a UNICIDE string,
  626. // or the name length doesn't match the buffer length
  627. Status = STATUS_INVALID_PARAMETER;
  628. }
  629. }
  630. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  631. // In the case of Wait FSCTL a reconnection attempt will be made
  632. // if required
  633. ReestablishConnectionIfRequired = TRUE;
  634. TransactionName.Length = (USHORT)(s_NamedPipeTransactionName.Length +
  635. pWaitBuffer->NameLength);
  636. TransactionName.MaximumLength = TransactionName.Length;
  637. TransactionName.Buffer = (PWCHAR)RxAllocatePool(PagedPool,TransactionName.Length);
  638. if (TransactionName.Buffer != NULL) {
  639. fTransactioNameBufferAllocated = TRUE;
  640. RtlCopyMemory(TransactionName.Buffer,
  641. s_NamedPipeTransactionName.Buffer,
  642. s_NamedPipeTransactionName.Length);
  643. RtlCopyMemory(
  644. (PBYTE)TransactionName.Buffer + s_NamedPipeTransactionName.Length,
  645. pWaitBuffer->Name,
  646. pWaitBuffer->NameLength);
  647. } else {
  648. Status = STATUS_INSUFFICIENT_RESOURCES;
  649. }
  650. if (pWaitBuffer->TimeoutSpecified) {
  651. LARGE_INTEGER TimeWorkspace;
  652. LARGE_INTEGER WaitForever;
  653. WaitForever.LowPart = 0;
  654. WaitForever.HighPart =0x80000000;
  655. // Avoid negate of "WaitForever" since this generates an integer
  656. // overflow exception on some machines.
  657. if (pWaitBuffer->Timeout.QuadPart != WaitForever.QuadPart) {
  658. TimeWorkspace.QuadPart = -pWaitBuffer->Timeout.QuadPart / 10000;
  659. if ( TimeWorkspace.HighPart) {
  660. // Tried to specify a larger timeout than we can select.
  661. // set it to the Maximum we can request
  662. TimeoutIntervalInMilliSeconds = 0xfffffffe;
  663. } else {
  664. TimeoutIntervalInMilliSeconds = TimeWorkspace.LowPart;
  665. }
  666. }
  667. } else {
  668. TimeoutIntervalInMilliSeconds = 0;
  669. }
  670. }
  671. }
  672. break;
  673. case FSCTL_PIPE_ASSIGN_EVENT :
  674. case FSCTL_PIPE_QUERY_EVENT :
  675. case FSCTL_PIPE_IMPERSONATE :
  676. case FSCTL_PIPE_SET_CLIENT_PROCESS :
  677. case FSCTL_PIPE_QUERY_CLIENT_PROCESS :
  678. // These FSCTL's have not been implemented so far in NT. They will be implemented
  679. // in a future release.
  680. Status = STATUS_INVALID_PARAMETER;
  681. RxDbgTrace( 0, Dbg, ("MRxSmbNamedPipeFsControl: Unimplemented FS control code\n"));
  682. break;
  683. case FSCTL_PIPE_DISCONNECT :
  684. case FSCTL_PIPE_LISTEN :
  685. Status = STATUS_INVALID_PARAMETER;
  686. RxDbgTrace( 0, Dbg, ("MRxSmbNamedPipeFsControl: Invalid FS control code for redirector\n"));
  687. break;
  688. default:
  689. RxDbgTrace( 0, Dbg, ("MRxSmbNamedPipeFsControl: Invalid FS control code\n"));
  690. Status = STATUS_INVALID_PARAMETER;
  691. break;
  692. }
  693. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  694. if (ReestablishConnectionIfRequired) {
  695. if (capFobx != NULL) {
  696. Status = SmbCeReconnect(capFobx->pSrvOpen->pVNetRoot);
  697. } else {
  698. Status = STATUS_SUCCESS;
  699. }
  700. } else {
  701. Status = STATUS_SUCCESS;
  702. }
  703. if (Status == STATUS_SUCCESS) {
  704. PSMB_TRANSACTION_OPTIONS pTransactionOptions;
  705. PSMB_NAMED_PIPE_FSCTL_COMPLETION_CONTEXT pFsCtlCompletionContext;
  706. PSMB_TRANSACTION_RESUMPTION_CONTEXT pResumptionContext;
  707. RxDbgTrace( 0, Dbg, ("MRxSmbNamedPipeFsControl: TransactionName %ws Length %ld\n",
  708. TransactionName.Buffer,TransactionName.Length));
  709. pFsCtlCompletionContext =
  710. (PSMB_NAMED_PIPE_FSCTL_COMPLETION_CONTEXT)
  711. RxAllocatePoolWithTag(
  712. NonPagedPool,
  713. sizeof(SMB_NAMED_PIPE_FSCTL_COMPLETION_CONTEXT),
  714. MRXSMB_FSCTL_POOLTAG);
  715. if (pFsCtlCompletionContext != NULL) {
  716. pResumptionContext = &pFsCtlCompletionContext->ResumptionContext;
  717. pTransactionOptions = &(pFsCtlCompletionContext->Options);
  718. if (FsControlCode != FSCTL_PIPE_PEEK) {
  719. // The reference count is set to 2. one for the async
  720. // completion routine and one for the tail completion routine
  721. pFsCtlCompletionContext->pRxContext = RxContext;
  722. pFsCtlCompletionContext->ReferenceCount = 2;
  723. SmbCeInitializeAsynchronousTransactionResumptionContext(
  724. pResumptionContext,
  725. MRxSmbNamedPipeFsControlCompletion,
  726. pFsCtlCompletionContext);
  727. } else {
  728. // Currently PEEK operations are synchronous
  729. pFsCtlCompletionContext->pRxContext = NULL;
  730. pFsCtlCompletionContext->ReferenceCount = 1;
  731. }
  732. *pTransactionOptions = RxDefaultTransactionOptions;
  733. pTransactionOptions->NtTransactFunction = 0; // TRANSACT2/TRANSACT.
  734. pTransactionOptions->pTransactionName = &TransactionName;
  735. pTransactionOptions->Flags = SMB_XACT_FLAGS_FID_NOT_NEEDED;
  736. pTransactionOptions->TimeoutIntervalInMilliSeconds = TimeoutIntervalInMilliSeconds;
  737. if (TransactionName.Buffer != s_NamedPipeTransactionName.Buffer) {
  738. pFsCtlCompletionContext->pTransactionNameBuffer =
  739. TransactionName.Buffer;
  740. } else {
  741. pFsCtlCompletionContext->pTransactionNameBuffer = NULL;
  742. }
  743. if (FsControlCode != FSCTL_PIPE_PEEK) {
  744. Status = SmbCeAsynchronousTransact(
  745. RxContext, // the RXContext for the transaction
  746. pTransactionOptions, // transaction options
  747. Setup, // the setup buffer
  748. sizeof(Setup), // setup buffer length
  749. NULL,
  750. 0,
  751. pInputParamBuffer, // Input Param Buffer
  752. InputParamBufferLength, // Input param buffer length
  753. pOutputParamBuffer, // Output param buffer
  754. OutputParamBufferLength, // output param buffer length
  755. pInputDataBuffer, // Input data buffer
  756. InputDataBufferLength, // Input data buffer length
  757. pOutputDataBuffer, // output data buffer
  758. OutputDataBufferLength, // output data buffer length
  759. pResumptionContext // the resumption context
  760. );
  761. if (Status != STATUS_PENDING) {
  762. pFsCtlCompletionContext->ResumptionContext.FinalStatusFromServer
  763. = Status;
  764. }
  765. MRxSmbNamedPipeFsControlCompletion(pFsCtlCompletionContext);
  766. Status = STATUS_PENDING;
  767. } else {
  768. Status = SmbCeTransact(
  769. RxContext, // the RXContext for the transaction
  770. pTransactionOptions, // transaction options
  771. Setup, // the setup buffer
  772. sizeof(Setup), // setup buffer length
  773. NULL,
  774. 0,
  775. pInputParamBuffer, // Input Param Buffer
  776. InputParamBufferLength, // Input param buffer length
  777. pOutputParamBuffer, // Output param buffer
  778. OutputParamBufferLength, // output param buffer length
  779. pInputDataBuffer, // Input data buffer
  780. InputDataBufferLength, // Input data buffer length
  781. pOutputDataBuffer, // output data buffer
  782. OutputDataBufferLength, // output data buffer length
  783. pResumptionContext // the resumption context
  784. );
  785. switch (FsControlCode) {
  786. case FSCTL_PIPE_PEEK:
  787. {
  788. // In the case of FSCTL_PIPE_PEEK post processing is required to package the
  789. // results and also handle the idiosyncracies of the different servers.
  790. // e.g.,
  791. // Os/2 servers will allow PeekNamedPipe on closed pipes to succeed
  792. // even if the server side of the pipe is closed.
  793. //
  794. // If we get the status PIPE_STATE_CLOSING from the server, then
  795. // we need to return an error of STATUS_PIPE_DISCONNECTED, as this
  796. // is what NPFS will do.
  797. if (NT_SUCCESS(Status) ||
  798. (Status == RX_MAP_STATUS(BUFFER_OVERFLOW))) {
  799. if (pResumptionContext->ParameterBytesReceived >= sizeof(RESP_PEEK_NMPIPE)) {
  800. if ((SmbGetAlignedUshort(&PeekResponse.NamedPipeState) & PIPE_STATE_CLOSING) &&
  801. (PeekResponse.ReadDataAvailable == 0)) {
  802. Status = STATUS_PIPE_DISCONNECTED;
  803. } else {
  804. PFILE_PIPE_PEEK_BUFFER pPeekBuffer;
  805. pPeekBuffer = (PFILE_PIPE_PEEK_BUFFER)pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  806. pPeekBuffer->NamedPipeState = (ULONG)SmbGetAlignedUshort(&PeekResponse.NamedPipeState);
  807. pPeekBuffer->ReadDataAvailable = (ULONG)PeekResponse.ReadDataAvailable;
  808. pPeekBuffer->NumberOfMessages = MAXULONG;
  809. pPeekBuffer->MessageLength = (ULONG)PeekResponse.MessageLength;
  810. if (PeekResponse.MessageLength > OutputDataBufferLength) {
  811. Status = STATUS_BUFFER_OVERFLOW;
  812. }
  813. }
  814. }
  815. RxContext->InformationToReturn =
  816. FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]) +
  817. pResumptionContext->DataBytesReceived;
  818. }
  819. }
  820. break;
  821. default:
  822. RxContext->InformationToReturn =
  823. pResumptionContext->DataBytesReceived;
  824. break;
  825. }
  826. MRxSmbNamedPipeFsControlCompletion(pFsCtlCompletionContext);
  827. }
  828. } else {
  829. if (fTransactioNameBufferAllocated)
  830. {
  831. RxFreePool(TransactionName.Buffer);
  832. }
  833. Status = STATUS_INSUFFICIENT_RESOURCES;
  834. }
  835. }
  836. }
  837. if (!NT_SUCCESS(Status)) {
  838. if (Status == STATUS_INVALID_HANDLE) {
  839. Status = STATUS_INVALID_NETWORK_RESPONSE;
  840. }
  841. RxDbgTrace( 0, Dbg, ("MRxSmbNamedPipeFsControl(%ld): Failed .. returning %lx\n",FsControlCode,Status));
  842. }
  843. RxDbgTrace(-1, Dbg, ("MRxSmbNamedPipeFsControl exit...st=%08lx\n", Status));
  844. return Status;
  845. }
  846. #ifdef _WIN64
  847. typedef struct _LMR_TRANSACTION_32 {
  848. ULONG Type; // Type of structure
  849. ULONG Size; // Size of fixed portion of structure
  850. ULONG Version; // Structure version.
  851. ULONG NameLength; // Number of bytes in name (in path
  852. // format, e.g., \server\pipe\netapi\4)
  853. ULONG NameOffset; // Offset of name in buffer.
  854. BOOLEAN ResponseExpected; // Should remote system respond?
  855. ULONG Timeout; // Timeout time in milliseconds.
  856. ULONG SetupWords; // Number of trans setup words (may be
  857. // 0). (setup words are input/output.)
  858. ULONG SetupOffset; // Offset of setup (may be 0 for none).
  859. ULONG MaxSetup; // Size of setup word array (may be 0).
  860. ULONG ParmLength; // Input param area length (may be 0).
  861. void * POINTER_32 ParmPtr; // Input parameter area (may be NULL).
  862. ULONG MaxRetParmLength; // Output param. area length (may be 0).
  863. ULONG DataLength; // Input data area length (may be 0).
  864. void * POINTER_32 DataPtr; // Input data area (may be NULL).
  865. ULONG MaxRetDataLength; // Output data area length (may be 0).
  866. void * POINTER_32 RetDataPtr; // Output data area (may be NULL).
  867. } LMR_TRANSACTION_32, *PLMR_TRANSACTION_32;
  868. #endif
  869. NTSTATUS
  870. MRxSmbFsCtlUserTransact(PRX_CONTEXT RxContext)
  871. /*++
  872. Routine Description:
  873. This routine issues what is called a UserTransaction against the server that is serving the
  874. connection for this file. very strange.............
  875. Arguments:
  876. RxContext - the RDBSS context
  877. Return Value:
  878. RXSTATUS - The return status for the operation
  879. --*/
  880. {
  881. RxCaptureFobx;
  882. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  883. UNICODE_STRING TransactionName;
  884. LMR_TRANSACTION InputBuffer;
  885. ULONG InputBufferLength = pLowIoContext->ParamsFor.FsCtl.InputBufferLength;
  886. ULONG SizeOfLmrTransaction = 0;
  887. NTSTATUS Status;
  888. PAGED_CODE();
  889. if( pLowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL )
  890. {
  891. return (Status = STATUS_INVALID_PARAMETER);
  892. }
  893. InputBuffer = *((PLMR_TRANSACTION)pLowIoContext->ParamsFor.FsCtl.pInputBuffer);
  894. #ifdef _WIN64
  895. if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  896. PLMR_TRANSACTION_32 InputBuffer32 = (PLMR_TRANSACTION_32)pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  897. InputBuffer.Type = InputBuffer32->Type;
  898. InputBuffer.Size = InputBuffer32->Size;
  899. InputBuffer.Version = InputBuffer32->Version;
  900. InputBuffer.NameLength = InputBuffer32->NameLength;
  901. InputBuffer.NameOffset = InputBuffer32->NameOffset;
  902. InputBuffer.ResponseExpected = InputBuffer32->ResponseExpected;
  903. InputBuffer.Timeout = InputBuffer32->Timeout;
  904. InputBuffer.SetupWords = InputBuffer32->SetupWords;
  905. InputBuffer.SetupOffset = InputBuffer32->SetupOffset;
  906. InputBuffer.MaxSetup = InputBuffer32->MaxSetup;
  907. InputBuffer.ParmLength = InputBuffer32->ParmLength;
  908. InputBuffer.ParmPtr = (PVOID)InputBuffer32->ParmPtr;
  909. InputBuffer.MaxRetParmLength = InputBuffer32->MaxRetParmLength;
  910. InputBuffer.DataLength = InputBuffer32->DataLength;
  911. InputBuffer.DataPtr = (PVOID)InputBuffer32->DataPtr;
  912. InputBuffer.MaxRetDataLength = InputBuffer32->MaxRetDataLength;
  913. InputBuffer.RetDataPtr = (PVOID)InputBuffer32->RetDataPtr;
  914. SizeOfLmrTransaction = sizeof(LMR_TRANSACTION_32);
  915. } else {
  916. SizeOfLmrTransaction = sizeof(LMR_TRANSACTION);
  917. }
  918. #else
  919. SizeOfLmrTransaction = sizeof(LMR_TRANSACTION);
  920. #endif
  921. RxDbgTrace(+1, Dbg, ("MRxSmbFsCtlUserTransact...\n"));
  922. if (InputBufferLength < SizeOfLmrTransaction) {
  923. return(Status = STATUS_INVALID_PARAMETER);
  924. }
  925. if (InputBufferLength - SizeOfLmrTransaction < InputBuffer.NameLength) {
  926. return(Status = STATUS_BUFFER_TOO_SMALL);
  927. }
  928. if ((InputBuffer.Type != TRANSACTION_REQUEST) ||
  929. (InputBuffer.Version != TRANSACTION_VERSION)) {
  930. return(Status = STATUS_INVALID_PARAMETER);
  931. }
  932. if (InputBuffer.NameOffset + InputBuffer.NameLength > InputBufferLength) {
  933. return(Status = STATUS_INVALID_PARAMETER);
  934. }
  935. if (InputBuffer.SetupOffset + InputBuffer.SetupWords > InputBufferLength) {
  936. return(Status = STATUS_INVALID_PARAMETER);
  937. }
  938. if (capFobx != NULL) {
  939. PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)capFobx;
  940. if (NodeType(pVNetRoot) == RDBSS_NTC_V_NETROOT) {
  941. Status = SmbCeReconnect(pVNetRoot);
  942. } else {
  943. Status = SmbCeReconnect(capFobx->pSrvOpen->pVNetRoot);
  944. }
  945. if (Status != STATUS_SUCCESS) {
  946. return Status;
  947. }
  948. }
  949. Status = STATUS_MORE_PROCESSING_REQUIRED;
  950. TransactionName.MaximumLength = (USHORT)InputBuffer.NameLength;
  951. TransactionName.Length = (USHORT)InputBuffer.NameLength;
  952. TransactionName.Buffer = (PWSTR)(((PUCHAR)pLowIoContext->ParamsFor.FsCtl.pInputBuffer)+InputBuffer.NameOffset);
  953. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  954. SMB_TRANSACTION_SEND_PARAMETERS SendParameters;
  955. SMB_TRANSACTION_RECEIVE_PARAMETERS ReceiveParameters;
  956. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  957. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  958. PUCHAR SetupBuffer = NULL;
  959. RxDbgTrace( 0, Dbg, ("MRxSmbFsCtlUserTransact: TransactionName %ws Length %ld\n",
  960. TransactionName.Buffer,TransactionName.Length));
  961. TransactionOptions.NtTransactFunction = 0; // TRANSACT2/TRANSACT.
  962. TransactionOptions.pTransactionName = &TransactionName;
  963. TransactionOptions.Flags = SMB_XACT_FLAGS_FID_NOT_NEEDED;
  964. if (!InputBuffer.ResponseExpected) {
  965. TransactionOptions.Flags |= SMB_TRANSACTION_NO_RESPONSE;
  966. }
  967. TransactionOptions.TimeoutIntervalInMilliSeconds = InputBuffer.Timeout;
  968. SmbCeInitializeTransactionResumptionContext(&ResumptionContext);
  969. try {
  970. if (InputBuffer.SetupOffset){
  971. SetupBuffer = (PUCHAR)pLowIoContext->ParamsFor.FsCtl.pInputBuffer+InputBuffer.SetupOffset;
  972. }
  973. if (SetupBuffer) {
  974. ProbeForWrite(SetupBuffer,InputBuffer.MaxSetup,1);
  975. }
  976. if (InputBuffer.ParmPtr) {
  977. ProbeForWrite(InputBuffer.ParmPtr,InputBuffer.MaxRetParmLength,1);
  978. }
  979. if (InputBuffer.RetDataPtr) {
  980. ProbeForWrite(InputBuffer.RetDataPtr,InputBuffer.MaxRetDataLength,1);
  981. }
  982. } except(EXCEPTION_EXECUTE_HANDLER) {
  983. return STATUS_INVALID_PARAMETER;
  984. }
  985. Status = SmbCeTransact(
  986. RxContext,
  987. &TransactionOptions,
  988. SetupBuffer,
  989. (USHORT)InputBuffer.SetupWords,
  990. SetupBuffer,
  991. InputBuffer.MaxSetup,
  992. InputBuffer.ParmPtr,
  993. InputBuffer.ParmLength,
  994. InputBuffer.ParmPtr, // the buffer for the param information
  995. InputBuffer.MaxRetParmLength,// the length of the param buffer
  996. InputBuffer.DataPtr,
  997. InputBuffer.DataLength,
  998. InputBuffer.RetDataPtr, // the buffer for data
  999. InputBuffer.MaxRetDataLength,// the length of the buffer
  1000. &ResumptionContext);
  1001. if (NT_SUCCESS(Status)) {
  1002. //LowIoContext->ParamsFor.FsCtl.OutputBufferLength = ResumptionContext.DataBytesReceived;
  1003. #ifdef _WIN64
  1004. if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  1005. PLMR_TRANSACTION_32 pInputBuffer = (PLMR_TRANSACTION_32)pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1006. pInputBuffer->MaxRetParmLength = ResumptionContext.ParameterBytesReceived;
  1007. pInputBuffer->MaxRetDataLength = ResumptionContext.DataBytesReceived;
  1008. pInputBuffer->MaxSetup = ResumptionContext.SetupBytesReceived;
  1009. //this seems like a bad return value for iostatus.information
  1010. RxContext->InformationToReturn = SizeOfLmrTransaction + pInputBuffer->SetupWords;
  1011. } else {
  1012. PLMR_TRANSACTION pInputBuffer = (PLMR_TRANSACTION)pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1013. pInputBuffer->MaxRetParmLength = ResumptionContext.ParameterBytesReceived;
  1014. pInputBuffer->MaxRetDataLength = ResumptionContext.DataBytesReceived;
  1015. pInputBuffer->MaxSetup = ResumptionContext.SetupBytesReceived;
  1016. //this seems like a return value for iostatus.information
  1017. RxContext->InformationToReturn = SizeOfLmrTransaction + pInputBuffer->SetupWords;
  1018. }
  1019. #else
  1020. {
  1021. PLMR_TRANSACTION pInputBuffer = (PLMR_TRANSACTION)pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1022. pInputBuffer->MaxRetParmLength = ResumptionContext.ParameterBytesReceived;
  1023. pInputBuffer->MaxRetDataLength = ResumptionContext.DataBytesReceived;
  1024. pInputBuffer->MaxSetup = ResumptionContext.SetupBytesReceived;
  1025. //this seems like a return value for iostatus.information
  1026. RxContext->InformationToReturn = SizeOfLmrTransaction + pInputBuffer->SetupWords;
  1027. }
  1028. #endif
  1029. }
  1030. }
  1031. if (!NT_SUCCESS(Status)) {
  1032. RxDbgTrace( 0, Dbg, ("MRxSmbFsCtlUserTransact: Failed .. returning %lx\n",Status));
  1033. }
  1034. RxDbgTrace(-1, Dbg, ("MRxSmbFsCtlUserTransact exit...st=%08lx\n", Status));
  1035. return Status;
  1036. }
  1037. NTSTATUS
  1038. MRxSmbMailSlotFsControl(PRX_CONTEXT RxContext)
  1039. /*++
  1040. Routine Description:
  1041. This routine handles all named pipe related FSCTL's
  1042. Arguments:
  1043. RxContext - the RDBSS context
  1044. Return Value:
  1045. RXSTATUS - The return status for the operation
  1046. --*/
  1047. {
  1048. PAGED_CODE();
  1049. return STATUS_NOT_IMPLEMENTED;
  1050. }
  1051. NTSTATUS
  1052. MRxSmbDfsFsControl(PRX_CONTEXT RxContext)
  1053. /*++
  1054. Routine Description:
  1055. This routine handles all DFS related FSCTL's
  1056. Arguments:
  1057. RxContext - the RDBSS context
  1058. Return Value:
  1059. RXSTATUS - The return status for the operation
  1060. --*/
  1061. {
  1062. RxCaptureFobx;
  1063. RxCaptureFcb;
  1064. PMRX_SMB_SRV_OPEN pSmbSrvOpen;
  1065. SMB_TRANSACTION_OPTIONS TransactionOptions = DEFAULT_TRANSACTION_OPTIONS;
  1066. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1067. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  1068. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  1069. NTSTATUS Status;
  1070. USHORT Setup;
  1071. PBYTE pInputParamBuffer = NULL;
  1072. PBYTE pOutputParamBuffer = NULL;
  1073. PBYTE pInputDataBuffer = NULL;
  1074. PBYTE pOutputDataBuffer = NULL;
  1075. ULONG InputParamBufferLength = 0;
  1076. ULONG OutputParamBufferLength = 0;
  1077. ULONG InputDataBufferLength = 0;
  1078. ULONG OutputDataBufferLength = 0;
  1079. PAGED_CODE();
  1080. RxDbgTrace(+1, Dbg, ("MRxSmbDfsFsControl...\n", 0));
  1081. if (RxContext->CurrentIrp->RequestorMode != KernelMode) {
  1082. // these FSCTLS are only su[pported from a kernel mode component
  1083. // because of parameter validation issues
  1084. return STATUS_INVALID_DEVICE_REQUEST;
  1085. }
  1086. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1087. if (capFobx != NULL) {
  1088. pSmbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1089. } else {
  1090. pSmbSrvOpen = NULL;
  1091. }
  1092. pInputParamBuffer = pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1093. InputParamBufferLength = pLowIoContext->ParamsFor.FsCtl.InputBufferLength;
  1094. switch (FsControlCode) {
  1095. case FSCTL_DFS_GET_REFERRALS:
  1096. {
  1097. pOutputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  1098. OutputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  1099. }
  1100. break;
  1101. case FSCTL_DFS_REPORT_INCONSISTENCY:
  1102. {
  1103. PWCHAR pDfsPathName;
  1104. //
  1105. // The input buffer from Dfs contains the path name with the inconsistency
  1106. // followed by the DFS_REFERRAL_V1 that has the inconsistency. The
  1107. // path name is sent in the Parameter section, and the DFS_REFERRAL_V1 is
  1108. // passed in the Data section. So, parse these two things out.
  1109. //
  1110. for (pDfsPathName = (PWCHAR) pInputParamBuffer;
  1111. *pDfsPathName != UNICODE_NULL;
  1112. pDfsPathName++) {
  1113. NOTHING;
  1114. }
  1115. pDfsPathName++; // Get past the NULL char
  1116. InputParamBufferLength = (ULONG) (((PCHAR)pDfsPathName) - ((PCHAR)pInputParamBuffer));
  1117. if (InputParamBufferLength >= pLowIoContext->ParamsFor.FsCtl.InputBufferLength) {
  1118. Status = STATUS_INVALID_PARAMETER;
  1119. } else {
  1120. pInputDataBuffer = (PBYTE)pDfsPathName;
  1121. InputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.InputBufferLength -
  1122. InputParamBufferLength;
  1123. }
  1124. }
  1125. break;
  1126. default:
  1127. ASSERT(!"Valid Dfs FSCTL");
  1128. }
  1129. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1130. Setup = TRANS2_GET_DFS_REFERRAL;
  1131. TransactionOptions.NtTransactFunction = 0; // TRANSACT2/TRANSACT.
  1132. TransactionOptions.pTransactionName = NULL;
  1133. TransactionOptions.TimeoutIntervalInMilliSeconds = SMBCE_TRANSACTION_TIMEOUT_NOT_USED;
  1134. Status = SmbCeTransact(
  1135. RxContext, // the RXContext for the transaction
  1136. &TransactionOptions, // transaction options
  1137. &Setup, // the setup buffer
  1138. sizeof(Setup), // setup buffer length
  1139. NULL,
  1140. 0,
  1141. pInputParamBuffer, // Input Param Buffer
  1142. InputParamBufferLength, // Input param buffer length
  1143. pOutputParamBuffer, // Output param buffer
  1144. OutputParamBufferLength, // output param buffer length
  1145. pInputDataBuffer, // Input data buffer
  1146. InputDataBufferLength, // Input data buffer length
  1147. pOutputDataBuffer, // output data buffer
  1148. OutputDataBufferLength, // output data buffer length
  1149. &ResumptionContext // the resumption context
  1150. );
  1151. if (!NT_SUCCESS(Status)) {
  1152. RxDbgTrace( 0, Dbg, ("MRxSmbDfsFsControl(%ld): Failed .. returning %lx\n",FsControlCode,Status));
  1153. } else {
  1154. RxContext->InformationToReturn = ResumptionContext.DataBytesReceived;
  1155. }
  1156. }
  1157. RxDbgTrace(-1, Dbg, ("MRxSmbDfsFsControl exit...st=%08lx\n", Status));
  1158. return Status;
  1159. }
  1160. NTSTATUS
  1161. MRxSmbFsControl(PRX_CONTEXT RxContext)
  1162. /*++
  1163. Routine Description:
  1164. This routine handles all the FSCTL's
  1165. Arguments:
  1166. RxContext - the RDBSS context
  1167. Return Value:
  1168. RXSTATUS - The return status for the operation
  1169. Notes:
  1170. Remoting of FSCTL's is permitted only to NT servers.
  1171. --*/
  1172. {
  1173. NTSTATUS Status = STATUS_SUCCESS;
  1174. RxCaptureFcb;
  1175. RxCaptureFobx;
  1176. PMRX_SMB_SRV_OPEN pSmbSrvOpen;
  1177. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1178. PFILE_OBJECT pTargetFileObject = NULL;
  1179. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  1180. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  1181. REQ_NT_IO_CONTROL FsCtlSetup;
  1182. PBYTE pInputParamBuffer = NULL;
  1183. PBYTE pOutputParamBuffer = NULL;
  1184. PBYTE pInputDataBuffer = NULL;
  1185. PBYTE pOutputDataBuffer = NULL;
  1186. #ifdef _WIN64
  1187. PBYTE pThunkedInputData = NULL;
  1188. ULONG ThunkedInputDataLength = 0;
  1189. #endif
  1190. ULONG InputParamBufferLength = 0;
  1191. ULONG OutputParamBufferLength = 0;
  1192. ULONG InputDataBufferLength = 0;
  1193. ULONG OutputDataBufferLength = 0;
  1194. USHORT FileOrTreeId;
  1195. SMB_TRANSACTION_OPTIONS TransactionOptions = DEFAULT_TRANSACTION_OPTIONS;
  1196. SMB_TRANSACTION_SEND_PARAMETERS SendParameters;
  1197. SMB_TRANSACTION_RECEIVE_PARAMETERS ReceiveParameters;
  1198. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1199. PAGED_CODE();
  1200. if (NodeType(capFcb) == RDBSS_NTC_DEVICE_FCB) {
  1201. return STATUS_INVALID_DEVICE_REQUEST;
  1202. }
  1203. if ((FsControlCode == FSCTL_LMR_SET_LINK_TRACKING_INFORMATION) &&
  1204. (RxContext->MinorFunction != IRP_MN_TRACK_LINK)) {
  1205. return STATUS_INVALID_DEVICE_REQUEST;
  1206. }
  1207. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1208. if (capFobx != NULL &&
  1209. MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)) {
  1210. return STATUS_NOT_IMPLEMENTED;
  1211. }
  1212. RxDbgTrace(+1, Dbg, ("MRxSmbFsControl...Entry FsControlCode(%lx)\n", FsControlCode));
  1213. FsCtlSetup.IsFlags = 0;
  1214. if (capFobx != NULL) {
  1215. if (NodeType(capFobx) == RDBSS_NTC_V_NETROOT) {
  1216. PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)capFobx;
  1217. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  1218. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(pVNetRoot);
  1219. // It is a root open the tree id needs to be sent to the server.
  1220. FileOrTreeId = pVNetRootContext->TreeId;
  1221. } else {
  1222. if (FsControlCode != FSCTL_LMR_GET_CONNECTION_INFO)
  1223. {
  1224. pSmbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1225. if (FlagOn(pSmbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  1226. BOOLEAN FcbAcquired = FALSE;
  1227. if (!RxIsFcbAcquiredExclusive(capFcb)) {
  1228. // This assert does not take into account the fact that other threads may
  1229. // own the resource shared, in which case we DO want to block and wait for
  1230. // the resource.
  1231. //ASSERT(!RxIsFcbAcquiredShared(capFcb));
  1232. Status = RxAcquireExclusiveFcbResourceInMRx( capFcb );
  1233. FcbAcquired = (Status == STATUS_SUCCESS);
  1234. } else {
  1235. FcbAcquired = TRUE;
  1236. }
  1237. if (FcbAcquired) {
  1238. Status = MRxSmbDeferredCreate(RxContext);
  1239. RxReleaseFcbResourceInMRx( capFcb );
  1240. }
  1241. if (Status!=STATUS_SUCCESS) {
  1242. goto FINALLY;
  1243. }
  1244. }
  1245. FileOrTreeId = pSmbSrvOpen->Fid;
  1246. }
  1247. else {
  1248. FileOrTreeId = 0;
  1249. }
  1250. }
  1251. } else {
  1252. FileOrTreeId = 0;
  1253. }
  1254. SmbPutAlignedUshort(&FsCtlSetup.Fid,FileOrTreeId);
  1255. SmbPutAlignedUlong(&FsCtlSetup.FunctionCode,FsControlCode);
  1256. FsCtlSetup.IsFsctl = TRUE;
  1257. TransactionOptions.NtTransactFunction = NT_TRANSACT_IOCTL;
  1258. TransactionOptions.pTransactionName = NULL;
  1259. Status = STATUS_SUCCESS;
  1260. switch (FsControlCode & 3) {
  1261. case METHOD_NEITHER:
  1262. {
  1263. ULONG Device;
  1264. // pInputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  1265. // InputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  1266. // pInputParamBuffer = pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1267. // InputParamBufferLength = pLowIoContext->ParamsFor.FsCtl.InputBufferLength;
  1268. // pOutputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  1269. // OutputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  1270. // pOutputParamBuffer = pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1271. // OutputParamBufferLength = pLowIoContext->ParamsFor.FsCtl.InputBufferLength;
  1272. Device = FsControlCode >> 16;
  1273. if (Device != FILE_DEVICE_FILE_SYSTEM) {
  1274. Status = STATUS_NOT_IMPLEMENTED;
  1275. break;
  1276. }
  1277. }
  1278. // fall thru.. for those FSContolcodes that belong to FILE_DEVICE_FILE_SYSTEM
  1279. // for which METHOD_NEITHER is specified we treat them as METHOD_BUFFERED
  1280. // Not Yet implemented
  1281. case METHOD_BUFFERED:
  1282. case METHOD_IN_DIRECT:
  1283. case METHOD_OUT_DIRECT:
  1284. {
  1285. pInputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1286. InputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.InputBufferLength;
  1287. pOutputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  1288. OutputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  1289. }
  1290. break;
  1291. default:
  1292. ASSERT(!"Valid Method for Fs Control");
  1293. Status = STATUS_INVALID_PARAMETER;
  1294. break;
  1295. }
  1296. #ifdef _WIN64
  1297. pThunkedInputData = pInputDataBuffer;
  1298. ThunkedInputDataLength = InputDataBufferLength;
  1299. #endif
  1300. // There is one FSCTL for which certain amount of preprocessing is required
  1301. // This is because the I/O subsystem passes in the information as a file
  1302. // object. The FID for the file object needs to be determined and the
  1303. // appropriate FID passed to the server instead of the file object.
  1304. if (FsControlCode == FSCTL_LMR_SET_LINK_TRACKING_INFORMATION) {
  1305. PREMOTE_LINK_TRACKING_INFORMATION pRemoteLinkInformation;
  1306. PMRX_FOBX pMRxFobx;
  1307. PMRX_SRV_OPEN pSrvOpen;
  1308. PMRX_SMB_SRV_OPEN pSmbSrvOpen;
  1309. try {
  1310. pRemoteLinkInformation =
  1311. (PREMOTE_LINK_TRACKING_INFORMATION)pInputDataBuffer;
  1312. if (pRemoteLinkInformation != NULL) {
  1313. pTargetFileObject = (PFILE_OBJECT)pRemoteLinkInformation->TargetFileObject;
  1314. if (pTargetFileObject != NULL) {
  1315. // Deduce the FID and substitute it for the File Object before shipping
  1316. // the FSCTL to the server.
  1317. pMRxFobx = (PMRX_FOBX)pTargetFileObject->FsContext2;
  1318. pSrvOpen = pMRxFobx->pSrvOpen;
  1319. pSmbSrvOpen = MRxSmbGetSrvOpenExtension(pSrvOpen);
  1320. if (pSmbSrvOpen != NULL) {
  1321. pRemoteLinkInformation->TargetFileObject =
  1322. (PVOID)(pSmbSrvOpen->Fid);
  1323. } else {
  1324. Status = STATUS_INVALID_PARAMETER;
  1325. }
  1326. }
  1327. #ifdef _WIN64
  1328. if( NT_SUCCESS(Status) )
  1329. {
  1330. ThunkedInputDataLength = InputDataBufferLength;
  1331. pThunkedInputData = Smb64ThunkRemoteLinkTrackingInfo( pInputDataBuffer, &ThunkedInputDataLength, &Status );
  1332. }
  1333. #endif
  1334. } else {
  1335. Status = STATUS_INVALID_PARAMETER;
  1336. }
  1337. } except(EXCEPTION_EXECUTE_HANDLER) {
  1338. Status=STATUS_INVALID_PARAMETER;
  1339. }
  1340. }
  1341. else if (FsControlCode == FSCTL_LMR_GET_CONNECTION_INFO)
  1342. {
  1343. PSMBCEDB_SERVER_ENTRY pServerEntry= SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1344. Status = STATUS_INVALID_PARAMETER;
  1345. pOutputDataBuffer = pLowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  1346. OutputDataBufferLength = pLowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  1347. if (pOutputDataBuffer && (OutputDataBufferLength==sizeof(LMR_CONNECTION_INFO_3)))
  1348. {
  1349. try
  1350. {
  1351. ProbeForWrite(
  1352. pOutputDataBuffer,
  1353. OutputDataBufferLength,
  1354. 1);
  1355. if (!memcmp(pOutputDataBuffer,EA_NAME_CSCAGENT,sizeof(EA_NAME_CSCAGENT)))
  1356. {
  1357. MRxSmbGetConnectInfoLevel3Fields(
  1358. (PLMR_CONNECTION_INFO_3)(pOutputDataBuffer),
  1359. pServerEntry,
  1360. TRUE);
  1361. Status = STATUS_SUCCESS;
  1362. }
  1363. }
  1364. except(EXCEPTION_EXECUTE_HANDLER)
  1365. {
  1366. Status=STATUS_INVALID_PARAMETER;
  1367. }
  1368. }
  1369. goto FINALLY;
  1370. }
  1371. if (NT_SUCCESS(Status)) {
  1372. #ifdef _WIN64
  1373. ASSERT( !( (FsControlCode == FSCTL_LMR_SET_LINK_TRACKING_INFORMATION) &&
  1374. (pThunkedInputData == NULL) ) );
  1375. #endif
  1376. Status = SmbCeTransact(
  1377. RxContext,
  1378. &TransactionOptions,
  1379. &FsCtlSetup,
  1380. sizeof(FsCtlSetup),
  1381. &FsCtlSetup,
  1382. sizeof(FsCtlSetup),
  1383. pInputParamBuffer,
  1384. InputParamBufferLength,
  1385. pOutputParamBuffer,
  1386. OutputParamBufferLength,
  1387. #ifndef _WIN64
  1388. pInputDataBuffer,
  1389. InputDataBufferLength,
  1390. #else
  1391. pThunkedInputData,
  1392. ThunkedInputDataLength,
  1393. #endif
  1394. pOutputDataBuffer,
  1395. OutputDataBufferLength,
  1396. &ResumptionContext);
  1397. RxContext->InformationToReturn = ResumptionContext.DataBytesReceived;
  1398. if (NT_SUCCESS(Status)) {
  1399. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1400. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1401. // invalidate the name based file info cache since it could change the attribute
  1402. // of the file on the server, i.e. FILE_ATTRIBUTE_COMPRESSED.
  1403. MRxSmbInvalidateFileInfoCache(RxContext);
  1404. // update the Fcb in case of reuse since the time stamp may have changed
  1405. ClearFlag(capFcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET);
  1406. if( RxContext->InformationToReturn > OutputDataBufferLength ) {
  1407. Status = STATUS_BUFFER_TOO_SMALL;
  1408. }
  1409. }
  1410. if( !NT_SUCCESS( Status ) ) {
  1411. // RxContext->InformationToReturn = 0;
  1412. RxDbgTrace(0,Dbg,("MRxSmbFsControl: Transaction Request Completion Status %lx\n",Status));
  1413. }
  1414. }
  1415. FINALLY:
  1416. if( FsControlCode == FSCTL_LMR_SET_LINK_TRACKING_INFORMATION )
  1417. {
  1418. #ifdef _WIN64
  1419. Smb64ReleaseThunkData( pThunkedInputData );
  1420. #endif
  1421. if( pTargetFileObject != NULL )
  1422. {
  1423. PREMOTE_LINK_TRACKING_INFORMATION pRemoteLinkInformation;
  1424. pRemoteLinkInformation =
  1425. (PREMOTE_LINK_TRACKING_INFORMATION)pInputDataBuffer;
  1426. pRemoteLinkInformation->TargetFileObject = pTargetFileObject;
  1427. }
  1428. }
  1429. RxDbgTrace(-1, Dbg, ("MRxSmbFsControl...Exit\n"));
  1430. return Status;
  1431. }
  1432. #if DBG
  1433. NTSTATUS
  1434. MRxSmbTestForLowIoIoctl(
  1435. IN PRX_CONTEXT RxContext
  1436. )
  1437. {
  1438. NTSTATUS Status = STATUS_SUCCESS;
  1439. RxCaptureFcb;RxCaptureFobx;
  1440. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  1441. PSZ Buffer = (PSZ)(LowIoContext->ParamsFor.IoCtl.pInputBuffer);
  1442. ULONG OutputBufferLength = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
  1443. ULONG InputBufferLength = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
  1444. UNICODE_STRING u;
  1445. PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME(capFobx->pSrvOpen,capFcb);
  1446. ULONG ReturnLength;
  1447. PAGED_CODE();
  1448. ReturnLength = OutputBufferLength;
  1449. if (ReturnLength > FileName->Length) {
  1450. ReturnLength = FileName->Length;
  1451. }
  1452. RxDbgTrace(0, Dbg,
  1453. ("Here in MRxSmbTestForLowIoIoctl %s, obl = %08lx, rl=%08lx\n", Buffer, OutputBufferLength, ReturnLength));
  1454. // return an obvious string to make sure that darryl is copying the results out correctly
  1455. // need to check the lengths i.e. need outputl<=inputl; also need to check that count and buffer
  1456. // are aligned for wchar
  1457. RtlCopyMemory(Buffer,FileName->Buffer,ReturnLength);
  1458. u.Buffer = (PWCHAR)(Buffer);
  1459. u.Length = u.MaximumLength = (USHORT)ReturnLength;
  1460. RtlUpcaseUnicodeString(&u,&u,FALSE);
  1461. RxContext->InformationToReturn =
  1462. //LowIoContext->ParamsFor.IoCtl.OutputBufferLength =
  1463. ReturnLength;
  1464. return(Status);
  1465. }
  1466. #endif //if DBG
  1467. NTSTATUS
  1468. MRxSmbIoCtl(
  1469. IN OUT PRX_CONTEXT RxContext)
  1470. /*++
  1471. Routine Description:
  1472. This routine performs an IOCTL operation. Currently, no calls are remoted; in
  1473. fact, the only call accepted is for debugging.
  1474. Arguments:
  1475. RxContext - the RDBSS context
  1476. Return Value:
  1477. RXSTATUS - The return status for the operation
  1478. Notes:
  1479. --*/
  1480. {
  1481. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  1482. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  1483. ULONG IoControlCode = pLowIoContext->ParamsFor.IoCtl.IoControlCode;
  1484. PAGED_CODE();
  1485. RxDbgTrace(+1, Dbg, ("MRxSmbIoCtl...\n", 0));
  1486. RxDbgTrace( 0, Dbg, ("MRxSmbIoCtl = %08lx\n", IoControlCode));
  1487. switch (IoControlCode) {
  1488. #if DBG
  1489. case IOCTL_LMMR_TESTLOWIO:
  1490. Status = MRxSmbTestForLowIoIoctl(RxContext);
  1491. break;
  1492. #endif //if DBG
  1493. default:
  1494. break;
  1495. }
  1496. RxDbgTrace(-1, Dbg, ("MRxSmbIoCtl -> %08lx\n", Status ));
  1497. return Status;
  1498. }
  1499. NTSTATUS
  1500. MRxSmbGetPrintJobId(
  1501. IN OUT PRX_CONTEXT RxContext)
  1502. /*++
  1503. Routine Description:
  1504. This routine performs an FSCTL operation (remote) on a file across the network
  1505. Arguments:
  1506. RxContext - the RDBSS context
  1507. Return Value:
  1508. RXSTATUS - The return status for the operation
  1509. Notes:
  1510. The FSCTL's handled by a mini rdr can be classified into one of two categories.
  1511. In the first category are those FSCTL's whose implementation are shared between
  1512. RDBSS and the mini rdr's and in the second category are those FSCTL's which
  1513. are totally implemented by the mini rdr's. To this a third category can be
  1514. added, i.e., those FSCTL's which should never be seen by the mini rdr's. The
  1515. third category is solely intended as a debugging aid.
  1516. The FSCTL's handled by a mini rdr can be classified based on functionality
  1517. --*/
  1518. {
  1519. NTSTATUS Status;
  1520. BOOLEAN FinalizationComplete;
  1521. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = NULL;
  1522. PSMBSTUFFER_BUFFER_STATE StufferState;
  1523. RxCaptureFobx;
  1524. RxCaptureFcb;
  1525. PIO_STACK_LOCATION IrpSp = RxContext->CurrentIrpSp;
  1526. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1527. PAGED_CODE();
  1528. RxDbgTrace(+1, Dbg, ("MRxSmbGetPrintJobId\n", 0 ));
  1529. if (capFcb == NULL || capFobx == NULL) {
  1530. return STATUS_INVALID_PARAMETER;
  1531. }
  1532. if (NodeType(capFcb) == RDBSS_NTC_DEVICE_FCB) {
  1533. return STATUS_INVALID_DEVICE_REQUEST;
  1534. }
  1535. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1536. if (FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
  1537. Status = MRxSmbFsControl(RxContext);
  1538. goto FINALLY;
  1539. }
  1540. if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(QUERY_PRINT_JOB_INFO) ) {
  1541. Status = STATUS_BUFFER_TOO_SMALL;
  1542. goto FINALLY;
  1543. }
  1544. Status= SmbPseCreateOrdinaryExchange(
  1545. RxContext,
  1546. capFobx->pSrvOpen->pVNetRoot,
  1547. SMBPSE_OE_FROM_GETPRINTJOBID,
  1548. MRxSmbCoreIoCtl,
  1549. &OrdinaryExchange
  1550. );
  1551. if (Status != STATUS_SUCCESS) {
  1552. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  1553. goto FINALLY;
  1554. }
  1555. OrdinaryExchange->AssociatedStufferState.CurrentCommand = SMB_COM_NO_ANDX_COMMAND;
  1556. StufferState = &OrdinaryExchange->AssociatedStufferState;
  1557. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  1558. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  1559. FinalizationComplete = SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  1560. ASSERT(FinalizationComplete);
  1561. FINALLY:
  1562. RxDbgTrace(-1, Dbg, ("MRxSmbIsValidDirectory exit with status=%08lx\n", Status ));
  1563. return(Status);
  1564. }
  1565. #define SPOOLER_DEVICE 0x53
  1566. #define GET_PRINTER_ID 0x60
  1567. typedef struct _SMB_RESP_PRINT_JOB_ID {
  1568. USHORT JobId;
  1569. UCHAR ServerName[LM20_CNLEN+1];
  1570. UCHAR QueueName[LM20_QNLEN+1];
  1571. UCHAR Padding; // Unknown what this padding is..
  1572. } SMB_RESP_PRINT_JOB_ID, *PSMB_RESP_PRINT_JOB_ID;
  1573. NTSTATUS
  1574. MRxSmbCoreIoCtl(
  1575. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  1576. )
  1577. /*++
  1578. Routine Description:
  1579. This is the start routine for SMB IOCTL. This initiates the construction of the
  1580. appropriate SMB.
  1581. Arguments:
  1582. pExchange - the exchange instance
  1583. Return Value:
  1584. NTSTATUS - The return status for the operation
  1585. --*/
  1586. {
  1587. NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
  1588. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  1589. RxCaptureFcb; RxCaptureFobx;
  1590. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1591. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1592. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  1593. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  1594. ULONG SmbLength;
  1595. PAGED_CODE();
  1596. RxDbgTrace(+1, Dbg, ("MRxSmbCoreIoCtl\n", 0 ));
  1597. switch (OrdinaryExchange->EntryPoint) {
  1598. case SMBPSE_OE_FROM_GETPRINTJOBID:
  1599. COVERED_CALL(
  1600. MRxSmbStartSMBCommand(
  1601. StufferState,
  1602. SetInitialSMB_ForReuse,
  1603. SMB_COM_IOCTL,
  1604. SMB_REQUEST_SIZE(IOCTL),
  1605. NO_EXTRA_DATA,
  1606. SMB_BEST_ALIGNMENT(1,0),
  1607. RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  1608. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  1609. );
  1610. MRxSmbDumpStufferState (1100,"SMB w/ GFA before stuffing",StufferState);
  1611. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  1612. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  1613. MRxSmbStuffSMB (StufferState,
  1614. "0wwwwwwwwwwwwwwB!",
  1615. // 0 UCHAR WordCount; // Count of parameter words = 8
  1616. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  1617. SPOOLER_DEVICE, // w _USHORT( Category);
  1618. GET_PRINTER_ID, // w _USHORT( Function ); // Device function
  1619. 0, // w _USHORT( TotalParameterCount ); // Total parameter bytes being sent
  1620. 0, // w _USHORT( TotalDataCount ); // Total data bytes being sent
  1621. 0, // w _USHORT( MaxParameterCount ); // Max parameter bytes to return
  1622. 0, // w _USHORT( MaxDataCount ); // Max data bytes to return
  1623. 0, // w _ULONG ( Timeout );
  1624. 0, // w _USHORT( Reserved );
  1625. 0, // w _USHORT( ParameterCount ); // Parameter bytes sent this buffer
  1626. 0, // w _USHORT( ParameterOffset ); // Offset (from header start) to params
  1627. 0, // w _USHORT( DataCount ); // Data bytes sent this buffer
  1628. 0, // w _USHORT( DataOffset ); // Offset (from header start) to data
  1629. 0, // w _USHORT( ByteCount ); // Count of data bytes
  1630. SMB_WCT_CHECK(14) 0 // _USHORT( ByteCount ); // Count of data bytes; min = 0
  1631. // UCHAR Buffer[1]; // Reserved buffer
  1632. );
  1633. break;
  1634. default:
  1635. Status = STATUS_NOT_IMPLEMENTED;
  1636. }
  1637. if (Status == STATUS_SUCCESS) {
  1638. MRxSmbDumpStufferState (700,"SMB w/ GFA after stuffing",StufferState);
  1639. Status = SmbPseOrdinaryExchange(
  1640. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1641. SMBPSE_OETYPE_IOCTL
  1642. );
  1643. }
  1644. FINALLY:
  1645. RxDbgTrace(-1, Dbg, ("MRxSmbSynchronousGetFileAttributes exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  1646. return(Status);
  1647. }
  1648. NTSTATUS
  1649. MRxSmbFinishCoreIoCtl(
  1650. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1651. PRESP_IOCTL Response
  1652. )
  1653. /*++
  1654. Routine Description:
  1655. This routine copies the print job ID and server and queue name to the user buffer.
  1656. Arguments:
  1657. OrdinaryExchange - the exchange instance
  1658. Response - the response
  1659. Return Value:
  1660. RXSTATUS - The return status for the operation
  1661. --*/
  1662. {
  1663. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1664. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1665. PIRP Irp = RxContext->CurrentIrp;
  1666. PIO_STACK_LOCATION IrpSp = RxContext->CurrentIrpSp;
  1667. PAGED_CODE();
  1668. RxDbgTrace(+1, Dbg, ("MRxSmbFinishCoreIoCtl\n", 0 ));
  1669. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishCoreIoCtl:");
  1670. switch (OrdinaryExchange->EntryPoint) {
  1671. case SMBPSE_OE_FROM_GETPRINTJOBID:
  1672. if (Response->WordCount != 8 ||
  1673. SmbGetUshort(&Response->DataCount) != sizeof(SMB_RESP_PRINT_JOB_ID)) {
  1674. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1675. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1676. } else {
  1677. OEM_STRING OemString;
  1678. UNICODE_STRING UnicodeString;
  1679. PQUERY_PRINT_JOB_INFO OutputBuffer = Irp->UserBuffer;
  1680. PSMB_RESP_PRINT_JOB_ID RespPrintJobId = (PSMB_RESP_PRINT_JOB_ID)((PUCHAR)Response+(Response->DataOffset-sizeof(SMB_HEADER)));
  1681. OutputBuffer->JobId = RespPrintJobId->JobId;
  1682. RtlInitAnsiString(&OemString, RespPrintJobId->ServerName);
  1683. UnicodeString.Buffer = OutputBuffer->ServerName;
  1684. UnicodeString.MaximumLength = sizeof(OutputBuffer->ServerName);
  1685. Status = RtlOemStringToUnicodeString(&UnicodeString, &OemString, FALSE);
  1686. if (Status == STATUS_SUCCESS) {
  1687. RtlInitAnsiString(&OemString, RespPrintJobId->QueueName);
  1688. UnicodeString.Buffer = OutputBuffer->QueueName;
  1689. UnicodeString.MaximumLength = sizeof(OutputBuffer->QueueName);
  1690. Status = RtlOemStringToUnicodeString(&UnicodeString, &OemString, FALSE);
  1691. IrpSp->Parameters.FileSystemControl.InputBufferLength = sizeof(QUERY_PRINT_JOB_INFO);
  1692. }
  1693. }
  1694. break;
  1695. default:
  1696. ASSERT(FALSE);
  1697. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1698. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1699. }
  1700. RxDbgTrace(-1, Dbg, ("MRxSmbFinishCoreIoCtl returning %08lx\n", Status ));
  1701. return Status;
  1702. }
  1703. typedef struct _SecPkgContext_TargetInformation
  1704. {
  1705. unsigned long MarshalledTargetInfoLength;
  1706. unsigned char SEC_FAR * MarshalledTargetInfo;
  1707. } SecPkgContext_TargetInformation, SEC_FAR * PSecPkgContext_TargetInformation;
  1708. NTSTATUS
  1709. MRxSmbQueryTargetInfo(
  1710. PRX_CONTEXT RxContext
  1711. )
  1712. /*++
  1713. Routine Description:
  1714. This routine performs a query target information operation against a connection
  1715. Arguments:
  1716. RxContext - the RDBSS context
  1717. Return Value:
  1718. RXSTATUS - The return status for the operation
  1719. Notes:
  1720. RDR gets the target information based on the security context of the connection and
  1721. returns the marshalled target information on the output buffer.
  1722. --*/
  1723. {
  1724. PMRX_V_NET_ROOT pVNetRoot = NULL;
  1725. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = NULL;
  1726. NTSTATUS Status = STATUS_SUCCESS;
  1727. SECURITY_STATUS SecStatus;
  1728. SecPkgContext_TargetInformation SecTargetInfo;
  1729. PLOWIO_CONTEXT pLowIoContext = &RxContext->LowIoContext;
  1730. ULONG FsControlCode = pLowIoContext->ParamsFor.FsCtl.FsControlCode;
  1731. PLMR_QUERY_TARGET_INFO LmrQueryTargetInfo = RxContext->CurrentIrp->UserBuffer;
  1732. PAGED_CODE();
  1733. RxDbgTrace(+1, Dbg, ("MRxSmbQueryTargetInfo...\n", 0));
  1734. RxDbgTrace( 0, Dbg, ("MRxSmbQueryTargetInfo = %08lx\n", FsControlCode));
  1735. if (RxContext->CurrentIrp->RequestorMode != KernelMode) {
  1736. // this FSCTLS is only supported from a kernel mode component
  1737. return STATUS_INVALID_DEVICE_REQUEST;
  1738. }
  1739. if (LmrQueryTargetInfo == NULL) {
  1740. return STATUS_INVALID_PARAMETER;
  1741. }
  1742. if (RxContext->pRelevantSrvOpen == NULL) {
  1743. return STATUS_INVALID_PARAMETER;
  1744. }
  1745. pVNetRoot = (PMRX_V_NET_ROOT)RxContext->pRelevantSrvOpen->pVNetRoot;
  1746. if (NodeType(pVNetRoot) != RDBSS_NTC_V_NETROOT) {
  1747. return STATUS_INVALID_PARAMETER;
  1748. }
  1749. pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)pVNetRoot->Context;
  1750. SecStatus = QueryContextAttributesW(
  1751. &pVNetRootContext->pSessionEntry->Session.SecurityContextHandle,
  1752. SECPKG_ATTR_TARGET_INFORMATION,
  1753. &SecTargetInfo);
  1754. Status = MapSecurityError( SecStatus );
  1755. if (Status == STATUS_SUCCESS) {
  1756. if (SecTargetInfo.MarshalledTargetInfoLength+sizeof(LMR_QUERY_TARGET_INFO) > LmrQueryTargetInfo->BufferLength) {
  1757. LmrQueryTargetInfo->BufferLength = SecTargetInfo.MarshalledTargetInfoLength + sizeof(LMR_QUERY_TARGET_INFO);
  1758. Status = STATUS_BUFFER_TOO_SMALL;
  1759. } else {
  1760. RtlCopyMemory(LmrQueryTargetInfo->TargetInfoMarshalled,
  1761. SecTargetInfo.MarshalledTargetInfo,
  1762. SecTargetInfo.MarshalledTargetInfoLength);
  1763. LmrQueryTargetInfo->BufferLength = SecTargetInfo.MarshalledTargetInfoLength;
  1764. }
  1765. {
  1766. SIZE_T MarshalledTargetInfoLength_SizeT;
  1767. MarshalledTargetInfoLength_SizeT = SecTargetInfo.MarshalledTargetInfoLength;
  1768. ZwFreeVirtualMemory(
  1769. NtCurrentProcess(),
  1770. &SecTargetInfo.MarshalledTargetInfo,
  1771. &MarshalledTargetInfoLength_SizeT,
  1772. MEM_RELEASE);
  1773. ASSERT(MarshalledTargetInfoLength_SizeT <= MAXULONG);
  1774. SecTargetInfo.MarshalledTargetInfoLength = (ULONG)MarshalledTargetInfoLength_SizeT;
  1775. }
  1776. }
  1777. return Status;
  1778. }