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.

4883 lines
163 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. openclos.c
  5. Abstract:
  6. This module implements the mini redirector call down routines pertaining to opening/
  7. closing of file/directories.
  8. Author:
  9. Joe Linn [JoeLi] 7-March-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <ntddmup.h>
  15. #include <dfsfsctl.h> //CODE.IMPROVEMENT time to put this into precomp.h???
  16. #include "csc.h"
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, MRxSmbMungeBufferingIfWriteOnlyHandles)
  19. #pragma alloc_text(PAGE, MRxSmbCopyAndTranslatePipeState)
  20. #pragma alloc_text(PAGE, IsReconnectRequired)
  21. #pragma alloc_text(PAGE, MRxSmbIsCreateWithEasSidsOrLongName)
  22. #pragma alloc_text(PAGE, MRxSmbShouldTryToCollapseThisOpen)
  23. #pragma alloc_text(PAGE, MRxSmbCreate)
  24. #pragma alloc_text(PAGE, MRxSmbDeferredCreate)
  25. #pragma alloc_text(PAGE, MRxSmbCollapseOpen)
  26. #pragma alloc_text(PAGE, MRxSmbComputeNewBufferingState)
  27. #pragma alloc_text(PAGE, MRxSmbConstructDeferredOpenContext)
  28. #pragma alloc_text(PAGE, MRxSmbAdjustCreateParameters)
  29. #pragma alloc_text(PAGE, MRxSmbAdjustReturnedCreateAction)
  30. #pragma alloc_text(PAGE, MRxSmbBuildNtCreateAndX)
  31. #pragma alloc_text(PAGE, MRxSmbBuildOpenAndX)
  32. #pragma alloc_text(PAGE, MRxSmbBuildOpenPrintFile)
  33. #pragma alloc_text(PAGE, SmbPseExchangeStart_Create)
  34. #pragma alloc_text(PAGE, MRxSmbSetSrvOpenFlags)
  35. #pragma alloc_text(PAGE, MRxSmbCreateFileSuccessTail)
  36. #pragma alloc_text(PAGE, MRxSmbFinishNTCreateAndX)
  37. #pragma alloc_text(PAGE, MRxSmbFinishOpenAndX)
  38. #pragma alloc_text(PAGE, MRxSmbFinishCreatePrintFile)
  39. #pragma alloc_text(PAGE, MRxSmbFinishT2OpenFile)
  40. #pragma alloc_text(PAGE, MRxSmbT2OpenFile)
  41. #pragma alloc_text(PAGE, MRxSmbFinishLongNameCreateFile)
  42. #pragma alloc_text(PAGE, MRxSmbCreateWithEasSidsOrLongName)
  43. #pragma alloc_text(PAGE, MRxSmbZeroExtend)
  44. #pragma alloc_text(PAGE, MRxSmbTruncate)
  45. #pragma alloc_text(PAGE, MRxSmbCleanupFobx)
  46. #pragma alloc_text(PAGE, MRxSmbForcedClose)
  47. #pragma alloc_text(PAGE, MRxSmbCloseSrvOpen)
  48. #pragma alloc_text(PAGE, MRxSmbBuildClose)
  49. #pragma alloc_text(PAGE, MRxSmbBuildClosePrintFile)
  50. #pragma alloc_text(PAGE, MRxSmbBuildFindClose)
  51. #pragma alloc_text(PAGE, SmbPseExchangeStart_Close)
  52. #pragma alloc_text(PAGE, MRxSmbFinishClose)
  53. #pragma alloc_text(PAGE, MRxSmbPreparseName )
  54. #pragma alloc_text(PAGE, MRxSmbGetConnectionId )
  55. #endif
  56. //
  57. // From ea.c.
  58. //
  59. NTSTATUS
  60. MRxSmbAddExtraAcesToSelfRelativeSD(
  61. IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor,
  62. IN BOOLEAN InheritableAces,
  63. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor
  64. );
  65. NTSTATUS
  66. MRxSmbCreateExtraAcesSelfRelativeSD(
  67. IN BOOLEAN InheritableAces,
  68. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor
  69. );
  70. //
  71. // The debug trace level
  72. //
  73. #define Dbg (DEBUG_TRACE_CREATE)
  74. // forwards
  75. NTSTATUS
  76. SmbPseExchangeStart_Create(
  77. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  78. );
  79. NTSTATUS
  80. SmbPseExchangeStart_Close(
  81. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  82. );
  83. NTSTATUS
  84. MRxSmbCreateWithEasSidsOrLongName(
  85. IN OUT PRX_CONTEXT RxContext,
  86. IN OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState
  87. );
  88. NTSTATUS
  89. MRxSmbDownlevelCreate(
  90. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  91. );
  92. ULONG MRxSmbInitialSrvOpenFlags = 0; //CODE.IMPROVEMENT this should be regeditable
  93. extern BOOLEAN MRxSmbEnableCachingOnWriteOnlyOpens;
  94. extern BOOLEAN DisableByteRangeLockingOnReadOnlyFiles;
  95. extern ULONG MRxSmbConnectionIdLevel;
  96. BOOLEAN MRxSmbDeferredOpensEnabled = TRUE; //this is regedit-able
  97. BOOLEAN MRxSmbOplocksDisabled = FALSE; //this is regedit-able
  98. #if defined(REMOTE_BOOT)
  99. //
  100. // Oplocks for disabled for remote boot clients till we run autochk at which time
  101. // it is turned on by the IOCTL.
  102. BOOLEAN MRxSmbOplocksDisabledOnRemoteBootClients = FALSE;
  103. #endif // defined(REMOTE_BOOT)
  104. extern LIST_ENTRY MRxSmbPagingFilesSrvOpenList;
  105. #ifndef FORCE_NO_NTCREATE
  106. #define MRxSmbForceNoNtCreate FALSE
  107. #else
  108. BOOLEAN MRxSmbForceNoNtCreate = TRUE;
  109. #endif
  110. #ifdef RX_PRIVATE_BUILD
  111. //CODE.IMPROVEMENT this should be on a registry setting......
  112. //#define FORCE_SMALL_BUFFERS
  113. #endif //#ifdef RX_PRIVATE_BUILD
  114. #ifndef FORCE_SMALL_BUFFERS
  115. //use size calculated from the negotiated size
  116. ULONG MrxSmbLongestShortName = 0xffff;
  117. //use the negotiated size
  118. ULONG MrxSmbCreateTransactPacketSize = 0xffff;
  119. #else
  120. ULONG MrxSmbLongestShortName = 0;
  121. ULONG MrxSmbCreateTransactPacketSize = 100;
  122. #endif
  123. LONG MRxSmbNumberOfSrvOpens = 0;
  124. INLINE VOID
  125. MRxSmbIncrementSrvOpenCount(
  126. PSMBCEDB_SERVER_ENTRY pServerEntry,
  127. PMRX_SRV_OPEN SrvOpen)
  128. {
  129. LONG NumberOfSrvOpens;
  130. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  131. if (!FlagOn(smbSrvOpen->FileInfo.Basic.FileAttributes,
  132. FILE_ATTRIBUTE_DIRECTORY)) {
  133. ASSERT(!smbSrvOpen->NumOfSrvOpenAdded);
  134. smbSrvOpen->NumOfSrvOpenAdded = TRUE;
  135. InterlockedIncrement(&pServerEntry->Server.NumberOfSrvOpens);
  136. NumberOfSrvOpens = InterlockedIncrement(&MRxSmbNumberOfSrvOpens);
  137. if (NumberOfSrvOpens == 1) {
  138. PoRegisterSystemState(
  139. MRxSmbPoRegistrationState,
  140. (ES_SYSTEM_REQUIRED | ES_CONTINUOUS));
  141. }
  142. }
  143. }
  144. VOID
  145. MRxSmbDecrementSrvOpenCount(
  146. PSMBCEDB_SERVER_ENTRY pServerEntry,
  147. LONG SrvOpenServerVersion,
  148. PMRX_SRV_OPEN SrvOpen)
  149. {
  150. LONG NumberOfSrvOpens;
  151. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  152. if (!FlagOn(smbSrvOpen->FileInfo.Basic.FileAttributes,
  153. FILE_ATTRIBUTE_DIRECTORY)) {
  154. ASSERT(smbSrvOpen->NumOfSrvOpenAdded);
  155. smbSrvOpen->NumOfSrvOpenAdded = FALSE;
  156. if (SrvOpenServerVersion == (LONG)pServerEntry->Server.Version) {
  157. ASSERT(pServerEntry->Server.NumberOfSrvOpens > 0);
  158. InterlockedDecrement(&pServerEntry->Server.NumberOfSrvOpens);
  159. }
  160. NumberOfSrvOpens = InterlockedDecrement(&MRxSmbNumberOfSrvOpens);
  161. if (NumberOfSrvOpens == 0) {
  162. PoRegisterSystemState(
  163. MRxSmbPoRegistrationState,
  164. ES_CONTINUOUS);
  165. }
  166. }
  167. }
  168. INLINE VOID
  169. MRxSmbMungeBufferingIfWriteOnlyHandles (
  170. ULONG WriteOnlySrvOpenCount,
  171. PMRX_SRV_OPEN SrvOpen
  172. )
  173. /*++
  174. Routine Description:
  175. This routine modifies the buffering flags on a srvopen so that
  176. no cacheing will be allowed if there are any write-only handles
  177. to the file.
  178. Arguments:
  179. WriteOnlySrvOpenCount - the number of writeonly srvopens
  180. SrvOpen - the srvopen whose buffring flags are to be munged
  181. Return Value:
  182. RXSTATUS - The return status for the operation
  183. --*/
  184. {
  185. BOOLEAN IsLoopBack = FALSE;
  186. PMRX_SRV_CALL pSrvCall;
  187. PSMBCEDB_SERVER_ENTRY pServerEntry;
  188. PAGED_CODE();
  189. pSrvCall = SrvOpen->pVNetRoot->pNetRoot->pSrvCall;
  190. pServerEntry = SmbCeGetAssociatedServerEntry(pSrvCall);
  191. IsLoopBack = pServerEntry->Server.IsLoopBack;
  192. if (IsLoopBack || (WriteOnlySrvOpenCount != 0)) {
  193. SrvOpen->BufferingFlags &=
  194. ~( FCB_STATE_WRITECACHEING_ENABLED |
  195. FCB_STATE_FILESIZECACHEING_ENABLED |
  196. FCB_STATE_FILETIMECACHEING_ENABLED |
  197. FCB_STATE_LOCK_BUFFERING_ENABLED |
  198. FCB_STATE_READCACHEING_ENABLED |
  199. FCB_STATE_COLLAPSING_ENABLED
  200. );
  201. }
  202. }
  203. INLINE VOID
  204. MRxSmbCopyAndTranslatePipeState(
  205. IN OUT PRX_CONTEXT RxContext,
  206. IN ULONG PipeState
  207. )
  208. /*++
  209. Routine Description:
  210. This routine updates the pipe state according to the parameters specified at
  211. setup time
  212. Arguments:
  213. RxContext - the context
  214. PipeState - the state of the pipe
  215. --*/
  216. {
  217. PAGED_CODE();
  218. if (RxContext->Create.pNetRoot->Type == NET_ROOT_PIPE) {
  219. RxContext->Create.pNetRoot->NamedPipeParameters.DataCollectionSize =
  220. MRxSmbConfiguration.NamedPipeDataCollectionSize;
  221. RxContext->Create.PipeType =
  222. ((PipeState&SMB_PIPE_TYPE_MESSAGE)==SMB_PIPE_TYPE_MESSAGE)
  223. ?FILE_PIPE_MESSAGE_TYPE:FILE_PIPE_BYTE_STREAM_TYPE;
  224. RxContext->Create.PipeReadMode =
  225. ((PipeState&SMB_PIPE_READMODE_MESSAGE)==SMB_PIPE_READMODE_MESSAGE)
  226. ?FILE_PIPE_MESSAGE_MODE:FILE_PIPE_BYTE_STREAM_MODE;
  227. RxContext->Create.PipeCompletionMode =
  228. ((PipeState&SMB_PIPE_NOWAIT)==SMB_PIPE_NOWAIT)
  229. ?FILE_PIPE_COMPLETE_OPERATION:FILE_PIPE_QUEUE_OPERATION;
  230. }
  231. }
  232. INLINE BOOLEAN
  233. IsReconnectRequired(
  234. PMRX_SRV_CALL SrvCall)
  235. /*++
  236. Routine Description:
  237. This routine determines if a reconnect is required to a given server
  238. Arguments:
  239. SrvCall - the SRV_CALL instance
  240. Return Value:
  241. TRUE if a reconnect is required
  242. --*/
  243. {
  244. BOOLEAN ReconnectRequired = FALSE;
  245. PSMBCEDB_SERVER_ENTRY pServerEntry;
  246. PAGED_CODE();
  247. pServerEntry = SmbCeGetAssociatedServerEntry(SrvCall);
  248. if (pServerEntry != NULL) {
  249. ReconnectRequired = (pServerEntry->Header.State != SMBCEDB_ACTIVE);
  250. }
  251. return ReconnectRequired;
  252. }
  253. BOOLEAN
  254. MRxSmbIsCreateWithEasSidsOrLongName(
  255. IN OUT PRX_CONTEXT RxContext,
  256. OUT PULONG DialectFlags
  257. )
  258. /*++
  259. Routine Description:
  260. This routine determines if the create operation involves EA's or security
  261. desriptors. In such cases a separate protocol is required
  262. Arguments:
  263. RxContext - the RX_CONTEXT instance
  264. DialectFlags - the dialect flags associated with the server
  265. Return Value:
  266. TRUE if a reconnect is required
  267. --*/
  268. {
  269. RxCaptureFcb;
  270. ULONG LongestShortName,LongestShortNameFromSrvBufSize;
  271. PMRX_SRV_CALL SrvCall = (PMRX_SRV_CALL)RxContext->Create.pSrvCall;
  272. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  273. PSMBCEDB_SERVER_ENTRY pServerEntry;
  274. PAGED_CODE();
  275. pServerEntry = SmbCeGetAssociatedServerEntry(SrvCall);
  276. ASSERT(pServerEntry != NULL);
  277. *DialectFlags = pServerEntry->Server.DialectFlags;
  278. // DOWN.LEVEL if the server takes OEM names or we use a different protocol
  279. // this would have to be different. maybe a switch or a precompute.
  280. LongestShortNameFromSrvBufSize =
  281. MAXIMUM_SMB_BUFFER_SIZE -
  282. QuadAlign(sizeof(NT_SMB_HEADER) +
  283. FIELD_OFFSET(REQ_NT_CREATE_ANDX,Buffer[0])
  284. );
  285. LongestShortName = min(MrxSmbLongestShortName,LongestShortNameFromSrvBufSize);
  286. return (RxContext->Create.EaLength ||
  287. RxContext->Create.SdLength ||
  288. RemainingName->Length > LongestShortName);
  289. }
  290. NTSTATUS
  291. MRxSmbShouldTryToCollapseThisOpen (
  292. IN PRX_CONTEXT RxContext
  293. )
  294. /*++
  295. Routine Description:
  296. This routine determines if the mini knows of a good reason not
  297. to try collapsing on this open. Presently, the only reason would
  298. be if this were a copychunk open.
  299. Arguments:
  300. RxContext - the RDBSS context
  301. Return Value:
  302. NTSTATUS - The return status for the operation
  303. SUCCESS --> okay to try collapse
  304. other (MORE_PROCESSING_REQUIRED) --> dont collapse
  305. --*/
  306. {
  307. NTSTATUS Status = STATUS_SUCCESS;
  308. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  309. RxCaptureFcb;
  310. PMRX_SMB_FCB smbFcb = (PMRX_SMB_FCB)capFcb->Context;
  311. PAGED_CODE();
  312. if (SrvOpen)
  313. {
  314. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  315. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)(RxContext->Create.pSrvCall->Context);
  316. if (smbSrvOpen->Version != pServerEntry->Server.Version)
  317. {
  318. return STATUS_MORE_PROCESSING_REQUIRED;
  319. }
  320. if ( smbFcb->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  321. {
  322. // This is most likely a change notify for a directory, so don't allow collapsing to make change notifies
  323. // work correctly. (Multiple notifies using different handles are different from multiple ones using the same handle)
  324. return STATUS_MORE_PROCESSING_REQUIRED;
  325. }
  326. }
  327. IF_NOT_MRXSMB_CSC_ENABLED{
  328. NOTHING;
  329. } else {
  330. if (MRxSmbCscIsThisACopyChunkOpen(RxContext, NULL)){
  331. Status = STATUS_MORE_PROCESSING_REQUIRED;
  332. }
  333. }
  334. return Status;
  335. }
  336. NTSTATUS
  337. MRxSmbCreate (
  338. IN OUT PRX_CONTEXT RxContext
  339. )
  340. /*++
  341. Routine Description:
  342. This routine opens a file across the network
  343. Arguments:
  344. RxContext - the RDBSS context
  345. Return Value:
  346. NTSTATUS - The return status for the operation
  347. --*/
  348. {
  349. NTSTATUS Status;
  350. RxCaptureFcb;
  351. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  352. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  353. PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
  354. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)SrvCall->Context;
  355. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  356. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  357. PMRX_V_NET_ROOT pVNetRoot = SrvOpen->pVNetRoot;
  358. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  359. PSMBCEDB_SESSION_ENTRY pSessionEntry ;
  360. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = NULL;
  361. BOOLEAN ReconnectRequired;
  362. BOOLEAN CreateWithEasSidsOrLongName = FALSE;
  363. ULONG DialectFlags = pServerEntry->Server.DialectFlags;
  364. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  365. PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
  366. ULONG Disposition = CreateParameters->Disposition;
  367. SMBFCB_HOLDING_STATE SmbFcbHoldingState = SmbFcb_NotHeld;
  368. SMBFCB_HOLDING_STATE OriginalSmbFcbHoldingState;
  369. PVOID OldWriteOnlyOpenRetryContext = RxContext->WriteOnlyOpenRetryContext;
  370. #if defined(REMOTE_BOOT)
  371. BOOLEAN ModifiedSd = FALSE;
  372. ULONG OriginalSdLength;
  373. PSECURITY_DESCRIPTOR SelfRelativeSd;
  374. PSECURITY_DESCRIPTOR OriginalSd;
  375. BOOLEAN NetworkCreateSucceeded = FALSE;
  376. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  377. FINISH_FCB_INIT_PARAMETERS FinishFcbInitParameters;
  378. UNICODE_STRING relativeName;
  379. PUNICODE_PREFIX_TABLE_ENTRY tableEntry;
  380. PRBR_PREFIX prefixEntry;
  381. #endif // defined(REMOTE_BOOT)
  382. PAGED_CODE();
  383. RxDbgTrace(+1, Dbg, ("MRxSmbCreate\n", 0 ));
  384. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  385. RxDbgTrace( 0, Dbg, (" Attempt to open %wZ\n", RemainingName ));
  386. if (FlagOn( capFcb->FcbState, FCB_STATE_PAGING_FILE ) &&
  387. !MRxSmbBootedRemotely) {
  388. return STATUS_NOT_IMPLEMENTED;
  389. }
  390. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_STATUS) &&
  391. MRxSmbIsStreamFile(RemainingName,NULL)) {
  392. // The Samba server return file system type NTFS but doesn't support stream
  393. return STATUS_OBJECT_PATH_NOT_FOUND;
  394. }
  395. if (!(pServerEntry->Server.DialectFlags & DF_EXTENDED_SECURITY)) {
  396. // The Create Options have been extended for NT5 servers. Since
  397. // EXTENDED_SECURITY is also only supported by NT5 servers we use
  398. // that to distinguish NT5 servers from non NT5 servers. It would
  399. // be better if we have a separate way of determining the create
  400. // options as opposed to this aliasing. This will have to do till
  401. // we can get the associated protocol change
  402. RxContext->Create.NtCreateParameters.CreateOptions &= 0xfffff;
  403. }
  404. #if defined(REMOTE_BOOT)
  405. FinishFcbInitParameters.CallFcbFinishInit = FALSE;
  406. // If it is not a remote boot machine we do not permit paging over the
  407. // net yet.
  408. //
  409. // Remote boot redirection. If the file being opened is on the remote
  410. // boot share, and the share-relative part of the name matches a prefix
  411. // in the remote boot redirection list, reparse this open over to the
  412. // local disk.
  413. //
  414. if (pVNetRoot != NULL &&
  415. (pVNetRootContext = SmbCeGetAssociatedVNetRootContext(pVNetRoot)) != NULL &&
  416. (pSessionEntry = pVNetRootContext->pSessionEntry) != NULL) {
  417. PSMBCE_SESSION pSession = &pSessionEntry->Session;
  418. if (FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION) &&
  419. (MRxSmbRemoteBootRedirectionPrefix.Length != 0)) {
  420. if (RtlPrefixUnicodeString( &MRxSmbRemoteBootPath,
  421. RemainingName,
  422. TRUE)) {
  423. relativeName.Buffer =
  424. (PWCHAR)((PCHAR)RemainingName->Buffer + MRxSmbRemoteBootPath.Length);
  425. relativeName.Length = RemainingName->Length - MRxSmbRemoteBootPath.Length;
  426. if ((relativeName.Length != 0) && (*relativeName.Buffer == L'\\')) {
  427. tableEntry = RtlFindUnicodePrefix(
  428. &MRxSmbRemoteBootRedirectionTable,
  429. &relativeName,
  430. 0);
  431. if (tableEntry != NULL) {
  432. prefixEntry = CONTAINING_RECORD( tableEntry, RBR_PREFIX, TableEntry );
  433. if ( prefixEntry->Redirect ) {
  434. UNICODE_STRING newPath;
  435. BOOLEAN reparseRequired;
  436. newPath.Length = (USHORT)(MRxSmbRemoteBootRedirectionPrefix.Length +
  437. relativeName.Length);
  438. newPath.MaximumLength = newPath.Length;
  439. // Note: Can't use RxAllocatePoolWithTag for this allocation.
  440. newPath.Buffer = RxAllocatePoolWithTag(
  441. PagedPool,
  442. newPath.Length,
  443. MRXSMB_MISC_POOLTAG );
  444. if (newPath.Buffer != NULL) {
  445. RtlCopyMemory(
  446. newPath.Buffer,
  447. MRxSmbRemoteBootRedirectionPrefix.Buffer,
  448. MRxSmbRemoteBootRedirectionPrefix.Length);
  449. RtlCopyMemory(
  450. (PCHAR)newPath.Buffer + MRxSmbRemoteBootRedirectionPrefix.Length,
  451. relativeName.Buffer,
  452. relativeName.Length);
  453. Status = RxPrepareToReparseSymbolicLink(
  454. RxContext,
  455. TRUE,
  456. &newPath,
  457. TRUE,
  458. &reparseRequired
  459. );
  460. ASSERT( reparseRequired || !NT_SUCCESS(Status) );
  461. if ( reparseRequired ) {
  462. return STATUS_REPARSE;
  463. } else {
  464. RxFreePool( newPath.Buffer );
  465. return Status;
  466. }
  467. }
  468. }
  469. }
  470. }
  471. }
  472. }
  473. }
  474. #endif // defined(REMOTE_BOOT)
  475. IF_NOT_MRXSMB_CSC_ENABLED{
  476. NOTHING;
  477. } else if (!smbSrvOpen->HotReconnectInProgress) {
  478. NTSTATUS CscCreateStatus;
  479. CscCreateStatus = MRxSmbCscCreatePrologue(RxContext,&SmbFcbHoldingState);
  480. if (CscCreateStatus != STATUS_MORE_PROCESSING_REQUIRED) {
  481. RxDbgTrace(-1, Dbg, ("MRxSmbRead shadow hit with status=%08lx\n", CscCreateStatus ));
  482. ASSERT(SmbFcbHoldingState==SmbFcb_NotHeld);
  483. return(CscCreateStatus);
  484. } else {
  485. RxDbgTrace(0, Dbg, ("MRxSmbCreate continuing from prolog w/ status=%08lx\n", CscCreateStatus ));
  486. }
  487. }
  488. OriginalSmbFcbHoldingState = SmbFcbHoldingState;
  489. // we cannot have a file cached on a write only handle. so we have to behave a little
  490. // differently if this is a write-only open. remember this in the smbsrvopen
  491. if ( ((CreateParameters->DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA)) == 0) &&
  492. ((CreateParameters->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0)
  493. ) {
  494. if (MRxSmbEnableCachingOnWriteOnlyOpens &&
  495. (RxContext->WriteOnlyOpenRetryContext == NULL)) {
  496. CreateParameters->DesiredAccess |= (FILE_READ_DATA | FILE_READ_ATTRIBUTES);
  497. RxContext->WriteOnlyOpenRetryContext = UIntToPtr( 0xaaaaaaaa );
  498. } else {
  499. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE);
  500. SrvOpen->Flags |= SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING;
  501. }
  502. }
  503. //the way that SMBs work, there is no buffering effect if we open for attributes-only
  504. //so set that up immediately.
  505. if ((CreateParameters->DesiredAccess
  506. & ~(FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE))
  507. == 0 ){
  508. SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE);
  509. }
  510. if (NetRoot->Type == NET_ROOT_MAILSLOT) {
  511. RxFinishFcbInitialization( capFcb, RDBSS_NTC_MAILSLOT, NULL);
  512. return STATUS_SUCCESS;
  513. }
  514. if ((NetRoot->Type == NET_ROOT_PIPE) &&
  515. (RemainingName->Length <= sizeof(WCHAR))) {
  516. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  517. RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx( RxContext, SrvOpen);
  518. if (RxContext->pFobx != NULL) {
  519. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  520. Status = STATUS_SUCCESS;
  521. } else {
  522. Status = STATUS_INSUFFICIENT_RESOURCES;
  523. }
  524. return Status;
  525. }
  526. // Get the control struct for the file not found name cache.
  527. //
  528. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  529. #if defined(REMOTE_BOOT)
  530. //
  531. // If this is a remote boot session, we need to put our ACLs on the
  532. // file.
  533. if (MRxSmbBootedRemotely &&
  534. MRxSmbRemoteBootDoMachineLogon &&
  535. (pVNetRoot != NULL) &&
  536. ((pVNetRootContext = SmbCeGetAssociatedVNetRootContext(pVNetRoot)) != NULL) &&
  537. ((pSessionEntry = pVNetRootContext->pSessionEntry) != NULL)) {
  538. PSMBCE_SESSION pSession = &pSessionEntry->Session;
  539. if (FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  540. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  541. //
  542. // Set this so the success tail knows to delay the call
  543. // to RxFinishFcbInitialization.
  544. //
  545. smbFcb->FinishFcbInitParameters = &FinishFcbInitParameters;
  546. if ((cp->Disposition != FILE_OPEN) && (cp->Disposition != FILE_OVERWRITE)) {
  547. PACCESS_ALLOWED_ACE CurrentAce;
  548. ULONG NewDaclSize;
  549. ULONG i;
  550. BOOLEAN IsDirectory;
  551. ModifiedSd = TRUE; // so we know to free it later.
  552. SelfRelativeSd = NULL;
  553. OriginalSdLength = RxContext->Create.SdLength;
  554. IsDirectory = (BOOLEAN)((cp->CreateOptions & FILE_DIRECTORY_FILE) != 0);
  555. if (RxContext->Create.SdLength == 0) {
  556. ASSERT (cp->SecurityContext != NULL);
  557. ASSERT (cp->SecurityContext->AccessState != NULL);
  558. //
  559. // Now create a security descriptor with the ACEs
  560. // we need in the DACL.
  561. //
  562. Status = MRxSmbCreateExtraAcesSelfRelativeSD(
  563. IsDirectory,
  564. &SelfRelativeSd);
  565. if (!NT_SUCCESS(Status)) {
  566. goto FINALLY;
  567. }
  568. //
  569. // Now replace the original SD with the new one.
  570. //
  571. cp->SecurityContext->AccessState->SecurityDescriptor = SelfRelativeSd;
  572. RxContext->Create.SdLength = RtlLengthSecurityDescriptor(SelfRelativeSd);
  573. } else {
  574. //
  575. // There is already a security descriptor there, so we
  576. // need to munge our ACLs on.
  577. //
  578. Status = MRxSmbAddExtraAcesToSelfRelativeSD(
  579. cp->SecurityContext->AccessState->SecurityDescriptor,
  580. IsDirectory,
  581. &SelfRelativeSd);
  582. if (!NT_SUCCESS(Status)) {
  583. goto FINALLY;
  584. }
  585. //
  586. // Replace the SD, saving the original.
  587. //
  588. OriginalSd = cp->SecurityContext->AccessState->SecurityDescriptor;
  589. cp->SecurityContext->AccessState->SecurityDescriptor = SelfRelativeSd;
  590. RxContext->Create.SdLength = RtlLengthSecurityDescriptor(SelfRelativeSd);
  591. }
  592. }
  593. }
  594. }
  595. #endif // defined(REMOTE_BOOT)
  596. // assume Reconnection to be trivially successful
  597. Status = STATUS_SUCCESS;
  598. if (!smbSrvOpen->HotReconnectInProgress) {
  599. CreateWithEasSidsOrLongName = MRxSmbIsCreateWithEasSidsOrLongName(RxContext,&DialectFlags);
  600. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
  601. CreateWithEasSidsOrLongName = FALSE;
  602. }
  603. }
  604. ReconnectRequired = IsReconnectRequired((PMRX_SRV_CALL)SrvCall);
  605. ////get rid of nonNT SDs right now CODE.IMPROVEMENT fix this and enable it!!
  606. //if (RxContext->Create.SdLength) {
  607. // RxDbgTrace(-1, Dbg, ("SDs w/o NTSMBS!\n"));
  608. // return((STATUS_NOT_SUPPORTED));
  609. //}
  610. //get rid of nonEA guys right now
  611. if (RxContext->Create.EaLength && !FlagOn(DialectFlags,DF_SUPPORTEA)) {
  612. RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
  613. Status = STATUS_NOT_SUPPORTED;
  614. goto FINALLY;
  615. }
  616. //
  617. // Look for this name in the Name Cache associated with the NetRoot.
  618. // If it's found and the open failed within the last 5 seconds AND
  619. // no other SMBs have been received in the interim AND
  620. // the create disposition is not (open_if or overwrite_if or create or supersede)
  621. // then fail this create with the same status as the last request
  622. // that went to the server.
  623. //
  624. if (!((Disposition==FILE_CREATE) || (Disposition==FILE_OPEN_IF) ||
  625. (Disposition==FILE_OVERWRITE_IF) || (Disposition==FILE_SUPERSEDE)) &&
  626. !ReconnectRequired &&
  627. !CreateWithEasSidsOrLongName) {
  628. //
  629. // We're not going to create it so look in name cache.
  630. //
  631. if (MRxSmbIsFileNotFoundCached(RxContext)) {
  632. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  633. goto FINALLY;
  634. }
  635. }
  636. if (ReconnectRequired || !CreateWithEasSidsOrLongName) {
  637. Status = SmbPseCreateOrdinaryExchange(
  638. RxContext,
  639. SrvOpen->pVNetRoot,
  640. SMBPSE_OE_FROM_CREATE,
  641. SmbPseExchangeStart_Create,
  642. &OrdinaryExchange);
  643. if (Status != STATUS_SUCCESS) {
  644. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  645. goto FINALLY;
  646. }
  647. OrdinaryExchange->Create.CreateWithEasSidsOrLongName = CreateWithEasSidsOrLongName;
  648. // For Creates, the resources need to be reacquired after sending an
  649. // SMB; so, do not hold onto the MIDS till finalization; instead give the MID back
  650. // right away
  651. OrdinaryExchange->SmbCeFlags &= ~SMBCE_EXCHANGE_REUSE_MID;
  652. OrdinaryExchange->SmbCeFlags |= (SMBCE_EXCHANGE_ATTEMPT_RECONNECTS |
  653. SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION);
  654. OrdinaryExchange->pSmbCeSynchronizationEvent = &RxContext->SyncEvent;
  655. OrdinaryExchange->SmbFcbHoldingState = SmbFcbHoldingState;
  656. // drop the resource before you go in!
  657. // the start routine will reacquire it on the way out.....
  658. if (!smbSrvOpen->HotReconnectInProgress) {
  659. RxReleaseFcbResourceInMRx( capFcb );
  660. }
  661. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  662. if (!smbSrvOpen->HotReconnectInProgress) {
  663. ASSERT((Status != STATUS_SUCCESS) || RxIsFcbAcquiredExclusive( capFcb ));
  664. }
  665. OrdinaryExchange->pSmbCeSynchronizationEvent = NULL;
  666. SmbFcbHoldingState = OrdinaryExchange->SmbFcbHoldingState;
  667. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  668. if (!smbSrvOpen->HotReconnectInProgress) {
  669. if (!RxIsFcbAcquiredExclusive(capFcb)) {
  670. ASSERT(!RxIsFcbAcquiredShared(capFcb));
  671. RxAcquireExclusiveFcbResourceInMRx( capFcb );
  672. }
  673. }
  674. }
  675. if (CreateWithEasSidsOrLongName && (Status == STATUS_SUCCESS)) {
  676. if (OriginalSmbFcbHoldingState != SmbFcbHoldingState) {
  677. //we have to reacquire the holding state
  678. NTSTATUS AcquireStatus = STATUS_UNSUCCESSFUL;
  679. ULONG AcquireOptions;
  680. BOOLEAN IsCopyChunkOpen = MRxSmbCscIsThisACopyChunkOpen(RxContext, NULL);
  681. //if we don't have it.....it must have been dropped........
  682. ASSERT(SmbFcbHoldingState == SmbFcb_NotHeld);
  683. if (IsCopyChunkOpen) {
  684. AcquireOptions = Exclusive_SmbFcbAcquire
  685. | DroppingFcbLock_SmbFcbAcquire
  686. | FailImmediately_SmbFcbAcquire;
  687. } else {
  688. AcquireOptions = Shared_SmbFcbAcquire
  689. | DroppingFcbLock_SmbFcbAcquire;
  690. }
  691. ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
  692. //must rezero the minirdr context.......
  693. RtlZeroMemory(&(RxContext->MRxContext[0]),sizeof(RxContext->MRxContext));
  694. AcquireStatus = MRxSmbCscAcquireSmbFcb(RxContext,AcquireOptions,&SmbFcbHoldingState);
  695. ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
  696. if (AcquireStatus != STATUS_SUCCESS) {
  697. //we couldn't acquire.....get out
  698. Status = AcquireStatus;
  699. ASSERT(SmbFcbHoldingState == SmbFcb_NotHeld);
  700. RxDbgTrace(0, Dbg,
  701. ("MRxSmbCreate couldn't reacquire!!!-> %08lx %08lx\n",RxContext,Status ));
  702. goto FINALLY;
  703. }
  704. }
  705. Status = SmbCeReconnect(RxContext->Create.pVNetRoot);
  706. if (Status == STATUS_SUCCESS)
  707. {
  708. Status = MRxSmbCreateWithEasSidsOrLongName(RxContext,
  709. &SmbFcbHoldingState );
  710. }
  711. }
  712. // There are certain downlevel servers(OS/2 servers) that return the error
  713. // STATUS_OPEN_FAILED. This is a context sensitive error code that needs to
  714. // be interpreted in conjunction with the disposition specified for the OPEN.
  715. if (Status == STATUS_OPEN_FAILED) {
  716. switch (Disposition) {
  717. //
  718. // If we were asked to create the file, and got OPEN_FAILED,
  719. // this implies that the file already exists.
  720. //
  721. case FILE_CREATE:
  722. Status = STATUS_OBJECT_NAME_COLLISION;
  723. break;
  724. //
  725. // If we were asked to open the file, and got OPEN_FAILED,
  726. // this implies that the file doesn't exist.
  727. //
  728. case FILE_OPEN:
  729. case FILE_SUPERSEDE:
  730. case FILE_OVERWRITE:
  731. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  732. break;
  733. //
  734. // If there is an error from either FILE_OPEN_IF or
  735. // FILE_OVERWRITE_IF, it indicates the user is trying to
  736. // open a file on a read-only share, so return the
  737. // correct error for that.
  738. //
  739. case FILE_OPEN_IF:
  740. case FILE_OVERWRITE_IF:
  741. Status = STATUS_NETWORK_ACCESS_DENIED;
  742. break;
  743. default:
  744. break;
  745. }
  746. }
  747. //
  748. // Check for file not found status. If this is the case then create a
  749. // name cache entry in the NetRoot name cache and record the status,
  750. // the smb received count and set the expiration time for 5 seconds.
  751. //
  752. if (Status == STATUS_SUCCESS) {
  753. //
  754. // The open succeeded so free up the name cache entry.
  755. //
  756. MRxSmbInvalidateFileNotFoundCache(RxContext);
  757. } else {
  758. if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
  759. Status == STATUS_OBJECT_PATH_NOT_FOUND) {
  760. // create the name based file not found cache
  761. MRxSmbCacheFileNotFound(RxContext);
  762. MRxSmbInvalidateInternalFileInfoCache(RxContext);
  763. } else {
  764. // invalid the name based file not found cache if other error happens
  765. MRxSmbInvalidateFileNotFoundCache(RxContext);
  766. }
  767. // invalid the name based file info cache
  768. MRxSmbInvalidateFileInfoCache(RxContext);
  769. }
  770. FINALLY:
  771. ASSERT(Status != (STATUS_PENDING));
  772. if (Status == STATUS_SUCCESS) {
  773. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SUCCESSFUL_OPEN);
  774. #if defined(REMOTE_BOOT)
  775. NetworkCreateSucceeded = TRUE;
  776. #endif // defined(REMOTE_BOOT)
  777. }
  778. #if defined(REMOTE_BOOT)
  779. //
  780. // Put back the old SD if there was one (we do this *before* calling
  781. // MRxSmbCscCreateEpilogue since it may try to apply the SD to the
  782. // shadow file).
  783. //
  784. if (ModifiedSd && !smbSrvOpen->HotReconnectInProgress) {
  785. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  786. if (SelfRelativeSd != NULL) {
  787. RxFreePool(SelfRelativeSd);
  788. }
  789. RxContext->Create.SdLength = OriginalSdLength;
  790. if (OriginalSdLength > 0) {
  791. cp->SecurityContext->AccessState->SecurityDescriptor = OriginalSd;
  792. } else {
  793. cp->SecurityContext->AccessState->SecurityDescriptor = NULL;
  794. }
  795. }
  796. #endif // defined(REMOTE_BOOT)
  797. if (!smbSrvOpen->HotReconnectInProgress &&
  798. (Status != STATUS_RETRY)) {
  799. ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
  800. MRxSmbCscCreateEpilogue(RxContext,&Status,&SmbFcbHoldingState);
  801. #if defined(REMOTE_BOOT)
  802. if (!NT_SUCCESS(Status) &&
  803. NetworkCreateSucceeded) {
  804. NTSTATUS CloseStatus;
  805. PRX_CONTEXT pLocalRxContext;
  806. RxCaptureFobx;
  807. //
  808. // Epilogue failed, we need to close the open we just did on
  809. // the network since we are going to fail the create.
  810. //
  811. ClearFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SUCCESSFUL_OPEN);
  812. pLocalRxContext = RxCreateRxContext(
  813. NULL,
  814. ((PFCB)capFcb)->RxDeviceObject,
  815. RX_CONTEXT_FLAG_WAIT|RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING);
  816. if (pLocalRxContext != NULL) {
  817. pLocalRxContext->MajorFunction = IRP_MJ_CLOSE;
  818. pLocalRxContext->pFcb = capFcb;
  819. pLocalRxContext->pFobx = capFobx;
  820. DbgPrint("ABOUT TO CALL MRXSMBCLOSESRVOPEN, STATUS FROM EPILOGUE IS %lx\n", Status);
  821. //DbgBreakPoint();
  822. CloseStatus = MRxSmbCloseSrvOpen(pLocalRxContext);
  823. DbgPrint("MRXSMBCLOSESRVOPEN STATUS IS %lx\n", CloseStatus);
  824. RxDereferenceAndDeleteRxContext(pLocalRxContext);
  825. } else {
  826. Status = STATUS_INSUFFICIENT_RESOURCES;
  827. }
  828. }
  829. #endif // defined(REMOTE_BOOT)
  830. }
  831. #if defined(REMOTE_BOOT)
  832. //
  833. // If we delayed the success tail until now, call it.
  834. //
  835. if (FinishFcbInitParameters.CallFcbFinishInit &&
  836. (Status == STATUS_SUCCESS)) {
  837. PFCB_INIT_PACKET InitPacket;
  838. if (FinishFcbInitParameters.InitPacketProvided) {
  839. InitPacket = &FinishFcbInitParameters.InitPacket;
  840. } else {
  841. InitPacket = NULL;
  842. }
  843. RxFinishFcbInitialization(
  844. capFcb,
  845. FinishFcbInitParameters.FileType,
  846. InitPacket);
  847. }
  848. #endif // defined(REMOTE_BOOT)
  849. if (Status == STATUS_NETWORK_NAME_DELETED) {
  850. Status = STATUS_RETRY;
  851. } else if (pServerEntry->Server.IsRemoteBootServer) {
  852. if (Status == STATUS_IO_TIMEOUT ||
  853. Status == STATUS_BAD_NETWORK_PATH ||
  854. Status == STATUS_NETWORK_UNREACHABLE ||
  855. Status == STATUS_REMOTE_NOT_LISTENING ||
  856. Status == STATUS_USER_SESSION_DELETED ||
  857. Status == STATUS_CONNECTION_DISCONNECTED) {
  858. RxDbgTrace(-1, Dbg, ("MRxSmbCreate: Got status %08lx, setting to RETRY status.\n", Status ));
  859. Status = STATUS_RETRY;
  860. }
  861. }
  862. if ((OldWriteOnlyOpenRetryContext == NULL) &&
  863. (RxContext->WriteOnlyOpenRetryContext != NULL)) {
  864. CreateParameters->DesiredAccess &= ~(FILE_READ_DATA | FILE_READ_ATTRIBUTES);
  865. if ((Status == STATUS_ACCESS_DENIED) ||
  866. (Status == STATUS_SHARING_VIOLATION)) {
  867. Status = STATUS_RETRY;
  868. }
  869. }
  870. RxDbgTrace(-1, Dbg, ("MRxSmbCreate exit with status=%08lx\n", Status ));
  871. RxLog(("MRxSmbCreate exits %lx\n", Status));
  872. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  873. SmbLogError(Status,
  874. LOG,
  875. MRxSmbCreate,
  876. LOGULONG(Status)
  877. LOGUSTR(*RemainingName));
  878. }
  879. return(Status);
  880. }
  881. NTSTATUS
  882. MRxSmbDeferredCreate (
  883. IN OUT PRX_CONTEXT RxContext
  884. )
  885. /*++
  886. Routine Description:
  887. This routine constructs a rxcontext from saved information and then calls
  888. MRxSmbCreate. The hard/hokey part is that we have to keep the holding state
  889. of the resource "pure". the only way to do this without getting in the middle
  890. of the tracker code is to do drop release pairs. The plan is that this is a
  891. pretty infrequent operation..........
  892. Arguments:
  893. RxContext - the RDBSS context
  894. Return Value:
  895. RXSTATUS - The return status for the operation
  896. --*/
  897. {
  898. NTSTATUS Status = STATUS_SUCCESS;
  899. RxCaptureFcb;
  900. RxCaptureFobx;
  901. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  902. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  903. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  904. PMRX_SMB_DEFERRED_OPEN_CONTEXT DeferredOpenContext = smbSrvOpen->DeferredOpenContext;
  905. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  906. PRX_CONTEXT OpenRxContext,oc;
  907. PAGED_CODE();
  908. if (!smbSrvOpen->HotReconnectInProgress &&
  909. (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)
  910. || !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN))) {
  911. Status = STATUS_SUCCESS;
  912. goto FINALLY;
  913. }
  914. if (DeferredOpenContext == NULL) {
  915. if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_CLOSED)) {
  916. Status = STATUS_FILE_CLOSED;
  917. goto FINALLY;
  918. } else {
  919. //DbgBreakPoint();
  920. }
  921. }
  922. if (!smbSrvOpen->HotReconnectInProgress) {
  923. ASSERT(RxIsFcbAcquiredExclusive(capFcb));
  924. }
  925. SmbCeAcquireResource();
  926. if (!smbSrvOpen->DeferredOpenInProgress) {
  927. PLIST_ENTRY pListHead;
  928. PLIST_ENTRY pListEntry;
  929. smbSrvOpen->DeferredOpenInProgress = TRUE;
  930. InitializeListHead(&smbSrvOpen->DeferredOpenSyncContexts);
  931. SmbCeReleaseResource();
  932. OpenRxContext = RxAllocatePoolWithTag(NonPagedPool,
  933. sizeof(RX_CONTEXT),
  934. MRXSMB_RXCONTEXT_POOLTAG);
  935. if (OpenRxContext==NULL) {
  936. Status = STATUS_INSUFFICIENT_RESOURCES;
  937. } else {
  938. RtlZeroMemory(
  939. OpenRxContext,
  940. sizeof(RX_CONTEXT));
  941. RxInitializeContext(
  942. NULL,
  943. RxContext->RxDeviceObject,
  944. 0,
  945. OpenRxContext );
  946. oc = OpenRxContext;
  947. oc->pFcb = capFcb;
  948. oc->pFobx = capFobx;
  949. oc->NonPagedFcb = RxContext->NonPagedFcb;
  950. oc->CurrentIrp = RxContext->CurrentIrp;
  951. oc->CurrentIrpSp = RxContext->CurrentIrpSp;
  952. oc->MajorFunction = IRP_MJ_CREATE;
  953. oc->pRelevantSrvOpen = SrvOpen;
  954. oc->Create.pVNetRoot = SrvOpen->pVNetRoot;
  955. oc->Create.pNetRoot = oc->Create.pVNetRoot->pNetRoot;
  956. oc->Create.pSrvCall = oc->Create.pNetRoot->pSrvCall;
  957. oc->Flags = DeferredOpenContext->RxContextFlags;
  958. oc->Flags |= RX_CONTEXT_FLAG_MINIRDR_INITIATED|RX_CONTEXT_FLAG_WAIT|RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK;
  959. oc->Create.Flags = DeferredOpenContext->RxContextCreateFlags;
  960. oc->Create.NtCreateParameters = DeferredOpenContext->NtCreateParameters;
  961. if (!smbSrvOpen->HotReconnectInProgress) {
  962. //the tracker gets very unhappy if you don't do this!
  963. //RxTrackerUpdateHistory(oc,capFcb,'aaaa',__LINE__,__FILE__,0xbadbad);
  964. }
  965. Status = MRxSmbCreate(oc);
  966. if (Status==STATUS_SUCCESS) {
  967. if (!MRxSmbIsThisADisconnectedOpen(SrvOpen)) {
  968. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  969. MRxSmbIncrementSrvOpenCount(pServerEntry,SrvOpen);
  970. } else {
  971. ASSERT(smbSrvOpen->NumOfSrvOpenAdded);
  972. if (smbSrvOpen->HotReconnectInProgress) {
  973. smbSrvOpen->NumOfSrvOpenAdded = FALSE;
  974. MRxSmbIncrementSrvOpenCount(pServerEntry,SrvOpen);
  975. }
  976. }
  977. }
  978. ClearFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  979. }
  980. if (!smbSrvOpen->HotReconnectInProgress) {
  981. //the tracker gets very unhappy if you don't do this!
  982. //RxTrackerUpdateHistory(oc,capFcb,'rrDO',__LINE__,__FILE__,0xbadbad);
  983. RxLog(("DeferredOpen %lx %lx %lx %lx\n", capFcb, capFobx, RxContext, Status));
  984. SmbLog(LOG,
  985. MRxSmbDeferredCreate_1,
  986. LOGPTR(capFcb)
  987. LOGPTR(capFobx)
  988. LOGPTR(RxContext)
  989. LOGULONG(Status));
  990. } else {
  991. RxLog(("RB Re-Open %lx %lx %lx %lx\n", capFcb, capFobx, RxContext, Status));
  992. SmbLog(LOG,
  993. MRxSmbDeferredCreate_2,
  994. LOGPTR(capFcb)
  995. LOGPTR(capFobx)
  996. LOGPTR(RxContext)
  997. LOGULONG(Status));
  998. }
  999. ASSERT(oc->ReferenceCount==1);
  1000. RxFreePool(oc);
  1001. }
  1002. if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_CLOSED) ||
  1003. FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_ORPHANED)) {
  1004. RxFreePool(smbSrvOpen->DeferredOpenContext);
  1005. smbSrvOpen->DeferredOpenContext = NULL;
  1006. RxDbgTrace(0, Dbg, ("Free deferred open context for file %wZ %lX\n",GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),smbSrvOpen));
  1007. }
  1008. SmbCeAcquireResource();
  1009. smbSrvOpen->DeferredOpenInProgress = FALSE;
  1010. pListHead = &smbSrvOpen->DeferredOpenSyncContexts;
  1011. pListEntry = pListHead->Flink;
  1012. while (pListEntry != pListHead) {
  1013. PDEFERRED_OPEN_SYNC_CONTEXT pWaitingContext;
  1014. pWaitingContext = (PDEFERRED_OPEN_SYNC_CONTEXT)CONTAINING_RECORD(
  1015. pListEntry,
  1016. DEFERRED_OPEN_SYNC_CONTEXT,
  1017. ListHead);
  1018. pListEntry = pListEntry->Flink;
  1019. RemoveHeadList(&pWaitingContext->ListHead);
  1020. pWaitingContext->Status = Status;
  1021. //DbgPrint("Signal RxContext %x after deferred open\n",pWaitingContext->RxContext);
  1022. RxSignalSynchronousWaiter(pWaitingContext->RxContext);
  1023. }
  1024. SmbCeReleaseResource();
  1025. } else {
  1026. DEFERRED_OPEN_SYNC_CONTEXT WaitingContext;
  1027. BOOLEAN AcquireExclusive = RxIsFcbAcquiredExclusive(capFcb);
  1028. BOOLEAN AcquireShare = RxIsFcbAcquiredShared(capFcb) > 0;
  1029. // put the RxContext on the waiting list
  1030. WaitingContext.RxContext = RxContext;
  1031. InitializeListHead(&WaitingContext.ListHead);
  1032. InsertTailList(
  1033. &smbSrvOpen->DeferredOpenSyncContexts,
  1034. &WaitingContext.ListHead);
  1035. SmbCeReleaseResource();
  1036. if (AcquireExclusive || AcquireShare) {
  1037. RxReleaseFcbResourceInMRx( capFcb );
  1038. }
  1039. RxWaitSync(RxContext);
  1040. Status = WaitingContext.Status;
  1041. KeInitializeEvent(
  1042. &RxContext->SyncEvent,
  1043. SynchronizationEvent,
  1044. FALSE);
  1045. if (AcquireExclusive) {
  1046. RxAcquireExclusiveFcbResourceInMRx(capFcb);
  1047. } else if (AcquireShare) {
  1048. RxAcquireSharedFcbResourceInMRx(capFcb);
  1049. }
  1050. }
  1051. FINALLY:
  1052. return Status;
  1053. }
  1054. NTSTATUS
  1055. MRxSmbCollapseOpen(
  1056. IN OUT PRX_CONTEXT RxContext
  1057. )
  1058. /*++
  1059. Routine Description:
  1060. This routine collapses a open locally
  1061. Arguments:
  1062. RxContext - the RDBSS context
  1063. Return Value:
  1064. NTSTATUS - The return status for the operation
  1065. --*/
  1066. {
  1067. NTSTATUS Status;
  1068. RxCaptureFcb;
  1069. RX_BLOCK_CONDITION FinalSrvOpenCondition;
  1070. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1071. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1072. PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
  1073. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  1074. PAGED_CODE();
  1075. RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx( RxContext, SrvOpen);
  1076. if (RxContext->pFobx != NULL) {
  1077. ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
  1078. RxContext->pFobx->OffsetOfNextEaToReturn = 1;
  1079. Status = STATUS_SUCCESS;
  1080. } else {
  1081. Status = STATUS_INSUFFICIENT_RESOURCES;
  1082. }
  1083. IF_NOT_MRXSMB_CSC_ENABLED{
  1084. ASSERT(smbSrvOpen->hfShadow == 0);
  1085. } else {
  1086. if (smbSrvOpen->hfShadow != 0) {
  1087. MRxSmbCscReportFileOpens();
  1088. }
  1089. }
  1090. return Status;
  1091. }
  1092. NTSTATUS
  1093. MRxSmbComputeNewBufferingState(
  1094. IN OUT PMRX_SRV_OPEN pMRxSrvOpen,
  1095. IN PVOID pMRxContext,
  1096. OUT PULONG pNewBufferingState)
  1097. /*++
  1098. Routine Description:
  1099. This routine maps the SMB specific oplock levels into the appropriate RDBSS
  1100. buffering state flags
  1101. Arguments:
  1102. pMRxSrvOpen - the MRX SRV_OPEN extension
  1103. pMRxContext - the context passed to RDBSS at Oplock indication time
  1104. pNewBufferingState - the place holder for the new buffering state
  1105. Return Value:
  1106. Notes:
  1107. --*/
  1108. {
  1109. ULONG OplockLevel,NewBufferingState;
  1110. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(pMRxSrvOpen);
  1111. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(pMRxSrvOpen->pFcb);
  1112. PAGED_CODE();
  1113. ASSERT(pNewBufferingState != NULL);
  1114. OplockLevel = PtrToUlong(pMRxContext);
  1115. if (OplockLevel == SMB_OPLOCK_LEVEL_II) {
  1116. NewBufferingState = (FCB_STATE_READBUFFERING_ENABLED |
  1117. FCB_STATE_READCACHEING_ENABLED);
  1118. } else {
  1119. NewBufferingState = 0;
  1120. }
  1121. pMRxSrvOpen->BufferingFlags = NewBufferingState;
  1122. MRxSmbMungeBufferingIfWriteOnlyHandles(
  1123. smbFcb->WriteOnlySrvOpenCount,
  1124. pMRxSrvOpen);
  1125. *pNewBufferingState = pMRxSrvOpen->BufferingFlags;
  1126. return STATUS_SUCCESS;
  1127. }
  1128. NTSTATUS
  1129. MRxSmbConstructDeferredOpenContext (
  1130. PRX_CONTEXT RxContext)
  1131. /*++
  1132. Routine Description:
  1133. This routine saves enough state that we can come back later and really do an
  1134. open if needed. We only do this for NT servers.
  1135. Arguments:
  1136. OrdinaryExchange - the exchange instance
  1137. Return Value:
  1138. NTSTATUS - The return status for the operation
  1139. --*/
  1140. {
  1141. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1142. RxCaptureFobx;
  1143. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1144. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1145. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)RxContext->Create.pSrvCall->Context;
  1146. PSMBCE_SERVER pServer = &pServerEntry->Server;
  1147. PMRX_SMB_DEFERRED_OPEN_CONTEXT DeferredOpenContext;
  1148. PDFS_NAME_CONTEXT pDNC=NULL;
  1149. DWORD cbSize;
  1150. PAGED_CODE();
  1151. RxDbgTrace(+1, Dbg, ("MRxSmbConstructDeferredOpenContext\n"));
  1152. //if (!FlagOn(pServer->DialectFlags,DF_NT_SMBS) && !MRxSmbBootedRemotely) {
  1153. // goto FINALLY;
  1154. //}
  1155. ASSERT(smbSrvOpen->DeferredOpenContext == NULL);
  1156. cbSize = sizeof(MRX_SMB_DEFERRED_OPEN_CONTEXT);
  1157. // if there is a dfs name context, we need to allocate memory
  1158. // fot aht too, because the name that is included in the
  1159. // context is deallocated by DFS when it returns from the create call
  1160. if(pDNC = RxContext->Create.NtCreateParameters.DfsNameContext)
  1161. {
  1162. cbSize += (sizeof(DFS_NAME_CONTEXT)+pDNC->UNCFileName.MaximumLength+sizeof(DWORD));
  1163. }
  1164. DeferredOpenContext = RxAllocatePoolWithTag(
  1165. NonPagedPool,
  1166. cbSize,
  1167. MRXSMB_DEFROPEN_POOLTAG);
  1168. if (DeferredOpenContext == NULL) {
  1169. Status = STATUS_INSUFFICIENT_RESOURCES;
  1170. goto FINALLY;
  1171. }
  1172. smbSrvOpen->DeferredOpenContext = DeferredOpenContext;
  1173. DeferredOpenContext->NtCreateParameters = RxContext->Create.NtCreateParameters;
  1174. DeferredOpenContext->RxContextCreateFlags = RxContext->Create.Flags;
  1175. DeferredOpenContext->RxContextFlags = RxContext->Flags;
  1176. DeferredOpenContext->NtCreateParameters.SecurityContext = NULL;
  1177. MRxSmbAdjustCreateParameters(RxContext, &DeferredOpenContext->SmbCp);
  1178. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN);
  1179. if (pDNC)
  1180. {
  1181. PDFS_NAME_CONTEXT pDNCDeferred=NULL;
  1182. // point the dfs name context after the rxcontext
  1183. pDNCDeferred = (PDFS_NAME_CONTEXT)((PBYTE)DeferredOpenContext+sizeof(MRX_SMB_DEFERRED_OPEN_CONTEXT));
  1184. DeferredOpenContext->NtCreateParameters.DfsNameContext = pDNCDeferred;
  1185. // copy the info
  1186. *pDNCDeferred = *pDNC;
  1187. if (pDNC->UNCFileName.Length)
  1188. {
  1189. ASSERT(pDNC->UNCFileName.Buffer);
  1190. // point the name buffer after deferredcontext+dfs_name_context
  1191. pDNCDeferred->UNCFileName.Buffer = (PWCHAR)((PBYTE)pDNCDeferred+sizeof(DFS_NAME_CONTEXT));
  1192. memcpy(pDNCDeferred->UNCFileName.Buffer,
  1193. pDNC->UNCFileName.Buffer,
  1194. pDNC->UNCFileName.Length);
  1195. }
  1196. }
  1197. FINALLY:
  1198. RxDbgTrace(-1, Dbg, ("MRxSmbConstructDeferredOpenContext, Status=%08lx\n",Status));
  1199. return Status;
  1200. }
  1201. VOID
  1202. MRxSmbAdjustCreateParameters (
  1203. PRX_CONTEXT RxContext,
  1204. PMRXSMB_CREATE_PARAMETERS smbcp
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. This uses the RxContext as a base to reeach out and get the values of the NT
  1209. create parameters. It also (a) implements the SMB idea that unbuffered is
  1210. translated to write-through and (b) gets the SMB security flags.
  1211. Arguments:
  1212. Return Value:
  1213. Notes:
  1214. --*/
  1215. {
  1216. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  1217. PAGED_CODE();
  1218. RxDbgTrace(+1, Dbg, ("MRxSmbAdjustCreateParameters\n"));
  1219. //CODE.IMPROVEMENT we might be better off looking for a deferred-open-context instead of
  1220. // minirdr-initiated.
  1221. if (!FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED)) {
  1222. cp->CreateOptions = cp->CreateOptions & ~(FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT);
  1223. //the NT SMB spec says we have to change no-intermediate-buffering to write-through
  1224. if (FlagOn(cp->CreateOptions,FILE_NO_INTERMEDIATE_BUFFERING)) {
  1225. ASSERT (RxContext->CurrentIrpSp!=NULL);
  1226. if (RxContext->CurrentIrpSp!=NULL) {
  1227. PFILE_OBJECT capFileObject = RxContext->CurrentIrpSp->FileObject;//sigh...CODE.IMPROVEMENT cp??
  1228. ClearFlag(cp->CreateOptions,FILE_NO_INTERMEDIATE_BUFFERING);
  1229. SetFlag(cp->CreateOptions,FILE_WRITE_THROUGH);
  1230. SetFlag(RxContext->Flags,RX_CONTEXT_FLAG_WRITE_THROUGH);
  1231. SetFlag(capFileObject->Flags,FO_WRITE_THROUGH);
  1232. }
  1233. }
  1234. smbcp->Pid = RxGetRequestorProcessId(RxContext);
  1235. smbcp->SecurityFlags = 0;
  1236. if (cp->SecurityContext != NULL) {
  1237. if (cp->SecurityContext->SecurityQos != NULL) {
  1238. if (cp->SecurityContext->SecurityQos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING) {
  1239. smbcp->SecurityFlags |= SMB_SECURITY_DYNAMIC_TRACKING;
  1240. }
  1241. if (cp->SecurityContext->SecurityQos->EffectiveOnly) {
  1242. smbcp->SecurityFlags |= SMB_SECURITY_EFFECTIVE_ONLY;
  1243. }
  1244. }
  1245. }
  1246. } else {
  1247. //here, we have a defered open!!!
  1248. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1249. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1250. //the parameters have already been adjusted...BUT null the security context.......
  1251. cp->SecurityContext = NULL;
  1252. *smbcp = smbSrvOpen->DeferredOpenContext->SmbCp;
  1253. }
  1254. RxDbgTrace(-1, Dbg, ("MRxSmbAdjustCreateParameters\n"));
  1255. }
  1256. INLINE VOID
  1257. MRxSmbAdjustReturnedCreateAction(
  1258. IN OUT PRX_CONTEXT RxContext
  1259. )
  1260. /*++
  1261. Routine Description:
  1262. This routine repairs a bug in NT servers whereby the create action is
  1263. contaminated by an oplock break. Basically, we make sure that if the guy
  1264. asked for FILE_OPEN and it works then he does not get FILE_SUPERCEDED or
  1265. FILE_CREATED as the result.
  1266. Arguments:
  1267. RxContext - the context for the operation so as to find the place where
  1268. info is returned
  1269. Return Value:
  1270. none
  1271. Notes:
  1272. --*/
  1273. {
  1274. ULONG q = RxContext->Create.ReturnedCreateInformation;
  1275. PAGED_CODE();
  1276. if ((q==FILE_SUPERSEDED)||(q==FILE_CREATED)||(q >FILE_MAXIMUM_DISPOSITION)) {
  1277. RxContext->Create.ReturnedCreateInformation = FILE_OPENED;
  1278. }
  1279. }
  1280. UNICODE_STRING UnicodeBackslash = {2,4,L"\\"};
  1281. NTSTATUS
  1282. MRxSmbBuildNtCreateAndX (
  1283. PSMBSTUFFER_BUFFER_STATE StufferState,
  1284. PMRXSMB_CREATE_PARAMETERS smbcp
  1285. )
  1286. /*++
  1287. Routine Description:
  1288. This builds an NtCreateAndX SMB. we don't have to worry about login id and such
  1289. since that is done by the connection engine....pretty neat huh? all we have to do
  1290. is to format up the bits
  1291. Arguments:
  1292. StufferState - the state of the smbbuffer from the stuffer's point of view
  1293. Return Value:
  1294. NTSTATUS
  1295. SUCCESS
  1296. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  1297. Notes:
  1298. --*/
  1299. {
  1300. NTSTATUS Status;
  1301. PRX_CONTEXT RxContext = StufferState->RxContext;
  1302. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  1303. RxCaptureFcb;
  1304. ACCESS_MASK DesiredAccess;
  1305. ULONG OplockFlags;
  1306. ULONG CreateOptions;
  1307. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1308. PSMBCE_SERVER pServer;
  1309. PAGED_CODE();
  1310. RxDbgTrace(+1, Dbg, ("MRxSmbBuildNtCreateAndX\n", 0 ));
  1311. pServer = SmbCeGetExchangeServer(StufferState->Exchange);
  1312. if (!pServer->IsLoopBack &&
  1313. !(cp->CreateOptions & FILE_DIRECTORY_FILE) &&
  1314. (cp->DesiredAccess & (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE )) &&
  1315. !MRxSmbOplocksDisabled
  1316. #if defined(REMOTE_BOOT)
  1317. && (!pServer->IsRemoteBootServer || !MRxSmbOplocksDisabledOnRemoteBootClients)
  1318. #endif // defined(REMOTE_BOOT)
  1319. ) {
  1320. DesiredAccess = cp->DesiredAccess & ~SYNCHRONIZE;
  1321. OplockFlags = (NT_CREATE_REQUEST_OPLOCK | NT_CREATE_REQUEST_OPBATCH);
  1322. } else {
  1323. DesiredAccess = cp->DesiredAccess;
  1324. OplockFlags = 0;
  1325. }
  1326. if (FlagOn(pServer->DialectFlags,DF_NT_STATUS)) {
  1327. CreateOptions = cp->CreateOptions;
  1328. } else {
  1329. // Samba server negotiates NT dialect bug doesn't support delete_on_close
  1330. CreateOptions = cp->CreateOptions & ~FILE_DELETE_ON_CLOSE;
  1331. }
  1332. OplockFlags |= NT_CREATE_REQUEST_EXTENDED_RESPONSE;
  1333. if ((RemainingName->Length==0)
  1334. && (FlagOn(RxContext->Create.Flags,RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH)) ) {
  1335. RemainingName = &UnicodeBackslash;
  1336. }
  1337. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never,
  1338. SMB_COM_NT_CREATE_ANDX, SMB_REQUEST_SIZE(NT_CREATE_ANDX),
  1339. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(4,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  1340. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  1341. );
  1342. SmbCeSetFullProcessIdInHeader(
  1343. StufferState->Exchange,
  1344. smbcp->Pid,
  1345. ((PNT_SMB_HEADER)StufferState->BufferBase));
  1346. MRxSmbStuffSMB (StufferState,
  1347. "XmwdddDdddDddyB",
  1348. // X UCHAR WordCount; // Count of parameter words = 24
  1349. // . UCHAR AndXCommand; // Secondary command; 0xFF = None
  1350. // . UCHAR AndXReserved; // MBZ
  1351. // . _USHORT( AndXOffset ); // Offset to next command wordcount
  1352. // m UCHAR Reserved; // MBZ
  1353. BooleanFlagOn(pServer->DialectFlags,DF_UNICODE)?
  1354. RemainingName->Length:RtlxUnicodeStringToOemSize(RemainingName),
  1355. // w _USHORT( NameLength ); // Length of Name[] in bytes
  1356. OplockFlags, // d _ULONG( Flags ); // Create flags
  1357. 0, //not used // d _ULONG( RootDirectoryFid ); // If non-zero, open is relative to this directory
  1358. DesiredAccess, // d ACCESS_MASK DesiredAccess; // NT access desired
  1359. // Dd LARGE_INTEGER AllocationSize; // Initial allocation size
  1360. SMB_OFFSET_CHECK(NT_CREATE_ANDX,AllocationSize)
  1361. cp->AllocationSize.LowPart, cp->AllocationSize.HighPart,
  1362. cp->FileAttributes, // d _ULONG( FileAttributes ); // File attributes for creation
  1363. cp->ShareAccess, // d _ULONG( ShareAccess ); // Type of share access
  1364. // D _ULONG( CreateDisposition ); // Action to take if file exists or not
  1365. SMB_OFFSET_CHECK(NT_CREATE_ANDX,CreateDisposition)
  1366. cp->Disposition,
  1367. CreateOptions, // d _ULONG( CreateOptions ); // Options to use if creating a file
  1368. cp->ImpersonationLevel,// d _ULONG( ImpersonationLevel ); // Security QOS information
  1369. smbcp->SecurityFlags, // y UCHAR SecurityFlags; // Security QOS information
  1370. SMB_WCT_CHECK(24) 0 // B _USHORT( ByteCount ); // Length of byte parameters
  1371. // . UCHAR Buffer[1];
  1372. // . //UCHAR Name[]; // File to open or create
  1373. );
  1374. //proceed with the stuff because we know here that the name fits
  1375. //CODE.IMPROVEMENT we don't need to copy here, we can just Mdl like in writes
  1376. MRxSmbStuffSMB(StufferState,
  1377. BooleanFlagOn(pServer->DialectFlags,DF_UNICODE)?"u!":"z!",
  1378. RemainingName);
  1379. MRxSmbDumpStufferState (700,"SMB w/ NTOPEN&X after stuffing",StufferState);
  1380. FINALLY:
  1381. RxDbgTraceUnIndent(-1,Dbg);
  1382. return(Status);
  1383. }
  1384. UNICODE_STRING MRxSmbOpenAndX_PipeString =
  1385. {sizeof(L"\\PIPE")-sizeof(WCHAR),sizeof(L"\\PIPE"),L"\\PIPE"};
  1386. NTSTATUS
  1387. MRxSmbBuildOpenAndX (
  1388. PSMBSTUFFER_BUFFER_STATE StufferState,
  1389. PMRXSMB_CREATE_PARAMETERS smbcp
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. This builds an OpenAndX SMB. we don't have to worry about login id and such
  1394. since that is done by the connection engine....pretty neat huh? all we have to do
  1395. is to format up the bits
  1396. Arguments:
  1397. StufferState - the state of the smbbuffer from the stuffer's point of view
  1398. Return Value:
  1399. RXSTATUS
  1400. SUCCESS
  1401. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  1402. Notes:
  1403. --*/
  1404. {
  1405. NTSTATUS Status;
  1406. PRX_CONTEXT RxContext = StufferState->RxContext;
  1407. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  1408. PSMB_EXCHANGE Exchange = StufferState->Exchange;
  1409. RxCaptureFcb;
  1410. PSMBCE_SERVER pServer;
  1411. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1412. // CODE.IMPROVEMENT a possible good idea would be to share the translation
  1413. // code with downlevel.......
  1414. USHORT smbDisposition;
  1415. USHORT smbSharingMode;
  1416. USHORT smbAttributes;
  1417. ULONG smbFileSize;
  1418. USHORT smbOpenMode;
  1419. USHORT OpenAndXFlags = (SMB_OPEN_QUERY_INFORMATION);
  1420. //CODE.IMPROVEMENT this value appears all over the rdr
  1421. USHORT SearchAttributes = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN;
  1422. LARGE_INTEGER CurrentTime;
  1423. ULONG SecondsSince1970;
  1424. PAGED_CODE();
  1425. RxDbgTrace(+1, Dbg, ("MRxSmbBuildOpenAndX\n", 0 ));
  1426. pServer = SmbCeGetExchangeServer(Exchange);
  1427. smbDisposition = MRxSmbMapDisposition(cp->Disposition);
  1428. smbSharingMode = MRxSmbMapShareAccess(((USHORT)cp->ShareAccess));
  1429. smbAttributes = MRxSmbMapFileAttributes(cp->FileAttributes);
  1430. smbFileSize = cp->AllocationSize.LowPart;
  1431. smbOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
  1432. smbSharingMode |= smbOpenMode;
  1433. if (cp->CreateOptions & FILE_WRITE_THROUGH) {
  1434. smbSharingMode |= SMB_DA_WRITE_THROUGH;
  1435. }
  1436. //lanman10 servers apparently don't like to get the time passed in.......
  1437. if (FlagOn(pServer->DialectFlags,DF_LANMAN20)) {
  1438. KeQuerySystemTime(&CurrentTime);
  1439. MRxSmbTimeToSecondsSince1970(&CurrentTime,
  1440. pServer,
  1441. &SecondsSince1970);
  1442. } else {
  1443. SecondsSince1970 = 0;
  1444. }
  1445. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never,
  1446. SMB_COM_OPEN_ANDX, SMB_REQUEST_SIZE(OPEN_ANDX),
  1447. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(4,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  1448. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  1449. );
  1450. MRxSmbStuffSMB (StufferState,
  1451. "XwwwwdwDddB",
  1452. // X UCHAR WordCount; // Count of parameter words = 15
  1453. // . UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
  1454. // . UCHAR AndXReserved; // Reserved (must be 0)
  1455. // . _USHORT( AndXOffset ); // Offset to next command WordCount
  1456. OpenAndXFlags, // w _USHORT( Flags ); // Additional information: bit set-
  1457. // // 0 - return additional info
  1458. // // 1 - set single user total file lock
  1459. // // 2 - server notifies consumer of
  1460. // // actions which may change file
  1461. smbSharingMode, // w _USHORT( DesiredAccess ); // File open mode
  1462. SearchAttributes, // w _USHORT( SearchAttributes );
  1463. smbAttributes, // w _USHORT( FileAttributes );
  1464. SecondsSince1970, // d _ULONG( CreationTimeInSeconds );
  1465. smbDisposition, // w _USHORT( OpenFunction );
  1466. // D _ULONG( AllocationSize ); // Bytes to reserve on create or truncate
  1467. SMB_OFFSET_CHECK(OPEN_ANDX,AllocationSize)
  1468. smbFileSize,
  1469. 0xffffffff, // d _ULONG( Timeout ); // Max milliseconds to wait for resource
  1470. 0, // d _ULONG( Reserved ); // Reserved (must be 0)
  1471. SMB_WCT_CHECK(15) 0 // B _USHORT( ByteCount ); // Count of data bytes; min = 1
  1472. // UCHAR Buffer[1]; // File name
  1473. );
  1474. //proceed with the stuff because we know here that the name fits
  1475. if (capFcb->pNetRoot->Type == NET_ROOT_PIPE) {
  1476. //for open&x, you have to put \PIPE if it's a pipe....
  1477. MRxSmbStuffSMB (StufferState,"z>!", &MRxSmbOpenAndX_PipeString,RemainingName);
  1478. } else {
  1479. MRxSmbStuffSMB (StufferState,"z!", RemainingName);
  1480. }
  1481. MRxSmbDumpStufferState (700,"SMB w/ OPEN&X after stuffing",StufferState);
  1482. FINALLY:
  1483. RxDbgTraceUnIndent(-1,Dbg);
  1484. return(Status);
  1485. }
  1486. NTSTATUS
  1487. MRxSmbBuildOpenPrintFile (
  1488. PSMBSTUFFER_BUFFER_STATE StufferState
  1489. )
  1490. /*++
  1491. Routine Description:
  1492. This builds an OpenPrintFile SMB. we don't have to worry about login id and such
  1493. since that is done by the connection engine....pretty neat huh? all we have to do
  1494. is to format up the bits
  1495. Arguments:
  1496. StufferState - the state of the smbbuffer from the stuffer's point of view
  1497. Return Value:
  1498. RXSTATUS
  1499. SUCCESS
  1500. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  1501. Notes:
  1502. --*/
  1503. {
  1504. NTSTATUS Status;
  1505. PRX_CONTEXT RxContext = StufferState->RxContext;
  1506. WCHAR UserNameBuffer[UNLEN + 1];
  1507. WCHAR UserDomainNameBuffer[UNLEN + 1];
  1508. UNICODE_STRING UserName,UserDomainName;
  1509. PAGED_CODE();
  1510. RxDbgTrace(+1, Dbg, ("MRxSmbOpenPrintFile\n", 0 ));
  1511. UserName.Length = UserName.MaximumLength = UNLEN * sizeof(WCHAR);
  1512. UserName.Buffer = UserNameBuffer;
  1513. UserDomainName.Length = UserDomainName.MaximumLength = UNLEN * sizeof(WCHAR);
  1514. UserDomainName.Buffer = UserDomainNameBuffer;
  1515. Status = SmbCeGetUserNameAndDomainName(
  1516. SmbCeGetExchangeSessionEntry(StufferState->Exchange),
  1517. &UserName,
  1518. &UserDomainName);
  1519. if (Status != STATUS_SUCCESS) {
  1520. RtlInitUnicodeString(&UserName,L"RDR2ID");
  1521. } else {
  1522. RtlUpcaseUnicodeString(&UserName,&UserName,FALSE);
  1523. }
  1524. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never,
  1525. SMB_COM_OPEN_PRINT_FILE, SMB_REQUEST_SIZE(OPEN_PRINT_FILE),
  1526. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(4,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  1527. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  1528. );
  1529. SmbCeSetFullProcessIdInHeader(
  1530. StufferState->Exchange,
  1531. RxGetRequestorProcessId(RxContext),
  1532. ((PNT_SMB_HEADER)StufferState->BufferBase));
  1533. // note that we hardwire graphics..........
  1534. MRxSmbStuffSMB (StufferState,
  1535. "0wwB4!",
  1536. // 0 UCHAR WordCount; // Count of parameter words = 2
  1537. 0, // w _USHORT( SetupLength ); // Length of printer setup data
  1538. 1, // w _USHORT( Mode ); // 0 = Text mode (DOS expands TABs)
  1539. // // 1 = Graphics mode
  1540. SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  1541. // UCHAR Buffer[1]; // Buffer containing:
  1542. &UserName // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  1543. // //UCHAR IdentifierString[]; // Identifier string
  1544. );
  1545. MRxSmbDumpStufferState (700,"SMB w/ openprintfile after stuffing",StufferState);
  1546. FINALLY:
  1547. RxDbgTraceUnIndent(-1,Dbg);
  1548. return(Status);
  1549. }
  1550. typedef enum _SMBPSE_CREATE_METHOD {
  1551. CreateAlreadyDone,
  1552. CreateUseCore,
  1553. CreateUseNT
  1554. } SMBPSE_CREATE_METHOD;
  1555. NTSTATUS
  1556. SmbPseExchangeStart_Create(
  1557. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  1558. )
  1559. /*++
  1560. Routine Description:
  1561. This is the start routine for net root construction exchanges. This initiates the
  1562. construction of the appropriate SMB's if required.
  1563. Arguments:
  1564. pExchange - the exchange instance
  1565. Return Value:
  1566. NTSTATUS - The return status for the operation
  1567. --*/
  1568. {
  1569. NTSTATUS Status = (STATUS_NOT_IMPLEMENTED);
  1570. NTSTATUS SetupStatus = STATUS_SUCCESS;
  1571. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  1572. SMBPSE_CREATE_METHOD CreateMethod = CreateAlreadyDone;
  1573. PSMBCE_SERVER pServer;
  1574. ULONG DialectFlags;
  1575. RxCaptureFcb;
  1576. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1577. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  1578. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1579. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1580. PSMBCE_NET_ROOT pSmbNetRoot = &(OrdinaryExchange->SmbCeContext.pVNetRootContext->pNetRootEntry->NetRoot);
  1581. PBOOLEAN MustRegainExclusiveResource = &OrdinaryExchange->Create.MustRegainExclusiveResource;
  1582. BOOLEAN CreateWithEasSidsOrLongName = OrdinaryExchange->Create.CreateWithEasSidsOrLongName;
  1583. BOOLEAN fRetryCore = FALSE;
  1584. PAGED_CODE();
  1585. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_Create\n", 0 ));
  1586. ASSERT_ORDINARY_EXCHANGE(OrdinaryExchange);
  1587. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  1588. DialectFlags = pServer->DialectFlags;
  1589. COVERED_CALL(MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0)));
  1590. if (!smbSrvOpen->HotReconnectInProgress) {
  1591. *MustRegainExclusiveResource = TRUE;
  1592. }
  1593. if (!FlagOn(DialectFlags,DF_NT_SMBS)) {
  1594. OEM_STRING OemString;
  1595. PUNICODE_STRING PathName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  1596. if (PathName->Length != 0) {
  1597. Status = RtlUnicodeStringToOemString(&OemString, PathName, TRUE);
  1598. if (!NT_SUCCESS(Status)) {
  1599. goto FINALLY;
  1600. }
  1601. //
  1602. // If we are canonicalizing as FAT, use FAT rules, otherwise use
  1603. // HPFS rules.
  1604. //
  1605. if (!FlagOn(DialectFlags,DF_LANMAN20)) {
  1606. if (!FsRtlIsFatDbcsLegal(OemString, FALSE, TRUE, TRUE)) {
  1607. RtlFreeOemString(&OemString);
  1608. Status = STATUS_OBJECT_NAME_INVALID;
  1609. goto FINALLY;
  1610. }
  1611. } else if (!FsRtlIsHpfsDbcsLegal(OemString, FALSE, TRUE, TRUE)) {
  1612. RtlFreeOemString(&OemString);
  1613. Status = STATUS_OBJECT_NAME_INVALID;
  1614. goto FINALLY;
  1615. }
  1616. RtlFreeOemString(&OemString);
  1617. }
  1618. }
  1619. if (StufferState->PreviousCommand != SMB_COM_NO_ANDX_COMMAND) {
  1620. // we have a latent session setup /tree connect command
  1621. //CODE.IMPROVEMENT for nt4.0+ we should get things changed so that NT_CREATE&X is a valid
  1622. // followon for SS&X and TC&X. we would get a bit better performance for NT3.51- if we
  1623. // used an open&x here instead.
  1624. //the status of the embedded header commands is passed back in the flags...joejoe make a proc
  1625. SetupStatus = SmbPseOrdinaryExchange(
  1626. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1627. SMBPSE_OETYPE_LATENT_HEADEROPS
  1628. );
  1629. if(SetupStatus != STATUS_SUCCESS) {
  1630. Status = SetupStatus;
  1631. goto FINALLY;
  1632. }
  1633. SmbCeUpdateSessionEntryAndVNetRootContext((PSMB_EXCHANGE)OrdinaryExchange);
  1634. // Turn off reconnect attempts now that we have successfully established
  1635. // the session and net root.
  1636. OrdinaryExchange->SmbCeFlags &= ~(SMBCE_EXCHANGE_ATTEMPT_RECONNECTS);
  1637. COVERED_CALL(MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0)));
  1638. }
  1639. if (!CreateWithEasSidsOrLongName) {
  1640. PUNICODE_STRING AlreadyPrefixedName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  1641. PMRXSMB_CREATE_PARAMETERS SmbCp = &OrdinaryExchange->Create.SmbCp;
  1642. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  1643. USHORT mappedOpenMode;
  1644. MRxSmbAdjustCreateParameters(RxContext,SmbCp);
  1645. mappedOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
  1646. if (capFcb->pNetRoot->Type == NET_ROOT_PRINT) {
  1647. COVERED_CALL(MRxSmbBuildOpenPrintFile(StufferState));
  1648. Status = SmbPseOrdinaryExchange(
  1649. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1650. SMBPSE_OETYPE_CREATEPRINTFILE
  1651. );
  1652. } else if ((!MRxSmbForceNoNtCreate)
  1653. && FlagOn(DialectFlags,DF_NT_SMBS)) {
  1654. BOOLEAN SecurityIsNULL =
  1655. (cp->SecurityContext == NULL) ||
  1656. (cp->SecurityContext->AccessState == NULL) ||
  1657. (cp->SecurityContext->AccessState->SecurityDescriptor == NULL);
  1658. CreateMethod = CreateUseNT;
  1659. //now catch the cases where we want to pseudoopen the file
  1660. if ( MRxSmbDeferredOpensEnabled &&
  1661. !FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED) &&
  1662. (capFcb->pNetRoot->Type == NET_ROOT_DISK) &&
  1663. SecurityIsNULL) {
  1664. ASSERT( RxContext->CurrentIrp != 0 );
  1665. if ((cp->Disposition==FILE_OPEN) &&
  1666. !BooleanFlagOn(cp->CreateOptions, FILE_OPEN_FOR_BACKUP_INTENT) &&
  1667. (!(cp->DesiredAccess & DELETE)||(capFcb->OpenCount == 0)) &&
  1668. (MustBeDirectory(cp->CreateOptions) ||
  1669. !(cp->DesiredAccess & ~(SYNCHRONIZE | DELETE | FILE_READ_ATTRIBUTES)))){
  1670. // NT apps expect that you will not succeed the create and then fail the attribs;
  1671. // if we had some way of identifying win32 apps then we could defer these (except
  1672. // for DFS). since we have no way to get that information (and don't even have
  1673. // a good SMB to send..........)
  1674. // we don't need to send the open for DELETE and FILE_READ_ATTRIBUTES requests since
  1675. // there are path basied SMB operations.
  1676. // we can also pseudoopen directories for file_open at the root of the
  1677. // share but otherwise we have to at least check that the directory
  1678. // exists. we might have to push out the open later. BTW, we wouldn't be
  1679. // in here if the name was too long for a GFA or CheckPath
  1680. Status = MRxSmbPseudoOpenTailFromFakeGFAResponse(
  1681. OrdinaryExchange,
  1682. MustBeDirectory(cp->CreateOptions)?FileTypeDirectory:FileTypeFile);
  1683. if (Status == STATUS_SUCCESS) {
  1684. // query the basic information to make sure the file exists on the server
  1685. //DbgPrint("Query basic with path\n");
  1686. Status = MRxSmbQueryFileInformationFromPseudoOpen(
  1687. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1688. FileBasicInformation);
  1689. if (Status == STATUS_SUCCESS) {
  1690. if (MustBeDirectory(cp->CreateOptions)) {
  1691. if (!OrdinaryExchange->Create.FileInfo.Standard.Directory) {
  1692. Status = STATUS_NOT_A_DIRECTORY;
  1693. }
  1694. } else {
  1695. if (OrdinaryExchange->Create.FileInfo.Standard.Directory) {
  1696. capFcb->Header.NodeTypeCode = RDBSS_STORAGE_NTC(FileTypeDirectory);
  1697. smbFcb->dwFileAttributes = OrdinaryExchange->Create.FileInfo.Basic.FileAttributes;
  1698. }
  1699. }
  1700. }
  1701. if ((Status == STATUS_SUCCESS) &&
  1702. (cp->DesiredAccess & DELETE) &&
  1703. (smbFcb->IndexNumber.QuadPart == 0) &&
  1704. (FlagOn(DialectFlags,DF_EXTENDED_SECURITY)) &&
  1705. (pSmbNetRoot->NetRootFileSystem == NET_ROOT_FILESYSTEM_NTFS)) {
  1706. // query internal information for the FID
  1707. //DbgPrint("Query Internal with path\n");
  1708. Status = MRxSmbQueryFileInformationFromPseudoOpen(
  1709. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1710. FileInternalInformation);
  1711. if (Status == STATUS_SUCCESS) {
  1712. smbFcb->IndexNumber = OrdinaryExchange->Create.FileInfo.Internal.IndexNumber;
  1713. //DbgPrint("FCB %x smbFcb %x %08x%08x\n",capFcb,smbFcb,smbFcb->IndexNumber.HighPart,smbFcb->IndexNumber.LowPart);
  1714. }
  1715. }
  1716. if (Status != STATUS_SUCCESS) {
  1717. RxFreePool(smbSrvOpen->DeferredOpenContext);
  1718. smbSrvOpen->DeferredOpenContext = NULL;
  1719. }
  1720. }
  1721. CreateMethod = CreateAlreadyDone;
  1722. }
  1723. }
  1724. //if no pseudoopen case was hit, do a real open
  1725. if (CreateMethod == CreateUseNT) {
  1726. //use NT_CREATE&X
  1727. COVERED_CALL(MRxSmbBuildNtCreateAndX(StufferState,SmbCp));
  1728. Status = SmbPseOrdinaryExchange(
  1729. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1730. SMBPSE_OETYPE_CREATE
  1731. );
  1732. if ((Status != STATUS_SUCCESS) &&
  1733. (NetRoot->Type == NET_ROOT_PIPE) &&
  1734. (OrdinaryExchange->SendCompletionStatus != STATUS_SUCCESS)) {
  1735. // If a cluster server disconnect, the VC is valid until the send operation.
  1736. // A retry will ensure the seamless failover for PIPE creation.
  1737. Status = STATUS_RETRY;
  1738. }
  1739. if (Status == STATUS_SUCCESS && RxContext->pFobx == NULL) {
  1740. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1741. }
  1742. if ((Status == STATUS_SUCCESS) && (cp->Disposition == FILE_OPEN)) {
  1743. MRxSmbAdjustReturnedCreateAction(RxContext);
  1744. }
  1745. if (Status == STATUS_SUCCESS) {
  1746. MRxSmbInvalidateFileNotFoundCache(RxContext);
  1747. }
  1748. if ((Status == STATUS_SUCCESS) &&
  1749. (smbFcb->IndexNumber.QuadPart == 0) &&
  1750. (FlagOn(DialectFlags,DF_EXTENDED_SECURITY)) &&
  1751. (pSmbNetRoot->NetRootFileSystem == NET_ROOT_FILESYSTEM_NTFS)) {
  1752. // query internal information for the FID
  1753. Status = MRxSmbQueryFileInformationFromPseudoOpen(
  1754. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1755. FileInternalInformation);
  1756. if (Status == STATUS_SUCCESS) {
  1757. smbFcb->IndexNumber = OrdinaryExchange->Create.FileInfo.Internal.IndexNumber;
  1758. //DbgPrint("FCB %x smbFcb %x %08x%08x\n",capFcb,smbFcb,smbFcb->IndexNumber.HighPart,smbFcb->IndexNumber.LowPart);
  1759. }
  1760. }
  1761. }
  1762. } else if (FlagOn(DialectFlags, DF_LANMAN10) &&
  1763. (mappedOpenMode != ((USHORT)-1)) &&
  1764. !MustBeDirectory(cp->CreateOptions)) {
  1765. PUNICODE_STRING PathName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  1766. if (MRxSmbDeferredOpensEnabled &&
  1767. capFcb->pNetRoot->Type == NET_ROOT_DISK &&
  1768. !FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED) &&
  1769. (pServer->Dialect != LANMAN21_DIALECT || MustBeDirectory(cp->CreateOptions)) &&
  1770. (cp->Disposition==FILE_OPEN) && ((PathName->Length == 0) ||
  1771. ((cp->DesiredAccess & ~(SYNCHRONIZE | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) == 0)) ){
  1772. // we don't need to send the open for DELETE and FILE_READ_ATTRIBUTES requests since
  1773. // there are path basied SMB operations.
  1774. // we should do pseudo open for FILE_WRITE_ATTRIBUTES. Othewise the server will return
  1775. // sharing violation
  1776. // send query path information to make sure the file exists on the server
  1777. Status = MRxSmbPseudoOpenTailFromFakeGFAResponse(
  1778. OrdinaryExchange,
  1779. MustBeDirectory(cp->CreateOptions)?FileTypeDirectory:FileTypeFile);
  1780. if (Status == STATUS_SUCCESS && AlreadyPrefixedName->Length > 0) {
  1781. Status = MRxSmbQueryFileInformationFromPseudoOpen(
  1782. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1783. FileBasicInformation);
  1784. if (Status != STATUS_SUCCESS) {
  1785. RxFreePool(smbSrvOpen->DeferredOpenContext);
  1786. smbSrvOpen->DeferredOpenContext = NULL;
  1787. }
  1788. }
  1789. CreateMethod = CreateAlreadyDone;
  1790. } else {
  1791. //use OPEN&X
  1792. COVERED_CALL(MRxSmbBuildOpenAndX(StufferState,SmbCp)); //CODE.IMPROVEMENT dont pass smbcp
  1793. Status = SmbPseOrdinaryExchange(
  1794. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1795. SMBPSE_OETYPE_CREATE
  1796. );
  1797. if (Status == STATUS_ACCESS_DENIED && !FlagOn(DialectFlags,DF_NT_SMBS)) {
  1798. CreateMethod = CreateUseCore;
  1799. fRetryCore = TRUE;
  1800. }
  1801. }
  1802. } else {
  1803. CreateMethod = CreateUseCore;
  1804. }
  1805. if (CreateMethod == CreateUseCore) {
  1806. Status = MRxSmbDownlevelCreate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1807. // put back the real error code if we are retrying open&x
  1808. if ((Status != STATUS_SUCCESS) && fRetryCore)
  1809. {
  1810. Status = STATUS_ACCESS_DENIED;
  1811. }
  1812. }
  1813. }
  1814. FINALLY:
  1815. if (*MustRegainExclusiveResource) {
  1816. SMBFCB_HOLDING_STATE *SmbFcbHoldingState = &OrdinaryExchange->SmbFcbHoldingState;
  1817. if (*SmbFcbHoldingState != SmbFcb_NotHeld) {
  1818. MRxSmbCscReleaseSmbFcb(RxContext,SmbFcbHoldingState);
  1819. }
  1820. RxAcquireExclusiveFcbResourceInMRx( capFcb );
  1821. }
  1822. // now that we have the fcb exclusive, we can do some updates
  1823. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE)) {
  1824. smbFcb->WriteOnlySrvOpenCount++;
  1825. }
  1826. MRxSmbMungeBufferingIfWriteOnlyHandles(
  1827. smbFcb->WriteOnlySrvOpenCount,
  1828. SrvOpen
  1829. );
  1830. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Create exit w %08lx\n", Status ));
  1831. return Status;
  1832. }
  1833. VOID
  1834. MRxSmbSetSrvOpenFlags (
  1835. PRX_CONTEXT RxContext,
  1836. RX_FILE_TYPE StorageType,
  1837. PMRX_SRV_OPEN SrvOpen,
  1838. PMRX_SMB_SRV_OPEN smbSrvOpen
  1839. )
  1840. {
  1841. PAGED_CODE();
  1842. RxDbgTrace( 0, Dbg, ("MRxSmbSetSrvOpenFlags oplockstate =%08lx\n", smbSrvOpen->OplockLevel ));
  1843. SrvOpen->BufferingFlags = 0;
  1844. if (!FlagOn(SrvOpen->pFcb->Attributes,FILE_ATTRIBUTE_SPARSE_FILE) ) {
  1845. switch (smbSrvOpen->OplockLevel) {
  1846. case SMB_OPLOCK_LEVEL_II:
  1847. SrvOpen->BufferingFlags |= (FCB_STATE_READBUFFERING_ENABLED |
  1848. FCB_STATE_READCACHEING_ENABLED);
  1849. break;
  1850. case SMB_OPLOCK_LEVEL_BATCH:
  1851. if (StorageType == FileTypeFile) {
  1852. SrvOpen->BufferingFlags |= FCB_STATE_COLLAPSING_ENABLED;
  1853. }
  1854. // lack of break intentional
  1855. case SMB_OPLOCK_LEVEL_EXCLUSIVE:
  1856. SrvOpen->BufferingFlags |= (FCB_STATE_WRITECACHEING_ENABLED |
  1857. FCB_STATE_FILESIZECACHEING_ENABLED |
  1858. FCB_STATE_FILETIMECACHEING_ENABLED |
  1859. FCB_STATE_WRITEBUFFERING_ENABLED |
  1860. FCB_STATE_LOCK_BUFFERING_ENABLED |
  1861. FCB_STATE_READBUFFERING_ENABLED |
  1862. FCB_STATE_READCACHEING_ENABLED);
  1863. break;
  1864. default:
  1865. ASSERT(!"Valid Oplock Level for Open");
  1866. case SMB_OPLOCK_LEVEL_NONE:
  1867. break;
  1868. }
  1869. }
  1870. SrvOpen->Flags |= MRxSmbInitialSrvOpenFlags;
  1871. }
  1872. NTSTATUS
  1873. MRxSmbCreateFileSuccessTail (
  1874. PRX_CONTEXT RxContext,
  1875. PBOOLEAN MustRegainExclusiveResource,
  1876. SMBFCB_HOLDING_STATE *SmbFcbHoldingState,
  1877. RX_FILE_TYPE StorageType,
  1878. SMB_FILE_ID Fid,
  1879. ULONG ServerVersion,
  1880. UCHAR OplockLevel,
  1881. ULONG CreateAction,
  1882. PSMBPSE_FILEINFO_BUNDLE FileInfo
  1883. )
  1884. /*++
  1885. Routine Description:
  1886. This routine finishes the initialization of the fcb and srvopen for a successful open.
  1887. Arguments:
  1888. Return Value:
  1889. NTSTATUS - The return status for the operation
  1890. --*/
  1891. {
  1892. NTSTATUS Status = STATUS_SUCCESS;
  1893. RxCaptureFcb;
  1894. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1895. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1896. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1897. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)RxContext->Create.pSrvCall->Context;
  1898. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)SrvOpen->pVNetRoot->Context;
  1899. ACCESS_MASK DesiredAccess = RxContext->Create.NtCreateParameters.DesiredAccess;
  1900. BOOLEAN ThisIsAPseudoOpen;
  1901. FCB_INIT_PACKET LocalInitPacket, *InitPacket;
  1902. PAGED_CODE();
  1903. RxDbgTrace(+1, Dbg, ("MRxSmbCreateFileSuccessTail\n", 0 ));
  1904. smbSrvOpen->Fid = Fid;
  1905. smbSrvOpen->Version = ServerVersion;
  1906. if (smbSrvOpen->HotReconnectInProgress) {
  1907. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1908. //capFcb->ActualAllocationLength = pFileInfo->Standard.AllocationSize.QuadPart;
  1909. //capFcb->Header.AllocationSize = pFileInfo->Standard.AllocationSize;
  1910. //capFcb->Header.FileSize = pFileInfo->Standard.EndOfFile;
  1911. //capFcb->Header.ValidDataLength = pFileInfo->Standard.EndOfFile;
  1912. // in case oplock breaks after re-open
  1913. if ((smbSrvOpen->OplockLevel != OplockLevel) &&
  1914. (pServerEntry->pRdbssSrvCall != NULL)) {
  1915. ULONG NewOplockLevel;
  1916. switch (OplockLevel) {
  1917. case OPLOCK_BROKEN_TO_II:
  1918. NewOplockLevel = SMB_OPLOCK_LEVEL_II;
  1919. break;
  1920. case OPLOCK_BROKEN_TO_NONE:
  1921. default:
  1922. NewOplockLevel = SMB_OPLOCK_LEVEL_NONE;
  1923. }
  1924. RxIndicateChangeOfBufferingState(
  1925. pServerEntry->pRdbssSrvCall,
  1926. MRxSmbMakeSrvOpenKey(pVNetRootContext->TreeId, Fid),
  1927. ULongToPtr(NewOplockLevel));
  1928. }
  1929. } else {
  1930. PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1931. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)SrvOpen->pVNetRoot->Context;
  1932. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  1933. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  1934. if (*SmbFcbHoldingState != SmbFcb_NotHeld) {
  1935. MRxSmbCscReleaseSmbFcb(
  1936. RxContext,
  1937. SmbFcbHoldingState);
  1938. }
  1939. if (*MustRegainExclusiveResource) {
  1940. //this is required because of oplock breaks
  1941. RxAcquireExclusiveFcbResourceInMRx( capFcb );
  1942. *MustRegainExclusiveResource = FALSE;
  1943. }
  1944. if (RxContext->pFobx==NULL) {
  1945. RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
  1946. }
  1947. ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
  1948. RxDbgTrace(
  1949. 0, Dbg,
  1950. ("Storagetype %08lx/Fid %08lx/Action %08lx\n", StorageType, Fid, CreateAction ));
  1951. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(SrvOpen->pVNetRoot);
  1952. SrvOpen->Key = MRxSmbMakeSrvOpenKey(pVNetRootContext->TreeId,Fid);
  1953. // UPGRADE OPLOCK ON READ ONLY
  1954. if (DisableByteRangeLockingOnReadOnlyFiles &&
  1955. (OplockLevel == SMB_OPLOCK_LEVEL_II) &&
  1956. (FileInfo->Basic.FileAttributes & FILE_ATTRIBUTE_READONLY) &&
  1957. ((DesiredAccess & FILE_GENERIC_READ) ||
  1958. !(DesiredAccess & FILE_GENERIC_WRITE) ||
  1959. !(DesiredAccess & ~(FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | STANDARD_RIGHTS_READ)))) {
  1960. OplockLevel = SMB_OPLOCK_LEVEL_BATCH;
  1961. }
  1962. if (MRxSmbIsStreamFile(FileName,NULL)) {
  1963. smbSrvOpen->OplockLevel = SMB_OPLOCK_LEVEL_NONE;
  1964. } else {
  1965. smbSrvOpen->OplockLevel = OplockLevel;
  1966. }
  1967. RxContext->Create.ReturnedCreateInformation = CreateAction;
  1968. //CODE.IMPROVEMENT maybe we shouldn't set the allocation up here.....rather we should max it where we use it
  1969. //sometimes the allocation is wrong! max it......
  1970. //CODE.IMPROVEMENT why not use 64bit compare????
  1971. if ( ((FileInfo->Standard.AllocationSize.HighPart == FileInfo->Standard.EndOfFile.HighPart)
  1972. && (FileInfo->Standard.AllocationSize.LowPart < FileInfo->Standard.EndOfFile.LowPart))
  1973. || (FileInfo->Standard.AllocationSize.HighPart < FileInfo->Standard.EndOfFile.HighPart)
  1974. ) {
  1975. FileInfo->Standard.AllocationSize = FileInfo->Standard.EndOfFile;
  1976. }
  1977. smbFcb->LastCscTimeStampHigh = FileInfo->Basic.LastWriteTime.HighPart;
  1978. smbFcb->LastCscTimeStampLow = FileInfo->Basic.LastWriteTime.LowPart;
  1979. smbFcb->NewShadowSize = FileInfo->Standard.EndOfFile;
  1980. smbFcb->dwFileAttributes = FileInfo->Basic.FileAttributes;
  1981. if (smbSrvOpen->OplockLevel > smbFcb->LastOplockLevel) {
  1982. ClearFlag(
  1983. capFcb->FcbState,
  1984. FCB_STATE_TIME_AND_SIZE_ALREADY_SET);
  1985. }
  1986. smbFcb->LastOplockLevel = smbSrvOpen->OplockLevel;
  1987. //the thing is this: if we have good info (not a pseudoopen) then we make the
  1988. //finish call passing the init packet; otherwise, we make the call NOT passing an init packet
  1989. ThisIsAPseudoOpen = BooleanFlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  1990. if (!ThisIsAPseudoOpen &&
  1991. !MRxSmbIsThisADisconnectedOpen(SrvOpen)) {
  1992. MRxSmbCreateFileInfoCache(RxContext,
  1993. FileInfo,
  1994. pServerEntry,
  1995. STATUS_SUCCESS);
  1996. MRxSmbIncrementSrvOpenCount(pServerEntry,SrvOpen);
  1997. }
  1998. if ((capFcb->OpenCount == 0) ||
  1999. (!ThisIsAPseudoOpen &&
  2000. !FlagOn(capFcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET))) {
  2001. if (!ThisIsAPseudoOpen) {
  2002. RxFormInitPacket(
  2003. LocalInitPacket,
  2004. &FileInfo->Basic.FileAttributes,
  2005. &FileInfo->Standard.NumberOfLinks,
  2006. &FileInfo->Basic.CreationTime,
  2007. &FileInfo->Basic.LastAccessTime,
  2008. &FileInfo->Basic.LastWriteTime,
  2009. &FileInfo->Basic.ChangeTime,
  2010. &FileInfo->Standard.AllocationSize,
  2011. &FileInfo->Standard.EndOfFile,
  2012. &FileInfo->Standard.EndOfFile);
  2013. InitPacket = &LocalInitPacket;
  2014. } else {
  2015. InitPacket = NULL;
  2016. }
  2017. #if defined(REMOTE_BOOT)
  2018. //
  2019. // If the caller wants it (on a remote boot system), then
  2020. // save the parameters to call RxFinishFcbInitialization
  2021. // later.
  2022. //
  2023. if (smbFcb->FinishFcbInitParameters) {
  2024. smbFcb->FinishFcbInitParameters->CallFcbFinishInit = TRUE;
  2025. smbFcb->FinishFcbInitParameters->FileType = RDBSS_STORAGE_NTC(StorageType);
  2026. if (InitPacket) {
  2027. smbFcb->FinishFcbInitParameters->InitPacketProvided = TRUE;
  2028. RtlCopyMemory(
  2029. &smbFcb->FinishFcbInitParameters->InitPacket,
  2030. InitPacket,
  2031. sizeof(FCB_INIT_PACKET));
  2032. } else {
  2033. smbFcb->FinishFcbInitParameters->InitPacketProvided = FALSE;
  2034. }
  2035. } else
  2036. #endif // defined(REMOTE_BOOT)
  2037. // initialize only if the filesize version is identical.
  2038. // This takes care of the situation where a create has retruned from the server
  2039. // with some file size, and before it gets here the file has been extended
  2040. // and the size has increased.
  2041. // The version is snapped by the create in SrvOpen and is incremented
  2042. // by the code that extends the filesize (in extending write)
  2043. if (((PFCB)capFcb)->ulFileSizeVersion == SrvOpen->ulFileSizeVersion)
  2044. {
  2045. RxFinishFcbInitialization( capFcb,
  2046. RDBSS_STORAGE_NTC(StorageType),
  2047. InitPacket
  2048. );
  2049. }
  2050. if (FlagOn( capFcb->FcbState, FCB_STATE_PAGING_FILE )) {
  2051. PPAGING_FILE_CONTEXT PagingFileContext;
  2052. ASSERT(FALSE);
  2053. PagingFileContext = RxAllocatePoolWithTag(NonPagedPool,
  2054. sizeof(PAGING_FILE_CONTEXT),
  2055. MRXSMB_MISC_POOLTAG);
  2056. if (PagingFileContext != NULL) {
  2057. PagingFileContext->pSrvOpen = SrvOpen;
  2058. PagingFileContext->pFobx = RxContext->pFobx;
  2059. InsertHeadList(
  2060. &MRxSmbPagingFilesSrvOpenList,
  2061. &PagingFileContext->ContextList);
  2062. } else {
  2063. Status = STATUS_INSUFFICIENT_RESOURCES;
  2064. }
  2065. }
  2066. }
  2067. if (Status == STATUS_SUCCESS &&
  2068. !SmbCeIsServerInDisconnectedMode(pServerEntry) &&
  2069. pVNetRootContext->pNetRootEntry->IsRemoteBoot) {
  2070. if (smbSrvOpen->DeferredOpenContext == NULL) {
  2071. Status = MRxSmbConstructDeferredOpenContext(RxContext);
  2072. if (Status == STATUS_SUCCESS) {
  2073. smbSrvOpen->DeferredOpenContext->NtCreateParameters.Disposition = FILE_OPEN;
  2074. ClearFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN);
  2075. }
  2076. }
  2077. }
  2078. MRxSmbSetSrvOpenFlags(RxContext,StorageType,SrvOpen,smbSrvOpen);
  2079. //(wrapperFcb->Condition) = Condition_Good;
  2080. RxContext->pFobx->OffsetOfNextEaToReturn = 1;
  2081. //transition happens later
  2082. }
  2083. RxDbgTrace(-1, Dbg, ("MRxSmbFinishCreateFile returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  2084. return Status;
  2085. }
  2086. NTSTATUS
  2087. MRxSmbFinishNTCreateAndX (
  2088. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  2089. PRESP_NT_CREATE_ANDX Response
  2090. )
  2091. /*++
  2092. Routine Description:
  2093. This routine actually gets the stuff out of the NTCreate_AndX response.
  2094. Arguments:
  2095. OrdinaryExchange - the exchange instance
  2096. Response - the response
  2097. Return Value:
  2098. RXSTATUS - The return status for the operation
  2099. --*/
  2100. {
  2101. NTSTATUS Status = STATUS_SUCCESS;
  2102. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  2103. RxCaptureFcb;
  2104. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2105. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2106. PSMBCE_SESSION pSession = SmbCeGetExchangeSession(OrdinaryExchange);
  2107. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetExchangeNetRootEntry(OrdinaryExchange);
  2108. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  2109. PSMBCE_NET_ROOT pSmbNetRoot = &(pNetRootEntry->NetRoot);
  2110. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  2111. RX_FILE_TYPE StorageType;
  2112. SMB_FILE_ID Fid;
  2113. ULONG CreateAction;
  2114. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  2115. PAGED_CODE();
  2116. RxDbgTrace(+1, Dbg, ("MRxSmbFinishNTCreateAndX\n", 0 ));
  2117. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  2118. if (FlagOn(pServer->DialectFlags,DF_NT_STATUS) &&
  2119. RxContext->Create.NtCreateParameters.CreateOptions & FILE_DELETE_ON_CLOSE) {
  2120. // Samba server negotiates NT dialect but doesn't support delete_after_close
  2121. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  2122. SetFlag((smbFcb)->MFlags,SMB_FCB_FLAG_SENT_DISPOSITION_INFO);
  2123. }
  2124. StorageType = RxInferFileType(RxContext);
  2125. if (StorageType == 0) {
  2126. StorageType = Response->Directory
  2127. ?(FileTypeDirectory)
  2128. :(FileTypeFile);
  2129. RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
  2130. }
  2131. Fid = SmbGetUshort(&Response->Fid);
  2132. CreateAction = SmbGetUlong(&Response->CreateAction);
  2133. pFileInfo->Basic.FileAttributes = SmbGetUlong(&Response->FileAttributes);
  2134. pFileInfo->Standard.NumberOfLinks = 1;
  2135. pFileInfo->Basic.CreationTime.LowPart = SmbGetUlong(&Response->CreationTime.LowPart);
  2136. pFileInfo->Basic.CreationTime.HighPart = SmbGetUlong(&Response->CreationTime.HighPart);
  2137. pFileInfo->Basic.LastAccessTime.LowPart = SmbGetUlong(&Response->LastAccessTime.LowPart);
  2138. pFileInfo->Basic.LastAccessTime.HighPart = SmbGetUlong(&Response->LastAccessTime.HighPart);
  2139. pFileInfo->Basic.LastWriteTime.LowPart = SmbGetUlong(&Response->LastWriteTime.LowPart);
  2140. pFileInfo->Basic.LastWriteTime.HighPart = SmbGetUlong(&Response->LastWriteTime.HighPart);
  2141. pFileInfo->Basic.ChangeTime.LowPart = SmbGetUlong(&Response->ChangeTime.LowPart);
  2142. pFileInfo->Basic.ChangeTime.HighPart = SmbGetUlong(&Response->ChangeTime.HighPart);
  2143. pFileInfo->Standard.AllocationSize.LowPart = SmbGetUlong(&Response->AllocationSize.LowPart);
  2144. pFileInfo->Standard.AllocationSize.HighPart = SmbGetUlong(&Response->AllocationSize.HighPart);
  2145. pFileInfo->Standard.EndOfFile.LowPart = SmbGetUlong(&Response->EndOfFile.LowPart);
  2146. pFileInfo->Standard.EndOfFile.HighPart = SmbGetUlong(&Response->EndOfFile.HighPart);
  2147. pFileInfo->Standard.Directory = Response->Directory;
  2148. MRxSmbCopyAndTranslatePipeState(RxContext,
  2149. SmbGetUshort(&Response->DeviceState));
  2150. // If this is an EXTENDED create responce copy the appropriate information.
  2151. // Note that this code relies on the fact that the fields common to
  2152. // RESP_NT_CREATE_ANDX and RESP_EXTENDED_NT_CREATE_ANDX have identical
  2153. // offsets in the two structures.
  2154. if (Response->WordCount == 42) {
  2155. PRESP_EXTENDED_NT_CREATE_ANDX ExtendedResponse;
  2156. ULONG AccessRights;
  2157. ExtendedResponse = (PRESP_EXTENDED_NT_CREATE_ANDX)Response;
  2158. AccessRights = SmbGetUlong(&ExtendedResponse->MaximalAccessRights);
  2159. smbSrvOpen->MaximalAccessRights = AccessRights;
  2160. AccessRights = SmbGetUlong(&ExtendedResponse->GuestMaximalAccessRights);
  2161. smbSrvOpen->GuestMaximalAccessRights = AccessRights;
  2162. } else {
  2163. // If the NT_CREATE_ANDX was to a downlevel server the access rights
  2164. // information is not available. Currently we default to maximum
  2165. // access for the current user and no access to other users in the
  2166. // disconnected mode for such files
  2167. smbSrvOpen->MaximalAccessRights = FILE_ALL_ACCESS;
  2168. smbSrvOpen->GuestMaximalAccessRights = 0;
  2169. }
  2170. if (Response->OplockLevel > SMB_OPLOCK_LEVEL_NONE) {
  2171. smbSrvOpen->FileStatusFlags = Response->FileStatusFlags;
  2172. smbSrvOpen->IsNtCreate = TRUE;
  2173. }
  2174. MRxSmbCreateFileSuccessTail (
  2175. RxContext,
  2176. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  2177. &OrdinaryExchange->SmbFcbHoldingState,
  2178. StorageType,
  2179. Fid,
  2180. OrdinaryExchange->ServerVersion,
  2181. Response->OplockLevel,
  2182. CreateAction,
  2183. pFileInfo
  2184. );
  2185. RxDbgTrace(-1, Dbg, ("MRxSmbFinishNTCreateAndX returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  2186. return Status;
  2187. }
  2188. NTSTATUS
  2189. MRxSmbFinishOpenAndX (
  2190. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  2191. PRESP_OPEN_ANDX Response
  2192. )
  2193. /*++
  2194. Routine Description:
  2195. This routine actually gets the stuff out of the NTCreate_AndX response.
  2196. Arguments:
  2197. OrdinaryExchange - the exchange instance
  2198. Response - the response
  2199. Return Value:
  2200. NTSTATUS - The return status for the operation
  2201. --*/
  2202. {
  2203. NTSTATUS Status = STATUS_SUCCESS;
  2204. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  2205. ULONG Disposition = RxContext->Create.NtCreateParameters.Disposition;
  2206. RxCaptureFcb;
  2207. RX_FILE_TYPE StorageType;
  2208. SMB_FILE_ID Fid;
  2209. UCHAR OplockLevel = SMB_OPLOCK_LEVEL_NONE;
  2210. ULONG CreateAction;
  2211. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2212. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2213. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  2214. PAGED_CODE();
  2215. RxDbgTrace(+1, Dbg, ("MRxSmbFinishOpenAndX\n", 0 ));
  2216. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  2217. StorageType = RxInferFileType(RxContext);
  2218. if (StorageType == 0) {
  2219. StorageType = FileTypeFile;
  2220. RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
  2221. }
  2222. ASSERT (StorageType == FileTypeFile);
  2223. Fid = SmbGetUshort(&Response->Fid);
  2224. if (SmbGetUshort(&Response->Action) & SMB_OACT_OPLOCK) {
  2225. OplockLevel = SMB_OPLOCK_LEVEL_BATCH; //we only ever ask for batch currently!!!
  2226. }
  2227. CreateAction = MRxSmbUnmapDisposition(SmbGetUshort(&Response->Action),Disposition);
  2228. pFileInfo->Basic.FileAttributes =
  2229. MRxSmbMapSmbAttributes(SmbGetUshort(&Response->FileAttributes));
  2230. // This is a downlevel server, the access rights
  2231. // information is not available. Currently we default to maximum
  2232. // access for the current user and no access to other users in the
  2233. // disconnected mode for such files
  2234. smbSrvOpen->MaximalAccessRights = FILE_ALL_ACCESS;
  2235. smbSrvOpen->GuestMaximalAccessRights = 0;
  2236. MRxSmbSecondsSince1970ToTime(
  2237. SmbGetUlong(&Response->LastWriteTimeInSeconds),
  2238. SmbCeGetExchangeServer(OrdinaryExchange),
  2239. &pFileInfo->Basic.LastWriteTime);
  2240. pFileInfo->Standard.NumberOfLinks = 1;
  2241. pFileInfo->Basic.CreationTime.HighPart = 0;
  2242. pFileInfo->Basic.CreationTime.LowPart = 0;
  2243. pFileInfo->Basic.LastAccessTime.HighPart = 0;
  2244. pFileInfo->Basic.LastAccessTime.LowPart = 0;
  2245. pFileInfo->Basic.ChangeTime.HighPart = 0;
  2246. pFileInfo->Basic.ChangeTime.LowPart = 0;
  2247. pFileInfo->Standard.EndOfFile.HighPart = 0;
  2248. pFileInfo->Standard.EndOfFile.LowPart = SmbGetUlong(&Response->DataSize);
  2249. pFileInfo->Standard.AllocationSize.QuadPart = pFileInfo->Standard.EndOfFile.QuadPart;
  2250. pFileInfo->Standard.Directory = (StorageType == FileTypeDirectory);
  2251. MRxSmbCopyAndTranslatePipeState(
  2252. RxContext,
  2253. SmbGetUshort(&Response->DeviceState) );
  2254. MRxSmbCreateFileSuccessTail (
  2255. RxContext,
  2256. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  2257. &OrdinaryExchange->SmbFcbHoldingState,
  2258. StorageType,
  2259. Fid,
  2260. OrdinaryExchange->ServerVersion,
  2261. OplockLevel,
  2262. CreateAction,
  2263. pFileInfo );
  2264. RxDbgTrace(-1, Dbg, ("MRxSmbFinishOpenAndX returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  2265. return Status;
  2266. }
  2267. NTSTATUS
  2268. MRxSmbFinishCreatePrintFile (
  2269. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  2270. PRESP_OPEN_PRINT_FILE Response
  2271. )
  2272. /*++
  2273. Routine Description:
  2274. This routine actually gets the stuff out of the NTCreate_AndX response.
  2275. Arguments:
  2276. OrdinaryExchange - the exchange instance
  2277. Response - the response
  2278. Return Value:
  2279. NTSTATUS - The return status for the operation
  2280. --*/
  2281. {
  2282. NTSTATUS Status = STATUS_SUCCESS;
  2283. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  2284. RxCaptureFcb;
  2285. RX_FILE_TYPE StorageType;
  2286. SMB_FILE_ID Fid;
  2287. ULONG CreateAction;
  2288. SMBPSE_FILEINFO_BUNDLE FileInfo;
  2289. PAGED_CODE();
  2290. RxDbgTrace(+1, Dbg, ("MRxSmbFinishCreatePrintFile\n", 0 ));
  2291. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  2292. StorageType = RDBSS_NTC_SPOOLFILE-RDBSS_NTC_STORAGE_TYPE_UNKNOWN;
  2293. Fid = SmbGetUshort(&Response->Fid);
  2294. CreateAction = FILE_OPENED;
  2295. RtlZeroMemory(
  2296. &FileInfo,
  2297. sizeof(FileInfo));
  2298. MRxSmbCreateFileSuccessTail (
  2299. RxContext,
  2300. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  2301. &OrdinaryExchange->SmbFcbHoldingState,
  2302. StorageType,
  2303. Fid,
  2304. OrdinaryExchange->ServerVersion,
  2305. SMB_OPLOCK_LEVEL_NONE,
  2306. CreateAction,
  2307. &FileInfo );
  2308. RxDbgTrace(-1, Dbg, ("MRxSmbFinishCreatePrintFile returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  2309. return Status;
  2310. }
  2311. NTSTATUS
  2312. MRxSmbFinishT2OpenFile (
  2313. IN OUT PRX_CONTEXT RxContext,
  2314. IN PRESP_OPEN2 Response,
  2315. IN OUT PBOOLEAN MustRegainExclusiveResource,
  2316. IN OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState,
  2317. IN ULONG ServerVersion
  2318. )
  2319. /*++
  2320. Routine Description:
  2321. This routine actually gets the stuff out of the T2/Open response.
  2322. CODE.IMPROVEMENT This routine is almost identical to the finish routine for NT long names
  2323. which, in turn, is almost the same as for short names. see the longname routine
  2324. details. CODE.IMPROVEMENT.ASHAMED this really is crappy........
  2325. Arguments:
  2326. RxContext - the context of the operation being performed
  2327. Response - the response
  2328. Return Value:
  2329. RXSTATUS - The return status for the operation
  2330. --*/
  2331. {
  2332. NTSTATUS Status = STATUS_SUCCESS;
  2333. RxCaptureFcb;
  2334. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2335. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2336. RX_FILE_TYPE StorageType;
  2337. SMB_FILE_ID Fid;
  2338. ULONG CreateAction;
  2339. ULONG Disposition = RxContext->Create.NtCreateParameters.Disposition;
  2340. ULONG FileAttributes;
  2341. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  2342. PAGED_CODE();
  2343. RxDbgTrace(+1, Dbg, ("MRxSmbFinishT2OpenFile\n", 0 ));
  2344. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  2345. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  2346. FileAttributes = MRxSmbMapSmbAttributes(Response->FileAttributes);
  2347. StorageType = RxInferFileType(RxContext);
  2348. if (StorageType == 0) {
  2349. StorageType = (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2350. ? FileTypeDirectory
  2351. : FileTypeFile;
  2352. }
  2353. if ((capFcb->OpenCount != 0) &&
  2354. (StorageType != 0) &&
  2355. (NodeType(capFcb) != RDBSS_STORAGE_NTC(StorageType))) {
  2356. return STATUS_OBJECT_TYPE_MISMATCH;
  2357. }
  2358. Fid = Response->Fid;
  2359. CreateAction = MRxSmbUnmapDisposition(Response->Action,Disposition);
  2360. RxDbgTrace( 0, Dbg, ("Storagetype %08lx/Fid %08lx/Action %08lx\n", StorageType, Fid, CreateAction ));
  2361. if (Response->Action & SMB_OACT_OPLOCK) {
  2362. smbSrvOpen->OplockLevel = SMB_OPLOCK_LEVEL_BATCH; //we only ever ask for batch currently!!!
  2363. }
  2364. RxContext->Create.ReturnedCreateInformation = CreateAction;
  2365. if (capFcb->OpenCount == 0) {
  2366. //
  2367. // Please note that we mask off the low bit on the time stamp here.
  2368. //
  2369. // We do this since the time stamps returned from other smbs (notably SmbGetAttrE and
  2370. // T2QueryDirectory) have a granularity of 2 seconds, while this
  2371. // time stamp has a granularity of 1 second. In order to make these
  2372. // two times consistant, we mask off the low order second in the
  2373. // timestamp. this idea was lifted from rdr1.
  2374. //
  2375. PSMBCEDB_SERVER_ENTRY pServerEntry;
  2376. pServerEntry = SmbCeReferenceAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  2377. ASSERT(pServerEntry != NULL);
  2378. MRxSmbSecondsSince1970ToTime(Response->CreationTimeInSeconds&0xfffffffe,
  2379. &pServerEntry->Server,
  2380. &pFileInfo->Basic.CreationTime);
  2381. SmbCeDereferenceServerEntry(pServerEntry);
  2382. }
  2383. pFileInfo->Basic.FileAttributes = FileAttributes;
  2384. pFileInfo->Basic.LastAccessTime.QuadPart = 0;
  2385. pFileInfo->Basic.LastWriteTime.QuadPart = 0;
  2386. pFileInfo->Basic.ChangeTime.QuadPart = 0;
  2387. pFileInfo->Standard.NumberOfLinks = 1;
  2388. pFileInfo->Standard.AllocationSize.QuadPart =
  2389. pFileInfo->Standard.EndOfFile.QuadPart = Response->DataSize;
  2390. pFileInfo->Standard.Directory = (StorageType == FileTypeDirectory);
  2391. MRxSmbCopyAndTranslatePipeState(
  2392. RxContext,
  2393. SmbGetUshort(&Response->DeviceState) );
  2394. MRxSmbCreateFileSuccessTail(
  2395. RxContext,
  2396. MustRegainExclusiveResource,
  2397. SmbFcbHoldingState,
  2398. StorageType,
  2399. Fid,
  2400. ServerVersion,
  2401. smbSrvOpen->OplockLevel,
  2402. CreateAction,
  2403. pFileInfo);
  2404. RxDbgTrace(-1, Dbg, ("MRxSmbFinishT2OpenFile returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  2405. return Status;
  2406. }
  2407. //#define MULTI_EA_MDL
  2408. NTSTATUS
  2409. MRxSmbT2OpenFile(
  2410. IN OUT PRX_CONTEXT RxContext,
  2411. IN OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState
  2412. )
  2413. /*++
  2414. Routine Description:
  2415. This routine opens a file across the network that has
  2416. 1) EAs,
  2417. 2) a name so long that it wont fit in an ordinary packet
  2418. NTRAID-455638-2/2/2000-yunlin We silently ignore it if SDs are specified.
  2419. Arguments:
  2420. RxContext - the RDBSS context
  2421. Return Value:
  2422. NTSTATUS - The return status for the operation
  2423. --*/
  2424. {
  2425. NTSTATUS Status;
  2426. RxCaptureFcb;
  2427. USHORT Setup = TRANS2_OPEN2;
  2428. BOOLEAN MustRegainExclusiveResource = FALSE;
  2429. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  2430. SMB_TRANSACTION_SEND_PARAMETERS SendParameters;
  2431. SMB_TRANSACTION_RECEIVE_PARAMETERS ReceiveParameters;
  2432. SMB_TRANSACTION_OPTIONS TransactionOptions;
  2433. PREQ_OPEN2 pCreateRequest = NULL;
  2434. RESP_OPEN2 CreateResponse;
  2435. PBYTE SendParamsBuffer,ReceiveParamsBuffer;
  2436. ULONG SendParamsBufferLength,ReceiveParamsBufferLength;
  2437. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  2438. MRXSMB_CREATE_PARAMETERS SmbCp;
  2439. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  2440. USHORT smbDisposition;
  2441. USHORT smbSharingMode;
  2442. USHORT smbAttributes;
  2443. ULONG smbFileSize;
  2444. USHORT smbOpenMode;
  2445. USHORT OpenFlags = SMB_OPEN_QUERY_INFORMATION;
  2446. USHORT SearchAttributes = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN;
  2447. ULONG SecondsSince1970;
  2448. BOOLEAN IsUnicode;
  2449. ULONG OS2_EaLength = 0;
  2450. PFEALIST ServerEaList = NULL;
  2451. ULONG EaLength = RxContext->Create.EaLength;
  2452. PFILE_FULL_EA_INFORMATION EaBuffer = RxContext->Create.EaBuffer;
  2453. ULONG FileNameLength,AllocationLength;
  2454. PAGED_CODE();
  2455. RxDbgTrace(0, Dbg, ("MRxSmbT2Open---\n"));
  2456. DbgPrint("MRxSmbT2Open---%08lx %08lx\n",EaBuffer,EaLength);
  2457. MRxSmbAdjustCreateParameters(RxContext,&SmbCp);
  2458. FileNameLength = RemainingName->Length;
  2459. AllocationLength = WordAlign(FIELD_OFFSET(REQ_OPEN2,Buffer[0])) +
  2460. FileNameLength+sizeof(WCHAR);
  2461. pCreateRequest = (PREQ_OPEN2)
  2462. RxAllocatePoolWithTag(
  2463. PagedPool,
  2464. AllocationLength,
  2465. 'bmsX' );
  2466. if (pCreateRequest==NULL) {
  2467. RxDbgTrace(0, Dbg, (" --> Couldn't get the pCreateRequest!\n"));
  2468. Status = STATUS_INSUFFICIENT_RESOURCES;
  2469. goto FINALLY;
  2470. }
  2471. smbDisposition = MRxSmbMapDisposition(cp->Disposition);
  2472. smbSharingMode = MRxSmbMapShareAccess(((USHORT)cp->ShareAccess));
  2473. smbAttributes = MRxSmbMapFileAttributes(cp->FileAttributes);
  2474. smbFileSize = cp->AllocationSize.LowPart;
  2475. smbOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
  2476. smbSharingMode |= smbOpenMode;
  2477. if (cp->CreateOptions & FILE_WRITE_THROUGH) {
  2478. smbSharingMode |= SMB_DA_WRITE_THROUGH;
  2479. }
  2480. if (capFcb->pNetRoot->Type == NET_ROOT_DISK) {
  2481. OpenFlags |= (SMB_OPEN_OPLOCK | SMB_OPEN_OPBATCH);
  2482. }
  2483. {
  2484. BOOLEAN GoodTime;
  2485. PSMBCEDB_SERVER_ENTRY pServerEntry;
  2486. LARGE_INTEGER CurrentTime;
  2487. pServerEntry = SmbCeReferenceAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  2488. ASSERT(pServerEntry != NULL);
  2489. IsUnicode = BooleanFlagOn(pServerEntry->Server.DialectFlags,DF_UNICODE);
  2490. KeQuerySystemTime(&CurrentTime);
  2491. GoodTime = MRxSmbTimeToSecondsSince1970(
  2492. &CurrentTime,
  2493. &pServerEntry->Server,
  2494. &SecondsSince1970
  2495. );
  2496. SmbCeDereferenceServerEntry(pServerEntry);
  2497. if (!GoodTime) {
  2498. SecondsSince1970 = 0;
  2499. }
  2500. }
  2501. pCreateRequest->Flags = OpenFlags; // Creation flags
  2502. pCreateRequest->DesiredAccess = smbSharingMode;
  2503. pCreateRequest->SearchAttributes = SearchAttributes;
  2504. pCreateRequest->FileAttributes = smbAttributes;
  2505. pCreateRequest->CreationTimeInSeconds = SecondsSince1970;
  2506. pCreateRequest->OpenFunction = smbDisposition;
  2507. pCreateRequest->AllocationSize = smbFileSize;
  2508. RtlZeroMemory(
  2509. &pCreateRequest->Reserved[0],
  2510. sizeof(pCreateRequest->Reserved));
  2511. {
  2512. NTSTATUS StringStatus;
  2513. PBYTE NameBuffer = &pCreateRequest->Buffer[0];
  2514. ULONG OriginalLengthRemaining = FileNameLength+sizeof(WCHAR);
  2515. ULONG LengthRemaining = OriginalLengthRemaining;
  2516. if (IsUnicode) {
  2517. StringStatus = SmbPutUnicodeString(&NameBuffer,RemainingName,&LengthRemaining);
  2518. } else {
  2519. StringStatus = SmbPutUnicodeStringAsOemString(&NameBuffer,RemainingName,&LengthRemaining);
  2520. DbgPrint("This is the name <%s>\n",&pCreateRequest->Buffer[0]);
  2521. }
  2522. ASSERT(StringStatus==STATUS_SUCCESS);
  2523. SendParamsBufferLength = FIELD_OFFSET(REQ_OPEN2,Buffer[0])
  2524. +OriginalLengthRemaining-LengthRemaining;
  2525. }
  2526. SendParamsBuffer = (PBYTE)pCreateRequest;
  2527. //SendParamsBufferLength = qweee;
  2528. ReceiveParamsBuffer = (PBYTE)&CreateResponse;
  2529. ReceiveParamsBufferLength = sizeof(CreateResponse);
  2530. if (EaLength!=0) {
  2531. //
  2532. // Convert Nt format FEALIST to OS/2 format
  2533. //
  2534. DbgPrint("MRxSmbT2Open again---%08lx %08lx\n",EaBuffer,EaLength);
  2535. OS2_EaLength = MRxSmbNtFullEaSizeToOs2 ( EaBuffer );
  2536. if ( OS2_EaLength > 0x0000ffff ) {
  2537. Status = STATUS_EA_TOO_LARGE;
  2538. goto FINALLY;
  2539. }
  2540. ServerEaList = RxAllocatePoolWithTag (PagedPool, OS2_EaLength, 'Ebms');
  2541. if ( ServerEaList == NULL ) {
  2542. Status = STATUS_INSUFFICIENT_RESOURCES;
  2543. goto FINALLY;
  2544. }
  2545. MRxSmbNtFullListToOs2 ( EaBuffer, ServerEaList );
  2546. } else {
  2547. OS2_EaLength = 0;
  2548. ServerEaList = NULL;
  2549. }
  2550. RxDbgTrace(0, Dbg, ("MRxSmbT2Open---os2ea %d buf %x\n", OS2_EaLength,ServerEaList));
  2551. DbgPrint("MRxSmbT2Open OS2 eastuff---%08lx %08lx\n",ServerEaList,OS2_EaLength);
  2552. TransactionOptions = RxDefaultTransactionOptions;
  2553. TransactionOptions.Flags |= SMB_XACT_FLAGS_FID_NOT_NEEDED;
  2554. if (BooleanFlagOn(capFcb->pNetRoot->Flags,NETROOT_FLAG_DFS_AWARE_NETROOT) &&
  2555. (RxContext->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT))) {
  2556. TransactionOptions.Flags |= SMB_XACT_FLAGS_DFS_AWARE;
  2557. }
  2558. ASSERT (MrxSmbCreateTransactPacketSize>=100); //don't try something bad!
  2559. TransactionOptions.MaximumTransmitSmbBufferSize = MrxSmbCreateTransactPacketSize;
  2560. RxReleaseFcbResourceInMRx( capFcb );
  2561. MustRegainExclusiveResource = TRUE;
  2562. Status = SmbCeTransact(
  2563. RxContext,
  2564. &TransactionOptions,
  2565. &Setup,
  2566. sizeof(Setup),
  2567. NULL,
  2568. 0,
  2569. SendParamsBuffer,
  2570. SendParamsBufferLength,
  2571. ReceiveParamsBuffer,
  2572. ReceiveParamsBufferLength,
  2573. ServerEaList,
  2574. OS2_EaLength,
  2575. NULL,
  2576. 0,
  2577. &ResumptionContext);
  2578. if (NT_SUCCESS(Status)) {
  2579. MRxSmbFinishT2OpenFile (
  2580. RxContext,
  2581. &CreateResponse,
  2582. &MustRegainExclusiveResource,
  2583. SmbFcbHoldingState,
  2584. ResumptionContext.ServerVersion);
  2585. if (cp->Disposition == FILE_OPEN) {
  2586. MRxSmbAdjustReturnedCreateAction(RxContext);
  2587. }
  2588. }
  2589. FINALLY:
  2590. ASSERT (Status != (STATUS_PENDING));
  2591. if (pCreateRequest != NULL) {
  2592. RxFreePool(pCreateRequest);
  2593. }
  2594. if (ServerEaList != NULL) {
  2595. RxFreePool(ServerEaList);
  2596. }
  2597. if (*SmbFcbHoldingState != SmbFcb_NotHeld) {
  2598. MRxSmbCscReleaseSmbFcb(RxContext,SmbFcbHoldingState);
  2599. }
  2600. if (MustRegainExclusiveResource) {
  2601. //this is required because of oplock breaks
  2602. RxAcquireExclusiveFcbResourceInMRx(capFcb );
  2603. }
  2604. RxDbgTraceUnIndent(-1,Dbg);
  2605. return Status;
  2606. }
  2607. NTSTATUS
  2608. MRxSmbFinishLongNameCreateFile (
  2609. IN OUT PRX_CONTEXT RxContext,
  2610. IN PRESP_CREATE_WITH_SD_OR_EA Response,
  2611. IN PBOOLEAN MustRegainExclusiveResource,
  2612. IN OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState,
  2613. IN ULONG ServerVersion
  2614. )
  2615. /*++
  2616. Routine Description:
  2617. This routine actually gets the stuff out of the NTTransact/NTCreateWithEAsOrSDs response.
  2618. CODE.IMPROVEMENT This routine is almost identical to the finish routine for "short names"..so
  2619. much so that some sort of merging should occur. an important point is that
  2620. the whole idea of >4k names is a very uncommon path so merging should not be
  2621. done so as to slow up the other path. On the other hand, it's not good to have
  2622. to change things in two places. CODE.IMPROVEMENT.ASHAMED this is terrible!
  2623. Arguments:
  2624. RxContext - the context of the operation being performed
  2625. Response - the response
  2626. Return Value:
  2627. RXSTATUS - The return status for the operation
  2628. --*/
  2629. {
  2630. NTSTATUS Status = STATUS_SUCCESS;
  2631. RxCaptureFcb;
  2632. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2633. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2634. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)SrvOpen->pVNetRoot->Context;
  2635. RX_FILE_TYPE StorageType;
  2636. SMB_FILE_ID Fid;
  2637. ULONG CreateAction;
  2638. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  2639. FCB_INIT_PACKET InitPacket;
  2640. PAGED_CODE();
  2641. RxDbgTrace(+1, Dbg, ("MRxSmbFinishLongNameCreateFile\n", 0 ));
  2642. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  2643. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  2644. if (RxContext->Create.NtCreateParameters.CreateOptions & FILE_DELETE_ON_CLOSE) {
  2645. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  2646. SetFlag((smbFcb)->MFlags,SMB_FCB_FLAG_SENT_DISPOSITION_INFO);
  2647. }
  2648. StorageType = RxInferFileType(RxContext);
  2649. if (StorageType == 0) {
  2650. StorageType = Response->Directory
  2651. ?FileTypeDirectory
  2652. :FileTypeFile;
  2653. RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
  2654. }
  2655. if ((capFcb->OpenCount != 0) &&
  2656. (StorageType != 0) &&
  2657. (NodeType(capFcb) != RDBSS_STORAGE_NTC(StorageType))) {
  2658. return STATUS_OBJECT_TYPE_MISMATCH;
  2659. }
  2660. Fid = SmbGetUshort(&Response->Fid);
  2661. CreateAction = SmbGetUlong(&Response->CreateAction);
  2662. pFileInfo->Basic.FileAttributes = Response->FileAttributes;
  2663. pFileInfo->Basic.CreationTime = Response->CreationTime;
  2664. pFileInfo->Basic.LastAccessTime = Response->LastAccessTime;
  2665. pFileInfo->Basic.LastWriteTime = Response->LastWriteTime;
  2666. pFileInfo->Basic.ChangeTime = Response->ChangeTime;
  2667. pFileInfo->Standard.NumberOfLinks = 1;
  2668. pFileInfo->Standard.AllocationSize = Response->AllocationSize;
  2669. pFileInfo->Standard.EndOfFile = Response->EndOfFile;
  2670. pFileInfo->Standard.Directory = Response->Directory;
  2671. if (((pFileInfo->Standard.AllocationSize.HighPart == pFileInfo->Standard.EndOfFile.HighPart) &&
  2672. (pFileInfo->Standard.AllocationSize.LowPart < pFileInfo->Standard.EndOfFile.LowPart)) ||
  2673. (pFileInfo->Standard.AllocationSize.HighPart < pFileInfo->Standard.EndOfFile.HighPart)) {
  2674. pFileInfo->Standard.AllocationSize = pFileInfo->Standard.EndOfFile;
  2675. }
  2676. MRxSmbCopyAndTranslatePipeState(
  2677. RxContext,
  2678. SmbGetUshort(&Response->DeviceState) );
  2679. //MRxSmbSetSrvOpenFlags(RxContext,StorageType,SrvOpen,smbSrvOpen);
  2680. if (Response->ExtendedResponse) {
  2681. PRESP_EXTENDED_CREATE_WITH_SD_OR_EA ExtendedResponse;
  2682. ULONG AccessRights;
  2683. ExtendedResponse = (PRESP_EXTENDED_CREATE_WITH_SD_OR_EA)Response;
  2684. AccessRights = SmbGetUlong(&ExtendedResponse->MaximalAccessRights);
  2685. smbSrvOpen->MaximalAccessRights = (USHORT)AccessRights;
  2686. AccessRights = SmbGetUlong(&ExtendedResponse->GuestMaximalAccessRights);
  2687. smbSrvOpen->GuestMaximalAccessRights = (USHORT)AccessRights;
  2688. } else {
  2689. // If the NT_CREATE_ANDX was to a downlevel server the access rights
  2690. // information is not available. Currently we default to maximum
  2691. // access for the current user and no access to other users in the
  2692. // disconnected mode for such files
  2693. smbSrvOpen->MaximalAccessRights = (USHORT)0x1ff;
  2694. smbSrvOpen->GuestMaximalAccessRights = (USHORT)0;
  2695. }
  2696. MRxSmbCreateFileSuccessTail(
  2697. RxContext,
  2698. MustRegainExclusiveResource,
  2699. SmbFcbHoldingState,
  2700. StorageType,
  2701. Fid,
  2702. ServerVersion,
  2703. Response->OplockLevel,
  2704. CreateAction,
  2705. pFileInfo);
  2706. RxDbgTrace(-1, Dbg, ("MRxSmbFinishLongNameCreateFile returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  2707. return Status;
  2708. }
  2709. #ifndef WIN9X
  2710. //#define MULTI_EA_MDL
  2711. #if 0
  2712. //#define FORCE_T2_OPEN
  2713. #ifdef FORCE_T2_OPEN
  2714. BOOLEAN ForceT2Open = TRUE;
  2715. #else
  2716. #define ForceT2Open FALSE
  2717. #endif
  2718. #endif //if 0
  2719. //force_t2_open doesn't work on an NT server......sigh........
  2720. #define ForceT2Open FALSE
  2721. NTSTATUS
  2722. MRxSmbCreateWithEasSidsOrLongName (
  2723. IN OUT PRX_CONTEXT RxContext,
  2724. IN OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState
  2725. )
  2726. /*++
  2727. Routine Description:
  2728. This routine opens a file across the network that has
  2729. 1) EAs,
  2730. 2) SIDs, or
  2731. 3) a name so long that it wont fit in an ordinary packet
  2732. Arguments:
  2733. RxContext - the RDBSS context
  2734. Return Value:
  2735. RXSTATUS - The return status for the operation
  2736. --*/
  2737. {
  2738. NTSTATUS Status;
  2739. RxCaptureFcb;
  2740. BOOLEAN MustRegainExclusiveResource = FALSE;
  2741. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  2742. SMB_TRANSACTION_SEND_PARAMETERS SendParameters;
  2743. SMB_TRANSACTION_RECEIVE_PARAMETERS ReceiveParameters;
  2744. SMB_TRANSACTION_OPTIONS TransactionOptions;
  2745. PREQ_CREATE_WITH_SD_OR_EA pCreateRequest = NULL;
  2746. PBYTE SendParamsBuffer,ReceiveParamsBuffer,SendDataBuffer;
  2747. ULONG SendParamsBufferLength,ReceiveParamsBufferLength,SendDataBufferLength;
  2748. RESP_EXTENDED_CREATE_WITH_SD_OR_EA CreateResponse;
  2749. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  2750. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  2751. MRXSMB_CREATE_PARAMETERS SmbCp;
  2752. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  2753. ULONG EaLength, SdLength, PadLength = 0, TotalLength = 0;
  2754. PBYTE CombinedBuffer = NULL;
  2755. #ifdef MULTI_EA_MDL
  2756. PRX_BUFFER EaMdl2 = NULL;
  2757. PRX_BUFFER EaMdl3 = NULL;
  2758. #endif
  2759. PMDL EaMdl = NULL;
  2760. PMDL SdMdl = NULL; BOOLEAN SdMdlLocked = FALSE;
  2761. PMDL PadMdl = NULL;
  2762. PMDL DataMdl = NULL;
  2763. ULONG FileNameLength,AllocationLength;
  2764. BOOLEAN IsUnicode = TRUE;
  2765. PAGED_CODE();
  2766. RxDbgTrace(0, Dbg, ("!!MRxSmbCreateWithEasSidsOrLongName---\n"));
  2767. {
  2768. PSMBCEDB_SERVER_ENTRY pServerEntry;
  2769. BOOLEAN DoesNtSmbs;
  2770. pServerEntry = SmbCeReferenceAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  2771. ASSERT(pServerEntry != NULL);
  2772. DoesNtSmbs = BooleanFlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS);
  2773. IsUnicode = BooleanFlagOn(pServerEntry->Server.DialectFlags,DF_UNICODE);
  2774. SmbCeDereferenceServerEntry(pServerEntry);
  2775. if (!DoesNtSmbs || ForceT2Open) {
  2776. NTSTATUS Status = MRxSmbT2OpenFile(RxContext,
  2777. SmbFcbHoldingState);
  2778. if (ForceT2Open && (Status!=STATUS_SUCCESS)) {
  2779. DbgPrint("BadStatus = %08lx\n",Status);
  2780. }
  2781. return(Status);
  2782. }
  2783. }
  2784. MRxSmbAdjustCreateParameters(RxContext,&SmbCp);
  2785. #if DBG
  2786. if (MRxSmbNeedSCTesting) MRxSmbTestStudCode();
  2787. #endif
  2788. RxDbgTrace(0, Dbg, ("MRxSmbCreateWithEasSidsOrLongName---\n"));
  2789. if(IsUnicode) {
  2790. FileNameLength = RemainingName->Length;
  2791. } else {
  2792. FileNameLength = RtlUnicodeStringToAnsiSize(RemainingName);
  2793. }
  2794. //CODE.IMPROVEMENT when transacts can take MDL chains instead of just buffers, we can
  2795. // use that here!
  2796. AllocationLength = WordAlign(FIELD_OFFSET(REQ_CREATE_WITH_SD_OR_EA,Buffer[0]))
  2797. +FileNameLength;
  2798. pCreateRequest = (PREQ_CREATE_WITH_SD_OR_EA)RxAllocatePoolWithTag( PagedPool,
  2799. AllocationLength,'bmsX' );
  2800. if (pCreateRequest==NULL) {
  2801. RxDbgTrace(0, Dbg, (" --> Couldn't get the pCreateRequest!\n"));
  2802. Status = STATUS_INSUFFICIENT_RESOURCES;
  2803. goto FINALLY;
  2804. }
  2805. if (IsUnicode) {
  2806. RtlCopyMemory((PBYTE)WordAlignPtr(&pCreateRequest->Buffer[0]),RemainingName->Buffer,FileNameLength);
  2807. } else {
  2808. PBYTE pName = &pCreateRequest->Buffer[0];
  2809. ULONG BufferLength = FileNameLength;
  2810. SmbPutUnicodeStringAsOemString(&pName, RemainingName, &BufferLength);
  2811. }
  2812. EaLength = RxContext->Create.EaLength;
  2813. SdLength = RxContext->Create.SdLength;
  2814. #if defined(REMOTE_BOOT)
  2815. //
  2816. // If this is a remote boot client and it did a NULL session logon, then
  2817. // we don't want to send ACLs to the server because a) the unchanged ACL
  2818. // has no meaning and b) a NULL session requires that files have world
  2819. // access.
  2820. //
  2821. if (MRxSmbBootedRemotely &&
  2822. !MRxSmbRemoteBootDoMachineLogon) {
  2823. PSMBCE_SESSION pSession;
  2824. pSession = &SmbCeGetAssociatedVNetRootContext(SrvOpen->pVNetRoot)->pSessionEntry->Session;
  2825. if (FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  2826. SdLength = 0;
  2827. }
  2828. }
  2829. #endif // defined(REMOTE_BOOT)
  2830. pCreateRequest->Flags = NT_CREATE_REQUEST_EXTENDED_RESPONSE; //nooplock // Creation flags ISSUE
  2831. pCreateRequest->RootDirectoryFid = 0; //norelopen // Optional directory for relative open
  2832. pCreateRequest->DesiredAccess = cp->DesiredAccess; // Desired access (NT format)
  2833. pCreateRequest->AllocationSize = cp->AllocationSize; // The initial allocation size in bytes
  2834. pCreateRequest->FileAttributes = cp->FileAttributes; // The file attributes
  2835. pCreateRequest->ShareAccess = cp->ShareAccess; // The share access
  2836. pCreateRequest->CreateDisposition = cp->Disposition; // Action to take if file exists or not
  2837. pCreateRequest->CreateOptions = cp->CreateOptions; // Options for creating a new file
  2838. pCreateRequest->SecurityDescriptorLength = SdLength; // Length of SD in bytes
  2839. pCreateRequest->EaLength = EaLength; // Length of EA in bytes
  2840. pCreateRequest->NameLength = IsUnicode ? FileNameLength : FileNameLength - 1; // Length of name in characters
  2841. pCreateRequest->ImpersonationLevel = cp->ImpersonationLevel; // Security QOS information
  2842. pCreateRequest->SecurityFlags = SmbCp.SecurityFlags; // Security QOS information
  2843. // UCHAR Buffer[1];
  2844. // //UCHAR Name[]; // The name of the file (not NUL terminated)
  2845. SendParamsBuffer = (PBYTE)pCreateRequest;
  2846. SendParamsBufferLength = AllocationLength;
  2847. ReceiveParamsBuffer = (PBYTE)&CreateResponse;
  2848. ReceiveParamsBufferLength = sizeof(CreateResponse);
  2849. if ((EaLength==0)||(SdLength==0)) {
  2850. PadLength = 0;
  2851. if (EaLength) {
  2852. // the EaBuffer is in nonpaged pool...so we dont lock or unlock
  2853. PBYTE EaBuffer = RxContext->Create.EaBuffer;
  2854. #ifdef MULTI_EA_MDL
  2855. ULONG EaLength0,EaLength2,EaLength3;
  2856. PBYTE EaBuffer2,EaBuffer3;
  2857. ASSERT(EaLength>11);
  2858. RxDbgTrace(0, Dbg, ("MRxSmbCreateWithEasSidsOrLongName--MULTIEAMDL\n"));
  2859. EaLength0 = (EaLength - 4)>>1;
  2860. EaBuffer2 = EaBuffer + EaLength0;
  2861. EaLength2 = 4;
  2862. EaBuffer3 = EaBuffer2 + EaLength2;
  2863. EaLength3 = EaLength - (EaBuffer3 - EaBuffer);
  2864. EaMdl = RxAllocateMdl(EaBuffer,EaLength0);
  2865. EaMdl2 = RxAllocateMdl(EaBuffer2,EaLength2);
  2866. EaMdl3 = RxAllocateMdl(EaBuffer3,EaLength3);
  2867. if ( (EaMdl==NULL) || (EaMdl2==NULL) || (EaMdl3==NULL) ) {
  2868. Status = STATUS_INSUFFICIENT_RESOURCES;
  2869. goto FINALLY;
  2870. }
  2871. MmBuildMdlForNonPagedPool(EaMdl);
  2872. MmBuildMdlForNonPagedPool(EaMdl2);
  2873. MmBuildMdlForNonPagedPool(EaMdl3);
  2874. EaMdl3->Next = NULL;
  2875. EaMdl2->Next = EaMdl3;
  2876. EaMdl->Next = EaMdl2;
  2877. #else
  2878. EaMdl = RxAllocateMdl(EaBuffer,EaLength);
  2879. if (EaMdl == NULL) {
  2880. Status = STATUS_INSUFFICIENT_RESOURCES;
  2881. goto FINALLY;
  2882. }
  2883. MmBuildMdlForNonPagedPool(EaMdl);
  2884. EaMdl->Next = NULL;
  2885. #endif
  2886. DataMdl = EaMdl;
  2887. }
  2888. if (SdLength) {
  2889. SdMdl = RxAllocateMdl(cp->SecurityContext->AccessState->SecurityDescriptor,SdLength);
  2890. if (SdMdl == NULL) {
  2891. Status = STATUS_INSUFFICIENT_RESOURCES;
  2892. } else {
  2893. RxProbeAndLockPages(SdMdl,KernelMode,IoModifyAccess,Status);
  2894. }
  2895. if (!NT_SUCCESS(Status)) goto FINALLY;
  2896. SdMdlLocked = TRUE;
  2897. PadLength = LongAlign(SdLength) - SdLength;
  2898. if (PadLength && EaLength) {
  2899. PadMdl = RxAllocateMdl(0,(sizeof(DWORD) + PAGE_SIZE - 1));
  2900. if (PadMdl == NULL) {
  2901. Status = STATUS_INSUFFICIENT_RESOURCES;
  2902. goto FINALLY;
  2903. }
  2904. RxBuildPaddingPartialMdl(PadMdl,PadLength);
  2905. PadMdl->Next = DataMdl;
  2906. DataMdl = PadMdl;
  2907. }
  2908. SdMdl->Next = DataMdl;
  2909. DataMdl = SdMdl;
  2910. }
  2911. } else {
  2912. //CODE.IMPROVEMENT this path disappears when the MDLstudcode is enabled
  2913. ULONG EaOffset = LongAlign(SdLength);
  2914. ULONG CombinedBufferLength = EaOffset + EaLength;
  2915. CombinedBuffer = RxAllocatePoolWithTag(PagedPool,CombinedBufferLength,'bms');
  2916. if (CombinedBuffer==NULL) {
  2917. Status = STATUS_INSUFFICIENT_RESOURCES;
  2918. goto FINALLY;
  2919. }
  2920. SdMdl = RxAllocateMdl(CombinedBuffer,CombinedBufferLength);
  2921. if (SdMdl == NULL) {
  2922. Status = STATUS_INSUFFICIENT_RESOURCES;
  2923. } else {
  2924. RxProbeAndLockPages(SdMdl,KernelMode,IoModifyAccess,Status);
  2925. }
  2926. if (!NT_SUCCESS(Status)) goto FINALLY;
  2927. SdMdlLocked = TRUE;
  2928. RtlCopyMemory(CombinedBuffer,cp->SecurityContext->AccessState->SecurityDescriptor,SdLength);
  2929. RtlZeroMemory(CombinedBuffer+SdLength,EaOffset-SdLength);
  2930. RtlCopyMemory(CombinedBuffer+EaOffset,RxContext->Create.EaBuffer,EaLength);
  2931. DataMdl = SdMdl;
  2932. }
  2933. RxDbgTrace(0, Dbg, ("MRxSmbCreateWithEasSidsOrLongName---s,p,ea %d,%d,%d buf %x\n",
  2934. SdLength,PadLength,EaLength,RxContext->Create.EaBuffer));
  2935. TransactionOptions = RxDefaultTransactionOptions;
  2936. TransactionOptions.NtTransactFunction = NT_TRANSACT_CREATE;
  2937. TransactionOptions.Flags |= SMB_XACT_FLAGS_FID_NOT_NEEDED;
  2938. //dfs is only for nt servers........
  2939. //if (BooleanFlagOn(capFcb->pNetRoot->Flags,NETROOT_FLAG_DFS_AWARE_NETROOT)
  2940. // && (RxContext->Create.NtCreateParameters.DfsContext == (PVOID)DFS_OPEN_CONTEXT)) {
  2941. // TransactionOptions.Flags |= SMB_XACT_FLAGS_DFS_AWARE;
  2942. //}
  2943. ASSERT (MrxSmbCreateTransactPacketSize>=100); //don't try something bad!
  2944. TransactionOptions.MaximumTransmitSmbBufferSize = MrxSmbCreateTransactPacketSize;
  2945. if (DataMdl!=NULL) {
  2946. SendDataBuffer = MmGetSystemAddressForMdlSafe(DataMdl,LowPagePriority);
  2947. if (SendDataBuffer == NULL) {
  2948. Status = STATUS_INSUFFICIENT_RESOURCES;
  2949. goto FINALLY;
  2950. }
  2951. SendDataBufferLength = EaLength+SdLength+PadLength;
  2952. } else {
  2953. SendDataBuffer = NULL;
  2954. SendDataBufferLength = 0;
  2955. }
  2956. RxReleaseFcbResourceInMRx(capFcb );
  2957. MustRegainExclusiveResource = TRUE;
  2958. Status = SmbCeTransact(
  2959. RxContext,
  2960. &TransactionOptions,
  2961. NULL,
  2962. 0,
  2963. NULL,
  2964. 0,
  2965. SendParamsBuffer,
  2966. SendParamsBufferLength,
  2967. ReceiveParamsBuffer,
  2968. ReceiveParamsBufferLength,
  2969. SendDataBuffer,
  2970. SendDataBufferLength,
  2971. NULL,
  2972. 0,
  2973. &ResumptionContext);
  2974. if (NT_SUCCESS(Status)) {
  2975. MRxSmbFinishLongNameCreateFile (
  2976. RxContext,
  2977. (PRESP_CREATE_WITH_SD_OR_EA)&CreateResponse,
  2978. &MustRegainExclusiveResource,
  2979. SmbFcbHoldingState,
  2980. ResumptionContext.ServerVersion);
  2981. if (cp->Disposition == FILE_OPEN) {
  2982. MRxSmbAdjustReturnedCreateAction(RxContext);
  2983. }
  2984. }
  2985. FINALLY:
  2986. ASSERT (Status != (STATUS_PENDING));
  2987. if (SdMdlLocked) MmUnlockPages(SdMdl);
  2988. if (EaMdl != NULL) { IoFreeMdl(EaMdl); }
  2989. #ifdef MULTI_EA_MDL
  2990. if (EaMdl2 != NULL) { IoFreeMdl(EaMdl2); }
  2991. if (EaMdl3 != NULL) { IoFreeMdl(EaMdl3); }
  2992. #endif
  2993. if (PadMdl != NULL) { IoFreeMdl(PadMdl); }
  2994. if (SdMdl != NULL) { IoFreeMdl(SdMdl); }
  2995. if (pCreateRequest != NULL) {
  2996. RxFreePool(pCreateRequest);
  2997. }
  2998. if (CombinedBuffer != NULL) {
  2999. RxFreePool(CombinedBuffer);
  3000. }
  3001. if (*SmbFcbHoldingState != SmbFcb_NotHeld) {
  3002. MRxSmbCscReleaseSmbFcb(RxContext,SmbFcbHoldingState);
  3003. }
  3004. if (MustRegainExclusiveResource) {
  3005. //this is required because of oplock breaks
  3006. RxAcquireExclusiveFcbResourceInMRx(capFcb );
  3007. }
  3008. RxDbgTraceUnIndent(-1,Dbg);
  3009. return Status;
  3010. }
  3011. #endif
  3012. NTSTATUS
  3013. MRxSmbZeroExtend(
  3014. IN PRX_CONTEXT pRxContext)
  3015. /*++
  3016. Routine Description:
  3017. This routine extends the data stream of a file system object
  3018. Arguments:
  3019. pRxContext - the RDBSS context
  3020. Return Value:
  3021. RXSTATUS - The return status for the operation
  3022. --*/
  3023. {
  3024. return STATUS_NOT_IMPLEMENTED;
  3025. }
  3026. NTSTATUS
  3027. MRxSmbTruncate(
  3028. IN PRX_CONTEXT pRxContext)
  3029. /*++
  3030. Routine Description:
  3031. This routine truncates the contents of a file system object
  3032. Arguments:
  3033. pRxContext - the RDBSS context
  3034. Return Value:
  3035. RXSTATUS - The return status for the operation
  3036. --*/
  3037. {
  3038. ASSERT(!"Found a truncate");
  3039. return STATUS_NOT_IMPLEMENTED;
  3040. }
  3041. NTSTATUS
  3042. MRxSmbCleanupFobx(
  3043. IN PRX_CONTEXT RxContext)
  3044. /*++
  3045. Routine Description:
  3046. This routine cleansup a file system object...normally a noop. unless it's a pipe in which case
  3047. we do the close at cleanup time and mark the file as being not open.
  3048. Arguments:
  3049. pRxContext - the RDBSS context
  3050. Return Value:
  3051. RXSTATUS - The return status for the operation
  3052. --*/
  3053. {
  3054. NTSTATUS Status = STATUS_SUCCESS;
  3055. PUNICODE_STRING RemainingName;
  3056. RxCaptureFcb;
  3057. RxCaptureFobx;
  3058. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  3059. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3060. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3061. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  3062. PSMBCEDB_SERVER_ENTRY pServerEntry;
  3063. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  3064. BOOLEAN SearchHandleOpen = FALSE;
  3065. PAGED_CODE();
  3066. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  3067. ASSERT ( NodeTypeIsFcb(capFcb) );
  3068. RxDbgTrace(+1, Dbg, ("MRxSmbCleanup\n", 0 ));
  3069. MRxSmbCscCleanupFobx(RxContext);
  3070. if (TypeOfOpen==RDBSS_NTC_STORAGE_TYPE_DIRECTORY) {
  3071. SearchHandleOpen = BooleanFlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN);
  3072. MRxSmbDeallocateSideBuffer(RxContext,smbFobx,"Cleanup");
  3073. if (smbFobx->Enumeration.ResumeInfo!=NULL) {
  3074. RxFreePool(smbFobx->Enumeration.ResumeInfo);
  3075. smbFobx->Enumeration.ResumeInfo = NULL;
  3076. }
  3077. }
  3078. if (FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED)) {
  3079. RxDbgTrace(-1, Dbg, ("File orphaned\n"));
  3080. return (STATUS_SUCCESS);
  3081. }
  3082. if (!SearchHandleOpen &&
  3083. capFcb->pNetRoot->Type != NET_ROOT_PIPE) {
  3084. RxDbgTrace(-1, Dbg, ("File not for closing at cleanup\n"));
  3085. return (STATUS_SUCCESS);
  3086. }
  3087. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  3088. if (smbSrvOpen->Version == pServerEntry->Server.Version) {
  3089. Status = SmbPseCreateOrdinaryExchange(
  3090. RxContext,
  3091. SrvOpen->pVNetRoot,
  3092. SMBPSE_OE_FROM_CLEANUPFOBX,
  3093. SmbPseExchangeStart_Close,
  3094. &OrdinaryExchange
  3095. );
  3096. if (Status != STATUS_SUCCESS) {
  3097. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  3098. return(Status);
  3099. }
  3100. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  3101. ASSERT (Status != (STATUS_PENDING));
  3102. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  3103. }
  3104. RxDbgTrace(-1, Dbg, ("MRxSmbCleanup exit with status=%08lx\n", Status ));
  3105. return(Status);
  3106. }
  3107. NTSTATUS
  3108. MRxSmbForcedClose(
  3109. IN PMRX_SRV_OPEN pSrvOpen)
  3110. /*++
  3111. Routine Description:
  3112. This routine closes a file system object
  3113. Arguments:
  3114. pSrvOpen - the instance to be closed
  3115. Return Value:
  3116. RXSTATUS - The return status for the operation
  3117. Notes:
  3118. --*/
  3119. {
  3120. PAGED_CODE();
  3121. return STATUS_NOT_IMPLEMENTED;
  3122. }
  3123. #undef Dbg
  3124. #define Dbg (DEBUG_TRACE_CLOSE)
  3125. NTSTATUS
  3126. MRxSmbCloseSrvOpen(
  3127. IN PRX_CONTEXT RxContext
  3128. )
  3129. /*++
  3130. Routine Description:
  3131. This routine closes a file across the network
  3132. Arguments:
  3133. RxContext - the RDBSS context
  3134. Return Value:
  3135. NTSTATUS - The return status for the operation
  3136. --*/
  3137. {
  3138. NTSTATUS Status = STATUS_SUCCESS;
  3139. PUNICODE_STRING RemainingName;
  3140. RxCaptureFcb;
  3141. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  3142. RxCaptureFobx;
  3143. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  3144. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3145. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3146. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  3147. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)(capFcb->pNetRoot->pSrvCall->Context);
  3148. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  3149. BOOLEAN NeedDelete;
  3150. BOOLEAN SearchHandleOpen = FALSE;
  3151. PAGED_CODE();
  3152. ASSERT ( NodeTypeIsFcb(capFcb) );
  3153. RxDbgTrace(+1, Dbg, ("MRxSmbClose\n", 0 ));
  3154. if (TypeOfOpen==RDBSS_NTC_STORAGE_TYPE_DIRECTORY) {
  3155. SearchHandleOpen = BooleanFlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN);
  3156. MRxSmbDeallocateSideBuffer(RxContext,smbFobx,"Close");
  3157. if (smbFobx->Enumeration.ResumeInfo!=NULL) {
  3158. RxFreePool(smbFobx->Enumeration.ResumeInfo);
  3159. smbFobx->Enumeration.ResumeInfo = NULL;
  3160. }
  3161. }
  3162. if (!smbSrvOpen->DeferredOpenInProgress &&
  3163. smbSrvOpen->DeferredOpenContext != NULL) {
  3164. RxFreePool(smbSrvOpen->DeferredOpenContext);
  3165. smbSrvOpen->DeferredOpenContext = NULL;
  3166. RxDbgTrace(0, Dbg, ("Free deferred open context for file %wZ %lX\n",GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),smbSrvOpen));
  3167. }
  3168. //Remove the open context from the list if it is a paging file
  3169. if (FlagOn( capFcb->FcbState, FCB_STATE_PAGING_FILE )) {
  3170. PLIST_ENTRY pListHead = &MRxSmbPagingFilesSrvOpenList;
  3171. PLIST_ENTRY pListEntry = pListHead->Flink;
  3172. ASSERT(FALSE);
  3173. while (pListEntry != pListHead) {
  3174. PPAGING_FILE_CONTEXT PagingFileContext;
  3175. PagingFileContext = (PPAGING_FILE_CONTEXT)CONTAINING_RECORD(pListEntry,PAGING_FILE_CONTEXT,ContextList);
  3176. if (PagingFileContext->pSrvOpen == SrvOpen) {
  3177. RemoveEntryList(pListEntry);
  3178. break;
  3179. }
  3180. }
  3181. }
  3182. IF_NOT_MRXSMB_CSC_ENABLED{
  3183. ASSERT(!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_OPEN_SURROGATED));
  3184. ASSERT(smbFcb->SurrogateSrvOpen==NULL);
  3185. ASSERT(smbFcb->CopyChunkThruOpen==NULL);
  3186. } else {
  3187. if (MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)) {
  3188. // If the net root entry has been transitioned into a disconnected
  3189. // mode of operation, trivially succeed close of deferred open
  3190. // operations and perform the appropriate book keeping for non
  3191. // deferred opens
  3192. if (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  3193. MRxSmbCscUpdateShadowFromClose(NULL,RxContext);
  3194. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  3195. RxDbgTrace(-1, Dbg, ("Disconnected close\n"));
  3196. }
  3197. if ((capFcb->OpenCount == 0) &&
  3198. FlagOn(capFcb->FcbState,FCB_STATE_DELETE_ON_CLOSE)) {
  3199. MRxSmbCscDeleteAfterCloseEpilogue(RxContext,&Status);
  3200. }
  3201. goto FINALLY;
  3202. }
  3203. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_OPEN_SURROGATED)){
  3204. if (smbSrvOpen->hfShadow != 0){
  3205. MRxSmbCscCloseShadowHandle(RxContext);
  3206. }
  3207. RxDbgTrace(-1, Dbg, ("Surrogated Open\n"));
  3208. goto FINALLY;
  3209. }
  3210. if (smbFcb->CopyChunkThruOpen == capFobx) {
  3211. smbFcb->CopyChunkThruOpen = NULL;
  3212. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  3213. ASSERT(smbSrvOpen->hfShadow == 0);
  3214. RxDbgTrace(-1, Dbg, ("CopyChunkOpen already closed\n"));
  3215. goto FINALLY;
  3216. }
  3217. }
  3218. if (smbFcb->SurrogateSrvOpen == SrvOpen) {
  3219. smbFcb->SurrogateSrvOpen = NULL;
  3220. }
  3221. }
  3222. if ((FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED)) ||
  3223. (capFcb->pNetRoot->Type == NET_ROOT_MAILSLOT) ||
  3224. (capFcb->pNetRoot->Type == NET_ROOT_PIPE) ) {
  3225. RxDbgTrace(-1, Dbg, ("File orphan or ipc\n"));
  3226. goto FINALLY;
  3227. }
  3228. if (smbSrvOpen->hfShadow != 0){
  3229. MRxSmbCscCloseShadowHandle(RxContext);
  3230. }
  3231. if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_FILE_RENAMED) ||
  3232. FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_FILE_DELETED) ){
  3233. RxDbgTrace(-1, Dbg, ("File already closed by ren/del\n"));
  3234. goto FINALLY;
  3235. }
  3236. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  3237. if (smbSrvOpen->Fid == 0xffff) {
  3238. // File has already been closed on the server.
  3239. goto FINALLY;
  3240. }
  3241. IF_NOT_MRXSMB_CSC_ENABLED{
  3242. ASSERT(smbSrvOpen->hfShadow == 0);
  3243. }
  3244. NeedDelete = FlagOn(capFcb->FcbState,FCB_STATE_DELETE_ON_CLOSE) && (capFcb->OpenCount == 0);
  3245. if (!NeedDelete &&
  3246. !SearchHandleOpen &&
  3247. FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)){
  3248. RxDbgTrace(-1, Dbg, ("File was not really open\n"));
  3249. goto FINALLY;
  3250. }
  3251. if (smbSrvOpen->Version == pServerEntry->Server.Version) {
  3252. Status = SmbPseCreateOrdinaryExchange(
  3253. RxContext,
  3254. SrvOpen->pVNetRoot,
  3255. SMBPSE_OE_FROM_CLOSESRVCALL,
  3256. SmbPseExchangeStart_Close,
  3257. &OrdinaryExchange
  3258. );
  3259. if (Status != STATUS_SUCCESS) {
  3260. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  3261. goto FINALLY;
  3262. }
  3263. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  3264. ASSERT (Status != (STATUS_PENDING));
  3265. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  3266. }
  3267. RxDbgTrace(-1, Dbg, ("MRxSmbClose exit with status=%08lx\n", Status ));
  3268. FINALLY:
  3269. if (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN) &&
  3270. !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_OPEN_SURROGATED) &&
  3271. (pServerEntry != NULL)) {
  3272. MRxSmbDecrementSrvOpenCount(
  3273. pServerEntry,
  3274. smbSrvOpen->Version,
  3275. SrvOpen);
  3276. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  3277. }
  3278. return(Status);
  3279. }
  3280. NTSTATUS
  3281. MRxSmbBuildClose (
  3282. PSMBSTUFFER_BUFFER_STATE StufferState
  3283. )
  3284. /*++
  3285. Routine Description:
  3286. This builds a Close SMB. we don't have to worry about login id and such
  3287. since that is done by the connection engine....pretty neat huh? all we have to do
  3288. is to format up the bits.
  3289. Arguments:
  3290. StufferState - the state of the smbbuffer from the stuffer's point of view
  3291. Return Value:
  3292. RXSTATUS
  3293. SUCCESS
  3294. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  3295. Notes:
  3296. --*/
  3297. {
  3298. NTSTATUS Status;
  3299. PRX_CONTEXT RxContext = StufferState->RxContext;
  3300. RxCaptureFcb;
  3301. RxCaptureFobx;
  3302. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3303. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3304. PAGED_CODE();
  3305. RxDbgTrace(+1, Dbg, ("MRxSmbBuildClose\n", 0 ));
  3306. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  3307. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse, SMB_COM_CLOSE,
  3308. SMB_REQUEST_SIZE(CLOSE),
  3309. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  3310. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  3311. );
  3312. MRxSmbDumpStufferState (1100,"SMB w/ CLOSE before stuffing",StufferState);
  3313. MRxSmbStuffSMB (StufferState,
  3314. "0wdB!",
  3315. // 0 UCHAR WordCount; // Count of parameter words = 3
  3316. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  3317. 0xffffffff, // d _ULONG( LastWriteTimeInSeconds ); // Time of last write, low and high
  3318. SMB_WCT_CHECK(3) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
  3319. // UCHAR Buffer[1]; // empty
  3320. );
  3321. MRxSmbDumpStufferState (700,"SMB w/ close after stuffing",StufferState);
  3322. FINALLY:
  3323. RxDbgTraceUnIndent(-1,Dbg);
  3324. return(Status);
  3325. }
  3326. NTSTATUS
  3327. MRxSmbBuildClosePrintFile (
  3328. PSMBSTUFFER_BUFFER_STATE StufferState
  3329. )
  3330. /*++
  3331. Routine Description:
  3332. This builds a ClosePrintFile SMB. we don't have to worry about login id and such
  3333. since that is done by the connection engine....pretty neat huh? all we have to do
  3334. is to format up the bits.
  3335. Arguments:
  3336. StufferState - the state of the smbbuffer from the stuffer's point of view
  3337. Return Value:
  3338. RXSTATUS
  3339. SUCCESS
  3340. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  3341. Notes:
  3342. --*/
  3343. {
  3344. NTSTATUS Status;
  3345. PRX_CONTEXT RxContext = StufferState->RxContext;
  3346. RxCaptureFcb;RxCaptureFobx;
  3347. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3348. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3349. PAGED_CODE();
  3350. RxDbgTrace(+1, Dbg, ("MRxSmbBuildClosePrintFile\n", 0 ));
  3351. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  3352. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse, SMB_COM_CLOSE_PRINT_FILE,
  3353. SMB_REQUEST_SIZE(CLOSE_PRINT_FILE),
  3354. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  3355. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  3356. );
  3357. MRxSmbDumpStufferState (1100,"SMB w/ closeprintfile before stuffing",StufferState);
  3358. MRxSmbStuffSMB (StufferState,
  3359. "0wB!",
  3360. // 0 UCHAR WordCount; // Count of parameter words = 1
  3361. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  3362. SMB_WCT_CHECK(1) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
  3363. // UCHAR Buffer[1]; // empty
  3364. );
  3365. MRxSmbDumpStufferState (700,"SMB w/ closeprintfile after stuffing",StufferState);
  3366. FINALLY:
  3367. RxDbgTraceUnIndent(-1,Dbg);
  3368. return(Status);
  3369. }
  3370. NTSTATUS
  3371. MRxSmbBuildFindClose (
  3372. PSMBSTUFFER_BUFFER_STATE StufferState
  3373. )
  3374. /*++
  3375. Routine Description:
  3376. This builds a Close SMB. we don't have to worry about login id and such
  3377. since that is done by the connection engine....pretty neat huh? all we have to do
  3378. is to format up the bits.
  3379. Arguments:
  3380. StufferState - the state of the smbbuffer from the stuffer's point of view
  3381. Return Value:
  3382. RXSTATUS
  3383. SUCCESS
  3384. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  3385. Notes:
  3386. --*/
  3387. {
  3388. NTSTATUS Status;
  3389. PRX_CONTEXT RxContext = StufferState->RxContext;
  3390. RxCaptureFcb;RxCaptureFobx;
  3391. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  3392. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  3393. PAGED_CODE();
  3394. RxDbgTrace(+1, Dbg, ("MRxSmbBuildFindClose\n", 0 ));
  3395. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse, SMB_COM_FIND_CLOSE2,
  3396. SMB_REQUEST_SIZE(FIND_CLOSE2),
  3397. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  3398. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  3399. );
  3400. MRxSmbDumpStufferState (1100,"SMB w/ CLOSE before stuffing",StufferState);
  3401. MRxSmbStuffSMB (StufferState,
  3402. "0wB!",
  3403. // 0 UCHAR WordCount; // Count of parameter words = 1
  3404. // w _USHORT( Sid ); // Find handle
  3405. smbFobx->Enumeration.SearchHandle,
  3406. SMB_WCT_CHECK(1) 0 // B! _USHORT( ByteCount ); // Count of data bytes = 0
  3407. // UCHAR Buffer[1]; // empty
  3408. );
  3409. MRxSmbDumpStufferState (700,"SMB w/ FindClose2 after stuffing",StufferState);
  3410. FINALLY:
  3411. RxDbgTraceUnIndent(-1,Dbg);
  3412. return(Status);
  3413. }
  3414. NTSTATUS
  3415. MRxSmbCoreDeleteForSupercedeOrClose(
  3416. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  3417. BOOLEAN DeleteDirectory
  3418. );
  3419. NTSTATUS
  3420. SmbPseExchangeStart_Close(
  3421. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  3422. )
  3423. /*++
  3424. Routine Description:
  3425. This is the start routine for close.
  3426. Arguments:
  3427. pExchange - the exchange instance
  3428. Return Value:
  3429. RXSTATUS - The return status for the operation
  3430. --*/
  3431. {
  3432. NTSTATUS Status = STATUS_SUCCESS;
  3433. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  3434. RxCaptureFcb;
  3435. RxCaptureFobx;
  3436. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3437. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  3438. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3439. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  3440. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  3441. PSMBCEDB_SERVER_ENTRY pServerEntry= SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  3442. PAGED_CODE();
  3443. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_Close\n", 0 ));
  3444. ASSERT(OrdinaryExchange->Type == ORDINARY_EXCHANGE);
  3445. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  3446. if(TypeOfOpen==RDBSS_NTC_STORAGE_TYPE_DIRECTORY){
  3447. if (FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN)) {
  3448. // we have a search handle open.....close it
  3449. //CODE.IMPROVEMENT the close and findclose operations should be compounded...but smbs don't allow it.
  3450. // problem is......findclose is on cleanup whereas close is on close
  3451. //actually...we should have a handle-based enum and then we wouldn't have a search handle
  3452. Status = MRxSmbBuildFindClose(StufferState);
  3453. if (Status == STATUS_SUCCESS) {
  3454. PSMBCE_SERVER pServer;
  3455. // Ensure that the searchhandle is valid
  3456. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  3457. if (smbFobx->Enumeration.Version == pServer->Version) {
  3458. NTSTATUS InnerStatus;
  3459. InnerStatus = SmbPseOrdinaryExchange(
  3460. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  3461. SMBPSE_OETYPE_FINDCLOSE
  3462. );
  3463. }
  3464. }
  3465. // if this didn't work, there's nothing you can do............
  3466. ClearFlag(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN);
  3467. ClearFlag(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST);
  3468. }
  3469. }
  3470. if ((OrdinaryExchange->EntryPoint == SMBPSE_OE_FROM_CLEANUPFOBX) &&
  3471. (capFcb->pNetRoot->Type != NET_ROOT_PIPE) ) {
  3472. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Close exit after searchhandle close %08lx\n", Status ));
  3473. return Status;
  3474. }
  3475. if ( !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN) ) {
  3476. //even if it didn't work there's nothing i can do......keep going
  3477. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  3478. MRxSmbDecrementSrvOpenCount(pServerEntry,pServerEntry->Server.Version,SrvOpen);
  3479. if (NodeType(capFcb)!=RDBSS_NTC_SPOOLFILE) {
  3480. Status = MRxSmbBuildClose(StufferState);
  3481. } else {
  3482. Status = MRxSmbBuildClosePrintFile(StufferState);
  3483. }
  3484. if (Status == STATUS_SUCCESS) {
  3485. // Ensure that the Fid is validated
  3486. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID);
  3487. Status = SmbPseOrdinaryExchange(
  3488. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  3489. SMBPSE_OETYPE_CLOSE
  3490. );
  3491. // Ensure that the Fid validation is disabled
  3492. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID);
  3493. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE)) {
  3494. smbFcb->WriteOnlySrvOpenCount--;
  3495. }
  3496. }
  3497. }
  3498. IF_NOT_MRXSMB_CSC_ENABLED{
  3499. ASSERT(smbFcb->hShadow==0);
  3500. } else {
  3501. if (smbFcb->hShadow!=0) {
  3502. MRxSmbCscUpdateShadowFromClose(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  3503. }
  3504. }
  3505. if ((Status!=STATUS_SUCCESS) ||
  3506. (capFcb->OpenCount > 0) ||
  3507. !FlagOn(capFcb->FcbState,FCB_STATE_DELETE_ON_CLOSE)) {
  3508. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Close exit w %08lx\n", Status ));
  3509. return Status;
  3510. }
  3511. RxDbgTrace(0, Dbg, ("SmbPseExchangeStart_Close delete on close\n" ));
  3512. if ( !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_FILE_DELETED)) {
  3513. if (!FlagOn(smbFcb->MFlags,SMB_FCB_FLAG_SENT_DISPOSITION_INFO)) {
  3514. //no need for setinitsmb here because coredelete does a init-on-resuse.....
  3515. //it's bad to pass the name this way...........
  3516. OrdinaryExchange->pPathArgument1 = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  3517. Status = MRxSmbCoreDeleteForSupercedeOrClose(
  3518. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  3519. ((BOOLEAN)( NodeType(capFcb)==RDBSS_NTC_STORAGE_TYPE_DIRECTORY )));
  3520. if (Status == STATUS_FILE_IS_A_DIRECTORY) {
  3521. Status = MRxSmbCoreDeleteForSupercedeOrClose(
  3522. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  3523. TRUE);
  3524. }
  3525. MRxSmbCacheFileNotFound(RxContext);
  3526. } else {
  3527. // if flag FILE_DELETE_ON_CLOSE is set on NT create, the file is deleted on close
  3528. // without client send any set disposition info request
  3529. MRxSmbInvalidateFileInfoCache(RxContext);
  3530. MRxSmbInvalidateInternalFileInfoCache(RxContext);
  3531. MRxSmbCacheFileNotFound(RxContext);
  3532. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_FILE_DELETED);
  3533. }
  3534. }
  3535. IF_NOT_MRXSMB_CSC_ENABLED{
  3536. IF_DEBUG {
  3537. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  3538. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry =
  3539. SmbCeGetAssociatedNetRootEntry(NetRoot);
  3540. ASSERT(smbFcb->hShadow==0);
  3541. ASSERT(!pNetRootEntry->NetRoot.CscEnabled);
  3542. }
  3543. } else {
  3544. MRxSmbCscDeleteAfterCloseEpilogue(RxContext,&Status);
  3545. }
  3546. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Close exit w %08lx\n", Status ));
  3547. return Status;
  3548. }
  3549. NTSTATUS
  3550. MRxSmbFinishClose (
  3551. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  3552. PRESP_CLOSE Response
  3553. )
  3554. /*++
  3555. Routine Description:
  3556. This routine actually gets the stuff out of the Close response and finishes
  3557. the close.
  3558. Arguments:
  3559. OrdinaryExchange - the exchange instance
  3560. Response - the response
  3561. Return Value:
  3562. NTSTATUS - The return status for the operation
  3563. --*/
  3564. {
  3565. NTSTATUS Status = STATUS_SUCCESS;
  3566. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  3567. RxCaptureFcb;
  3568. RxCaptureFobx;
  3569. PAGED_CODE();
  3570. RxDbgTrace(+1, Dbg, ("MRxSmbFinishClose(orClosePrintFile)\n", 0 ));
  3571. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishClose:");
  3572. if (Response->WordCount != 0 ||
  3573. SmbGetUshort(&Response->ByteCount) !=0) {
  3574. Status = STATUS_INVALID_NETWORK_RESPONSE;
  3575. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  3576. } else {
  3577. if (OrdinaryExchange->OEType == SMBPSE_OETYPE_CLOSE) {
  3578. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  3579. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  3580. smbSrvOpen->Fid = 0xffff;
  3581. }
  3582. }
  3583. RxDbgTrace(-1, Dbg, ("MRxSmbFinishClose returning %08lx\n", Status ));
  3584. return Status;
  3585. }
  3586. NTSTATUS
  3587. MRxSmbAreFilesAliased(
  3588. PFCB Fcb1,
  3589. PFCB Fcb2
  3590. )
  3591. {
  3592. PMRX_SMB_FCB smbFcb1 = MRxSmbGetFcbExtension(Fcb1);
  3593. PMRX_SMB_FCB smbFcb2 = MRxSmbGetFcbExtension(Fcb2);
  3594. if ((smbFcb2->IndexNumber.QuadPart == 0) ||
  3595. (smbFcb2->IndexNumber.QuadPart == smbFcb1->IndexNumber.QuadPart)) {
  3596. return STATUS_MORE_PROCESSING_REQUIRED;
  3597. } else {
  3598. return STATUS_SUCCESS;
  3599. }
  3600. }
  3601. NTSTATUS
  3602. MRxSmbPreparseName(
  3603. IN OUT PRX_CONTEXT RxContext,
  3604. IN PUNICODE_STRING Name
  3605. )
  3606. {
  3607. #define SNAPSHOT_DESIGNATION L"@GMT-"
  3608. #define SNAPSHOT_DESIGNATION_LENGTH wcslen(SNAPSHOT_DESIGNATION)
  3609. #define SNAPSHOT_FULL_LENGTH wcslen(L"@GMT-YYYY.MM.DD-HH.MM.SS")
  3610. PWSTR pStart, pCurrent, pEnd;
  3611. ULONG iCount;
  3612. // DbgPrint( "Checking %wZ\n", Name );
  3613. // Setup the pointers
  3614. pCurrent = Name->Buffer;
  3615. pEnd = Name->Buffer + (Name->Length/sizeof(WCHAR));
  3616. // Walk the string
  3617. while( pCurrent < pEnd )
  3618. {
  3619. // Walk to the next path element
  3620. while( (pCurrent < pEnd) &&
  3621. (*pCurrent != L'\\') )
  3622. pCurrent++;
  3623. // Skip the trailing slash
  3624. pCurrent++;
  3625. // DbgPrint( "Checking at %p\n", pCurrent );
  3626. if( pCurrent + SNAPSHOT_FULL_LENGTH <= pEnd )
  3627. {
  3628. pStart = pCurrent;
  3629. // First make sure the header for the element matches
  3630. for( iCount=0; iCount<SNAPSHOT_DESIGNATION_LENGTH; iCount++,pCurrent++ )
  3631. {
  3632. if( *pCurrent != SNAPSHOT_DESIGNATION[iCount] )
  3633. {
  3634. // DbgPrint( "NoMatch1: %C != %C (%d)\n", *pCurrent, SNAPSHOT_DESIGNATION[iCount], iCount );
  3635. goto no_match;
  3636. }
  3637. }
  3638. // Now make sure the length is correct, with no path designators in the middle
  3639. for( ; iCount < SNAPSHOT_FULL_LENGTH; iCount++, pCurrent++ )
  3640. {
  3641. if( *pCurrent == L'\\' )
  3642. {
  3643. // DbgPrint( "NoMatch2: %C == \\ (%d)\n", *pCurrent, iCount );
  3644. goto no_match;
  3645. }
  3646. }
  3647. // Make sure this is either the final element or we're at the end of the string
  3648. if( pCurrent != pEnd )
  3649. {
  3650. if( *pCurrent != L'\\' )
  3651. {
  3652. // DbgPrint( "NoMatch2: %C != \\ (%d)\n", *pCurrent, SNAPSHOT_DESIGNATION[iCount], iCount );
  3653. goto no_match;
  3654. }
  3655. }
  3656. // We've found an element, mark it
  3657. RxContext->Create.Flags |= RX_CONTEXT_CREATE_FLAG_SPECIAL_PATH;
  3658. return STATUS_SUCCESS;
  3659. }
  3660. else
  3661. {
  3662. // We can't fit the token in the remaining length, so we know we don't need to continue
  3663. // DbgPrint( "NoMatch4: Length runs past end.\n" );
  3664. return STATUS_SUCCESS;
  3665. }
  3666. no_match:
  3667. continue;
  3668. }
  3669. return STATUS_SUCCESS;
  3670. }
  3671. NTSTATUS
  3672. MRxSmbGetConnectionId(
  3673. IN PRX_CONTEXT RxContext,
  3674. IN OUT PRX_CONNECTION_ID RxConnectionId
  3675. )
  3676. {
  3677. RtlZeroMemory( RxConnectionId, sizeof(RX_CONNECTION_ID) );
  3678. switch( MRxSmbConnectionIdLevel )
  3679. {
  3680. case 0:
  3681. break;
  3682. case 1:
  3683. {
  3684. PQUERY_PATH_REQUEST QpReq;
  3685. PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext = NULL;
  3686. PIO_STACK_LOCATION IrpSp = RxContext->CurrentIrpSp;
  3687. if( (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) &&
  3688. (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH) ) {
  3689. QpReq = (PQUERY_PATH_REQUEST)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  3690. SubjectSecurityContext = &QpReq->SecurityContext->AccessState->SubjectSecurityContext;
  3691. }
  3692. else if( (IrpSp->MajorFunction == IRP_MJ_CREATE) && (IrpSp->Parameters.Create.SecurityContext != NULL) ) {
  3693. SubjectSecurityContext = &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext;
  3694. }
  3695. if( SubjectSecurityContext )
  3696. {
  3697. if (SubjectSecurityContext->ClientToken != NULL) {
  3698. SeQuerySessionIdToken(SubjectSecurityContext->ClientToken, &RxConnectionId->SessionID);
  3699. } else {
  3700. SeQuerySessionIdToken(SubjectSecurityContext->PrimaryToken, &RxConnectionId->SessionID);
  3701. }
  3702. }
  3703. }
  3704. break;
  3705. case 2:
  3706. {
  3707. PQUERY_PATH_REQUEST QpReq;
  3708. PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext = NULL;
  3709. PIO_STACK_LOCATION IrpSp = RxContext->CurrentIrpSp;
  3710. if( (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) &&
  3711. (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_REDIR_QUERY_PATH) ) {
  3712. QpReq = (PQUERY_PATH_REQUEST)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  3713. SubjectSecurityContext = &QpReq->SecurityContext->AccessState->SubjectSecurityContext;
  3714. }
  3715. else if( (IrpSp->MajorFunction == IRP_MJ_CREATE) && (IrpSp->Parameters.Create.SecurityContext != NULL) ) {
  3716. SubjectSecurityContext = &IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext;
  3717. }
  3718. if( SubjectSecurityContext )
  3719. {
  3720. if (SubjectSecurityContext->ClientToken != NULL) {
  3721. SeQueryAuthenticationIdToken(SubjectSecurityContext->ClientToken, &RxConnectionId->Luid);
  3722. } else {
  3723. SeQueryAuthenticationIdToken(SubjectSecurityContext->PrimaryToken, &RxConnectionId->Luid);
  3724. }
  3725. }
  3726. }
  3727. break;
  3728. }
  3729. return STATUS_SUCCESS;
  3730. }