Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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