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.

3427 lines
110 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 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. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. #ifdef ALLOC_PRAGMA
  12. #pragma alloc_text(PAGE, MRxSmbMungeBufferingIfWriteOnlyHandles)
  13. #pragma alloc_text(PAGE, IsReconnectRequired)
  14. #pragma alloc_text(PAGE, MRxSmbIsCreateWithEasSidsOrLongName)
  15. #pragma alloc_text(PAGE, MRxSmbShouldTryToCollapseThisOpen)
  16. #pragma alloc_text(PAGE, MRxSmbCreate)
  17. #pragma alloc_text(PAGE, MRxSmbDeferredCreate)
  18. #pragma alloc_text(PAGE, MRxSmbCollapseOpen)
  19. #pragma alloc_text(PAGE, MRxSmbComputeNewBufferingState)
  20. #pragma alloc_text(PAGE, MRxSmbConstructDeferredOpenContext)
  21. #pragma alloc_text(PAGE, MRxSmbAdjustCreateParameters)
  22. #pragma alloc_text(PAGE, MRxSmbAdjustReturnedCreateAction)
  23. #pragma alloc_text(PAGE, MRxSmbBuildNtCreateAndX)
  24. #pragma alloc_text(PAGE, MRxSmbBuildOpenAndX)
  25. #pragma alloc_text(PAGE, SmbPseExchangeStart_Create)
  26. #pragma alloc_text(PAGE, MRxSmbSetSrvOpenFlags)
  27. #pragma alloc_text(PAGE, MRxSmbCreateFileSuccessTail)
  28. #pragma alloc_text(PAGE, MRxSmbFinishNTCreateAndX)
  29. #pragma alloc_text(PAGE, MRxSmbFinishOpenAndX)
  30. #pragma alloc_text(PAGE, MRxSmbFinishT2OpenFile)
  31. #pragma alloc_text(PAGE, MRxSmbT2OpenFile)
  32. #pragma alloc_text(PAGE, MRxSmbFinishLongNameCreateFile)
  33. #pragma alloc_text(PAGE, MRxSmbCreateWithEasSidsOrLongName)
  34. #pragma alloc_text(PAGE, MRxSmbZeroExtend)
  35. #pragma alloc_text(PAGE, MRxSmbTruncate)
  36. #pragma alloc_text(PAGE, MRxSmbCleanupFobx)
  37. #pragma alloc_text(PAGE, MRxSmbForcedClose)
  38. #pragma alloc_text(PAGE, MRxSmbCloseSrvOpen)
  39. #pragma alloc_text(PAGE, MRxSmbBuildClose)
  40. #pragma alloc_text(PAGE, MRxSmbBuildFindClose)
  41. #pragma alloc_text(PAGE, SmbPseExchangeStart_Close)
  42. #pragma alloc_text(PAGE, MRxSmbFinishClose)
  43. #endif
  44. //
  45. // The debug trace level
  46. //
  47. #define Dbg (DEBUG_TRACE_CREATE)
  48. // forwards
  49. NTSTATUS
  50. SmbPseExchangeStart_Create(
  51. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  52. );
  53. NTSTATUS
  54. SmbPseExchangeStart_Close(
  55. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  56. );
  57. NTSTATUS
  58. MRxSmbCreateWithEasSidsOrLongName(
  59. IN OUT PRX_CONTEXT RxContext
  60. );
  61. NTSTATUS
  62. MRxSmbDownlevelCreate(
  63. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  64. );
  65. ULONG MRxSmbInitialSrvOpenFlags = 0;
  66. BOOLEAN MRxSmbDeferredOpensEnabled = TRUE; //this is regedit-able
  67. BOOLEAN MRxSmbOplocksDisabled = FALSE; //this is regedit-able
  68. extern LIST_ENTRY MRxSmbPagingFilesSrvOpenList;
  69. #ifndef FORCE_NO_NTCREATE
  70. #define MRxSmbForceNoNtCreate FALSE
  71. #else
  72. BOOLEAN MRxSmbForceNoNtCreate = TRUE;
  73. #endif
  74. #ifdef RX_PRIVATE_BUILD
  75. //#define FORCE_SMALL_BUFFERS
  76. #endif //#ifdef RX_PRIVATE_BUILD
  77. #ifndef FORCE_SMALL_BUFFERS
  78. //use size calculated from the negotiated size
  79. ULONG MrxSmbLongestShortName = 0xffff;
  80. //use the negotiated size
  81. ULONG MrxSmbCreateTransactPacketSize = 0xffff;
  82. #else
  83. ULONG MrxSmbLongestShortName = 0;
  84. ULONG MrxSmbCreateTransactPacketSize = 100;
  85. #endif
  86. LONG MRxSmbNumberOfSrvOpens = 0;
  87. INLINE VOID
  88. MRxSmbIncrementSrvOpenCount(
  89. PSMBCEDB_SERVER_ENTRY pServerEntry,
  90. PMRX_SRV_OPEN SrvOpen)
  91. {
  92. LONG NumberOfSrvOpens;
  93. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  94. if (!FlagOn(smbSrvOpen->FileInfo.Basic.FileAttributes,
  95. FILE_ATTRIBUTE_DIRECTORY)) {
  96. ASSERT(!smbSrvOpen->NumOfSrvOpenAdded);
  97. smbSrvOpen->NumOfSrvOpenAdded = TRUE;
  98. InterlockedIncrement(&pServerEntry->Server.NumberOfSrvOpens);
  99. NumberOfSrvOpens = InterlockedIncrement(&MRxSmbNumberOfSrvOpens);
  100. if (NumberOfSrvOpens == 1) {
  101. PoRegisterSystemState(
  102. MRxSmbPoRegistrationState,
  103. (ES_SYSTEM_REQUIRED | ES_CONTINUOUS));
  104. }
  105. }
  106. }
  107. VOID
  108. MRxSmbDecrementSrvOpenCount(
  109. PSMBCEDB_SERVER_ENTRY pServerEntry,
  110. LONG SrvOpenServerVersion,
  111. PMRX_SRV_OPEN SrvOpen)
  112. {
  113. LONG NumberOfSrvOpens;
  114. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  115. if (!FlagOn(smbSrvOpen->FileInfo.Basic.FileAttributes,
  116. FILE_ATTRIBUTE_DIRECTORY)) {
  117. ASSERT(smbSrvOpen->NumOfSrvOpenAdded);
  118. smbSrvOpen->NumOfSrvOpenAdded = FALSE;
  119. if (SrvOpenServerVersion == (LONG)pServerEntry->Server.Version) {
  120. ASSERT(pServerEntry->Server.NumberOfSrvOpens > 0);
  121. InterlockedDecrement(&pServerEntry->Server.NumberOfSrvOpens);
  122. }
  123. NumberOfSrvOpens = InterlockedDecrement(&MRxSmbNumberOfSrvOpens);
  124. if (NumberOfSrvOpens == 0) {
  125. PoRegisterSystemState(
  126. MRxSmbPoRegistrationState,
  127. ES_CONTINUOUS);
  128. }
  129. }
  130. }
  131. INLINE VOID
  132. MRxSmbMungeBufferingIfWriteOnlyHandles (
  133. ULONG WriteOnlySrvOpenCount,
  134. PMRX_SRV_OPEN SrvOpen
  135. )
  136. /*++
  137. Routine Description:
  138. This routine modifies the buffering flags on a srvopen so that
  139. no cacheing will be allowed if there are any write-only handles
  140. to the file.
  141. Arguments:
  142. WriteOnlySrvOpenCount - the number of writeonly srvopens
  143. SrvOpen - the srvopen whose buffring flags are to be munged
  144. Return Value:
  145. RXSTATUS - The return status for the operation
  146. --*/
  147. {
  148. BOOLEAN IsLoopBack = FALSE;
  149. PMRX_SRV_CALL pSrvCall;
  150. PSMBCEDB_SERVER_ENTRY pServerEntry;
  151. PAGED_CODE();
  152. pSrvCall = SrvOpen->pVNetRoot->pNetRoot->pSrvCall;
  153. pServerEntry = SmbCeGetAssociatedServerEntry(pSrvCall);
  154. IsLoopBack = pServerEntry->Server.IsLoopBack;
  155. if (IsLoopBack || (WriteOnlySrvOpenCount != 0)) {
  156. SrvOpen->BufferingFlags &=
  157. ~( FCB_STATE_WRITECACHING_ENABLED |
  158. FCB_STATE_FILESIZECACHEING_ENABLED |
  159. FCB_STATE_FILETIMECACHEING_ENABLED |
  160. FCB_STATE_LOCK_BUFFERING_ENABLED |
  161. FCB_STATE_READCACHING_ENABLED |
  162. FCB_STATE_COLLAPSING_ENABLED
  163. );
  164. }
  165. }
  166. INLINE BOOLEAN
  167. IsReconnectRequired(
  168. PMRX_SRV_CALL SrvCall)
  169. /*++
  170. Routine Description:
  171. This routine determines if a reconnect is required to a given server
  172. Arguments:
  173. SrvCall - the SRV_CALL instance
  174. Return Value:
  175. TRUE if a reconnect is required
  176. --*/
  177. {
  178. BOOLEAN ReconnectRequired = FALSE;
  179. PSMBCEDB_SERVER_ENTRY pServerEntry;
  180. PAGED_CODE();
  181. pServerEntry = SmbCeGetAssociatedServerEntry(SrvCall);
  182. if (pServerEntry != NULL) {
  183. ReconnectRequired = (pServerEntry->Header.State != SMBCEDB_ACTIVE);
  184. }
  185. return ReconnectRequired;
  186. }
  187. BOOLEAN
  188. MRxSmbIsCreateWithEasSidsOrLongName(
  189. IN OUT PRX_CONTEXT RxContext,
  190. OUT PULONG DialectFlags
  191. )
  192. /*++
  193. Routine Description:
  194. This routine determines if the create operation involves EA's or security
  195. desriptors. In such cases a separate protocol is required
  196. Arguments:
  197. RxContext - the RX_CONTEXT instance
  198. DialectFlags - the dialect flags associated with the server
  199. Return Value:
  200. TRUE if a reconnect is required
  201. --*/
  202. {
  203. RxCaptureFcb;
  204. ULONG LongestShortName,LongestShortNameFromSrvBufSize;
  205. PMRX_SRV_CALL SrvCall = (PMRX_SRV_CALL)RxContext->Create.pSrvCall;
  206. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  207. PSMBCEDB_SERVER_ENTRY pServerEntry;
  208. PAGED_CODE();
  209. pServerEntry = SmbCeGetAssociatedServerEntry(SrvCall);
  210. ASSERT(pServerEntry != NULL);
  211. *DialectFlags = pServerEntry->Server.DialectFlags;
  212. // DOWN.LEVEL if the server takes OEM names or we use a different protocol
  213. // this would have to be different. maybe a switch or a precompute.
  214. LongestShortNameFromSrvBufSize =
  215. MAXIMUM_SMB_BUFFER_SIZE -
  216. QuadAlign(sizeof(NT_SMB_HEADER) +
  217. FIELD_OFFSET(REQ_NT_CREATE_ANDX,Buffer[0])
  218. );
  219. LongestShortName = min(MrxSmbLongestShortName,LongestShortNameFromSrvBufSize);
  220. return (RxContext->Create.EaLength ||
  221. RxContext->Create.SdLength ||
  222. RemainingName->Length > LongestShortName);
  223. }
  224. NTSTATUS
  225. MRxSmbShouldTryToCollapseThisOpen (
  226. IN PRX_CONTEXT RxContext
  227. )
  228. /*++
  229. Routine Description:
  230. This routine determines if the mini knows of a good reason not
  231. to try collapsing on this open.
  232. Arguments:
  233. RxContext - the RDBSS context
  234. Return Value:
  235. NTSTATUS - The return status for the operation
  236. SUCCESS --> okay to try collapse
  237. other (MORE_PROCESSING_REQUIRED) --> dont collapse
  238. --*/
  239. {
  240. NTSTATUS Status = STATUS_SUCCESS;
  241. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  242. RxCaptureFcb;
  243. PAGED_CODE();
  244. if (SrvOpen)
  245. {
  246. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  247. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)(RxContext->Create.pSrvCall->Context);
  248. if (smbSrvOpen->Version != pServerEntry->Server.Version)
  249. {
  250. return STATUS_MORE_PROCESSING_REQUIRED;
  251. }
  252. }
  253. return Status;
  254. }
  255. NTSTATUS
  256. MRxSmbCreate (
  257. IN OUT PRX_CONTEXT RxContext
  258. )
  259. /*++
  260. Routine Description:
  261. This routine opens a file across the network
  262. Arguments:
  263. RxContext - the RDBSS context
  264. Return Value:
  265. NTSTATUS - The return status for the operation
  266. --*/
  267. {
  268. NTSTATUS Status;
  269. RxCaptureFcb;
  270. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  271. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  272. PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
  273. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)SrvCall->Context;
  274. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  275. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  276. PMRX_V_NET_ROOT pVNetRoot = SrvOpen->pVNetRoot;
  277. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  278. PSMBCEDB_SESSION_ENTRY pSessionEntry ;
  279. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = NULL;
  280. BOOLEAN ReconnectRequired;
  281. BOOLEAN CreateWithEasSidsOrLongName = FALSE;
  282. ULONG DialectFlags;
  283. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  284. PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
  285. ULONG Disposition = CreateParameters->Disposition;
  286. PAGED_CODE();
  287. RxDbgTrace(+1, Dbg, ("MRxSmbCreate\n", 0 ));
  288. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  289. RxDbgTrace( 0, Dbg, (" Attempt to open %wZ\n", RemainingName ));
  290. if (FlagOn( capFcb->FcbState, FCB_STATE_PAGING_FILE )) {
  291. return STATUS_NOT_IMPLEMENTED;
  292. }
  293. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_STATUS) &&
  294. MRxSmbIsStreamFile(RemainingName,NULL)) {
  295. // The Samba server return file system type NTFS but doesn't support stream
  296. return STATUS_OBJECT_PATH_NOT_FOUND;
  297. }
  298. RxContext->Create.NtCreateParameters.CreateOptions &= 0xfffff;
  299. if( NetRoot->Type == NET_ROOT_PRINT ) {
  300. return STATUS_OBJECT_NAME_NOT_FOUND;
  301. }
  302. // we cannot have a file cached on a write only handle. so we have to behave a little
  303. // differently if this is a write-only open. remember this in the smbsrvopen
  304. if ( ((CreateParameters->DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA)) == 0) &&
  305. ((CreateParameters->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0)
  306. ) {
  307. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE);
  308. SrvOpen->Flags |= SRVOPEN_FLAG_DONTUSE_WRITE_CACHING;
  309. }
  310. //the way that SMBs work, there is no buffering effect if we open for attributes-only
  311. //so set that up immediately.
  312. if ((CreateParameters->DesiredAccess
  313. & ~(FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE))
  314. == 0 ){
  315. SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE);
  316. }
  317. if (NetRoot->Type == NET_ROOT_MAILSLOT) {
  318. return STATUS_NOT_SUPPORTED;
  319. }
  320. if (NetRoot->Type == NET_ROOT_PIPE) {
  321. return STATUS_NOT_SUPPORTED;
  322. }
  323. // Get the control struct for the file not found name cache.
  324. //
  325. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(NetRoot);
  326. // assume Reconnection to be trivially successful
  327. Status = STATUS_SUCCESS;
  328. CreateWithEasSidsOrLongName = MRxSmbIsCreateWithEasSidsOrLongName(RxContext,&DialectFlags);
  329. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
  330. CreateWithEasSidsOrLongName = FALSE;
  331. }
  332. ReconnectRequired = IsReconnectRequired((PMRX_SRV_CALL)SrvCall);
  333. //get rid of nonEA guys right now
  334. if (RxContext->Create.EaLength && !FlagOn(DialectFlags,DF_SUPPORTEA)) {
  335. RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
  336. Status = STATUS_NOT_SUPPORTED;
  337. goto FINALLY;
  338. }
  339. if (ReconnectRequired || !CreateWithEasSidsOrLongName) {
  340. Status = __SmbPseCreateOrdinaryExchange(
  341. RxContext,
  342. SrvOpen->pVNetRoot,
  343. SMBPSE_OE_FROM_CREATE,
  344. SmbPseExchangeStart_Create,
  345. &OrdinaryExchange);
  346. if (Status != STATUS_SUCCESS) {
  347. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  348. goto FINALLY;
  349. }
  350. OrdinaryExchange->Create.CreateWithEasSidsOrLongName = CreateWithEasSidsOrLongName;
  351. // For Creates, the resources need to be reacquired after sending an
  352. // SMB; so, do not hold onto the MIDS till finalization; instead give the MID back
  353. // right away
  354. OrdinaryExchange->SmbCeFlags &= ~SMBCE_EXCHANGE_REUSE_MID;
  355. OrdinaryExchange->SmbCeFlags |= (SMBCE_EXCHANGE_ATTEMPT_RECONNECTS |
  356. SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION);
  357. OrdinaryExchange->pSmbCeSynchronizationEvent = &RxContext->SyncEvent;
  358. // drop the resource before you go in!
  359. // the start routine will reacquire it on the way out.....
  360. RxReleaseFcbResourceInMRx( capFcb );
  361. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  362. ASSERT((Status != STATUS_SUCCESS) || RxIsFcbAcquiredExclusive( capFcb ));
  363. OrdinaryExchange->pSmbCeSynchronizationEvent = NULL;
  364. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  365. if (!RxIsFcbAcquiredExclusive(capFcb)) {
  366. ASSERT(!RxIsFcbAcquiredShared(capFcb));
  367. RxAcquireExclusiveFcbResourceInMRx( capFcb );
  368. }
  369. }
  370. if (CreateWithEasSidsOrLongName && (Status == STATUS_SUCCESS)) {
  371. Status = MRxSmbCreateWithEasSidsOrLongName(RxContext);
  372. }
  373. // There are certain downlevel servers(OS/2 servers) that return the error
  374. // STATUS_OPEN_FAILED. This is a context sensitive error code that needs to
  375. // be interpreted in conjunction with the disposition specified for the OPEN.
  376. if (Status == STATUS_OPEN_FAILED) {
  377. switch (Disposition) {
  378. //
  379. // If we were asked to create the file, and got OPEN_FAILED,
  380. // this implies that the file already exists.
  381. //
  382. case FILE_CREATE:
  383. Status = STATUS_OBJECT_NAME_COLLISION;
  384. break;
  385. //
  386. // If we were asked to open the file, and got OPEN_FAILED,
  387. // this implies that the file doesn't exist.
  388. //
  389. case FILE_OPEN:
  390. case FILE_SUPERSEDE:
  391. case FILE_OVERWRITE:
  392. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  393. break;
  394. //
  395. // If there is an error from either FILE_OPEN_IF or
  396. // FILE_OVERWRITE_IF, it indicates the user is trying to
  397. // open a file on a read-only share, so return the
  398. // correct error for that.
  399. //
  400. case FILE_OPEN_IF:
  401. case FILE_OVERWRITE_IF:
  402. Status = STATUS_NETWORK_ACCESS_DENIED;
  403. break;
  404. default:
  405. break;
  406. }
  407. }
  408. FINALLY:
  409. ASSERT(Status != (STATUS_PENDING));
  410. if (Status == STATUS_SUCCESS) {
  411. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_SUCCESSFUL_OPEN);
  412. }
  413. RxDbgTrace(-1, Dbg, ("MRxSmbCreate exit with status=%08lx\n", Status ));
  414. RxLog(("MRxSmbCreate exits %lx\n", Status));
  415. return(Status);
  416. }
  417. NTSTATUS
  418. MRxSmbDeferredCreate (
  419. IN OUT PRX_CONTEXT RxContext
  420. )
  421. /*++
  422. Routine Description:
  423. This routine constructs a rxcontext from saved information and then calls
  424. MRxSmbCreate.
  425. Arguments:
  426. RxContext - the RDBSS context
  427. Return Value:
  428. RXSTATUS - The return status for the operation
  429. --*/
  430. {
  431. NTSTATUS Status = STATUS_SUCCESS;
  432. RxCaptureFcb;
  433. RxCaptureFobx;
  434. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  435. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  436. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  437. PMRX_SMB_DEFERRED_OPEN_CONTEXT DeferredOpenContext = smbSrvOpen->DeferredOpenContext;
  438. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  439. PRX_CONTEXT OpenRxContext,oc;
  440. PAGED_CODE();
  441. if ((!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)
  442. || !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN))) {
  443. Status = STATUS_SUCCESS;
  444. goto FINALLY;
  445. }
  446. if (DeferredOpenContext == NULL) {
  447. if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_CLOSED)) {
  448. Status = STATUS_FILE_CLOSED;
  449. goto FINALLY;
  450. } else {
  451. DbgBreakPoint();
  452. }
  453. }
  454. ASSERT(RxIsFcbAcquiredExclusive(capFcb));
  455. SmbCeAcquireResource();
  456. if (!smbSrvOpen->DeferredOpenInProgress) {
  457. PLIST_ENTRY pListHead;
  458. PLIST_ENTRY pListEntry;
  459. smbSrvOpen->DeferredOpenInProgress = TRUE;
  460. InitializeListHead(&smbSrvOpen->DeferredOpenSyncContexts);
  461. SmbCeReleaseResource();
  462. OpenRxContext = RxAllocatePoolWithTag(NonPagedPool,
  463. sizeof(RX_CONTEXT),
  464. MRXSMB_RXCONTEXT_POOLTAG);
  465. if (OpenRxContext==NULL) {
  466. Status = STATUS_INSUFFICIENT_RESOURCES;
  467. } else {
  468. RtlZeroMemory(
  469. OpenRxContext,
  470. sizeof(RX_CONTEXT));
  471. RxInitializeContext(
  472. NULL,
  473. RxContext->RxDeviceObject,
  474. 0,
  475. OpenRxContext );
  476. oc = OpenRxContext;
  477. oc->pFcb = capFcb;
  478. oc->pFobx = capFobx;
  479. oc->NonPagedFcb = RxContext->NonPagedFcb;
  480. oc->MajorFunction = IRP_MJ_CREATE;
  481. oc->pRelevantSrvOpen = SrvOpen;
  482. oc->Create.pVNetRoot = SrvOpen->pVNetRoot;
  483. oc->Create.pNetRoot = oc->Create.pVNetRoot->pNetRoot;
  484. oc->Create.pSrvCall = oc->Create.pNetRoot->pSrvCall;
  485. oc->Flags = DeferredOpenContext->RxContextFlags;
  486. oc->Flags |= RX_CONTEXT_FLAG_MINIRDR_INITIATED|RX_CONTEXT_FLAG_WAIT|RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK;
  487. oc->Create.Flags = DeferredOpenContext->RxContextCreateFlags;
  488. oc->Create.NtCreateParameters = DeferredOpenContext->NtCreateParameters;
  489. Status = MRxSmbCreate(oc);
  490. if (Status==STATUS_SUCCESS) {
  491. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  492. MRxSmbIncrementSrvOpenCount(pServerEntry,SrvOpen);
  493. } else {
  494. ASSERT(smbSrvOpen->NumOfSrvOpenAdded);
  495. }
  496. ClearFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  497. }
  498. RxLog(("DeferredOpen %lx %lx %lx %lx\n", capFcb, capFobx, RxContext, Status));
  499. ASSERT(oc->ReferenceCount==1);
  500. RxFreePool(oc);
  501. }
  502. if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_CLOSED) ||
  503. FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_ORPHANED)) {
  504. RxFreePool(smbSrvOpen->DeferredOpenContext);
  505. smbSrvOpen->DeferredOpenContext = NULL;
  506. RxDbgTrace(0, Dbg, ("Free deferred open context for file %wZ %lX\n",GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),smbSrvOpen));
  507. }
  508. SmbCeAcquireResource();
  509. smbSrvOpen->DeferredOpenInProgress = FALSE;
  510. pListHead = &smbSrvOpen->DeferredOpenSyncContexts;
  511. pListEntry = pListHead->Flink;
  512. while (pListEntry != pListHead) {
  513. PDEFERRED_OPEN_SYNC_CONTEXT pWaitingContext;
  514. pWaitingContext = (PDEFERRED_OPEN_SYNC_CONTEXT)CONTAINING_RECORD(
  515. pListEntry,
  516. DEFERRED_OPEN_SYNC_CONTEXT,
  517. ListHead);
  518. pListEntry = pListEntry->Flink;
  519. RemoveHeadList(&pWaitingContext->ListHead);
  520. pWaitingContext->Status = Status;
  521. //DbgPrint("Signal RxContext %x after deferred open\n",pWaitingContext->RxContext);
  522. RxSignalSynchronousWaiter(pWaitingContext->RxContext);
  523. }
  524. SmbCeReleaseResource();
  525. } else {
  526. DEFERRED_OPEN_SYNC_CONTEXT WaitingContext;
  527. BOOLEAN AcquireExclusive = RxIsFcbAcquiredExclusive(capFcb);
  528. BOOLEAN AcquireShare = RxIsFcbAcquiredShared(capFcb) > 0;
  529. // put the RxContext on the waiting list
  530. WaitingContext.RxContext = RxContext;
  531. InitializeListHead(&WaitingContext.ListHead);
  532. InsertTailList(
  533. &smbSrvOpen->DeferredOpenSyncContexts,
  534. &WaitingContext.ListHead);
  535. SmbCeReleaseResource();
  536. if (AcquireExclusive || AcquireShare) {
  537. RxReleaseFcbResourceInMRx( capFcb );
  538. }
  539. RxWaitSync(RxContext);
  540. Status = WaitingContext.Status;
  541. KeInitializeEvent(
  542. &RxContext->SyncEvent,
  543. SynchronizationEvent,
  544. FALSE);
  545. if (AcquireExclusive) {
  546. RxAcquireExclusiveFcbResourceInMRx(capFcb);
  547. } else if (AcquireShare) {
  548. RxAcquireSharedFcbResourceInMRx(capFcb);
  549. }
  550. }
  551. FINALLY:
  552. return Status;
  553. }
  554. NTSTATUS
  555. MRxSmbCollapseOpen(
  556. IN OUT PRX_CONTEXT RxContext
  557. )
  558. /*++
  559. Routine Description:
  560. This routine collapses a open locally
  561. Arguments:
  562. RxContext - the RDBSS context
  563. Return Value:
  564. NTSTATUS - The return status for the operation
  565. --*/
  566. {
  567. NTSTATUS Status;
  568. RxCaptureFcb;
  569. RX_BLOCK_CONDITION FinalSrvOpenCondition;
  570. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  571. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  572. PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
  573. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  574. PAGED_CODE();
  575. RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx( RxContext, SrvOpen);
  576. if (RxContext->pFobx != NULL) {
  577. ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
  578. RxContext->pFobx->OffsetOfNextEaToReturn = 1;
  579. Status = STATUS_SUCCESS;
  580. } else {
  581. Status = STATUS_INSUFFICIENT_RESOURCES;
  582. }
  583. return Status;
  584. }
  585. NTSTATUS
  586. MRxSmbComputeNewBufferingState(
  587. IN OUT PMRX_SRV_OPEN pMRxSrvOpen,
  588. IN PVOID pMRxContext,
  589. OUT PULONG pNewBufferingState)
  590. /*++
  591. Routine Description:
  592. This routine maps the SMB specific oplock levels into the appropriate RDBSS
  593. buffering state flags
  594. Arguments:
  595. pMRxSrvOpen - the MRX SRV_OPEN extension
  596. pMRxContext - the context passed to RDBSS at Oplock indication time
  597. pNewBufferingState - the place holder for the new buffering state
  598. Return Value:
  599. Notes:
  600. --*/
  601. {
  602. ULONG OplockLevel,NewBufferingState;
  603. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(pMRxSrvOpen);
  604. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(pMRxSrvOpen->pFcb);
  605. PAGED_CODE();
  606. ASSERT(pNewBufferingState != NULL);
  607. OplockLevel = PtrToUlong(pMRxContext);
  608. if (OplockLevel == SMB_OPLOCK_LEVEL_II) {
  609. NewBufferingState = (FCB_STATE_READBUFFERING_ENABLED |
  610. FCB_STATE_READCACHING_ENABLED);
  611. } else {
  612. NewBufferingState = 0;
  613. }
  614. pMRxSrvOpen->BufferingFlags = NewBufferingState;
  615. MRxSmbMungeBufferingIfWriteOnlyHandles(
  616. smbFcb->WriteOnlySrvOpenCount,
  617. pMRxSrvOpen);
  618. *pNewBufferingState = pMRxSrvOpen->BufferingFlags;
  619. return STATUS_SUCCESS;
  620. }
  621. NTSTATUS
  622. MRxSmbConstructDeferredOpenContext (
  623. PRX_CONTEXT RxContext)
  624. /*++
  625. Routine Description:
  626. This routine saves enough state that we can come back later and really do an
  627. open if needed. We only do this for NT servers.
  628. Arguments:
  629. OrdinaryExchange - the exchange instance
  630. Return Value:
  631. NTSTATUS - The return status for the operation
  632. --*/
  633. {
  634. NTSTATUS Status = STATUS_SUCCESS;
  635. RxCaptureFobx;
  636. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  637. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  638. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)RxContext->Create.pSrvCall->Context;
  639. PSMBCE_SERVER pServer = &pServerEntry->Server;
  640. PMRX_SMB_DEFERRED_OPEN_CONTEXT DeferredOpenContext;
  641. PDFS_NAME_CONTEXT pDNC=NULL;
  642. DWORD cbSize;
  643. PAGED_CODE();
  644. RxDbgTrace(+1, Dbg, ("MRxSmbConstructDeferredOpenContext\n"));
  645. ASSERT(smbSrvOpen->DeferredOpenContext == NULL);
  646. cbSize = sizeof(MRX_SMB_DEFERRED_OPEN_CONTEXT);
  647. // if there is a dfs name context, we need to allocate memory
  648. // fot aht too, because the name that is included in the
  649. // context is deallocated by DFS when it returns from the create call
  650. if(pDNC = RxContext->Create.NtCreateParameters.DfsNameContext)
  651. {
  652. cbSize += (sizeof(DFS_NAME_CONTEXT)+pDNC->UNCFileName.MaximumLength+sizeof(DWORD));
  653. }
  654. DeferredOpenContext = RxAllocatePoolWithTag(
  655. NonPagedPool,
  656. cbSize,
  657. MRXSMB_DEFROPEN_POOLTAG);
  658. if (DeferredOpenContext == NULL) {
  659. Status = STATUS_INSUFFICIENT_RESOURCES;
  660. goto FINALLY;
  661. }
  662. smbSrvOpen->DeferredOpenContext = DeferredOpenContext;
  663. DeferredOpenContext->NtCreateParameters = RxContext->Create.NtCreateParameters;
  664. DeferredOpenContext->RxContextCreateFlags = RxContext->Create.Flags;
  665. DeferredOpenContext->RxContextFlags = RxContext->Flags;
  666. DeferredOpenContext->NtCreateParameters.SecurityContext = NULL;
  667. MRxSmbAdjustCreateParameters(RxContext, &DeferredOpenContext->SmbCp);
  668. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN);
  669. if (pDNC)
  670. {
  671. PDFS_NAME_CONTEXT pDNCDeferred=NULL;
  672. // point the dfs name context after the rxcontext
  673. pDNCDeferred = (PDFS_NAME_CONTEXT)((PBYTE)DeferredOpenContext+sizeof(MRX_SMB_DEFERRED_OPEN_CONTEXT));
  674. DeferredOpenContext->NtCreateParameters.DfsNameContext = pDNCDeferred;
  675. // copy the info
  676. *pDNCDeferred = *pDNC;
  677. if (pDNC->UNCFileName.Length)
  678. {
  679. ASSERT(pDNC->UNCFileName.Buffer);
  680. // point the name buffer after deferredcontext+dfs_name_context
  681. pDNCDeferred->UNCFileName.Buffer = (PWCHAR)((PBYTE)pDNCDeferred+sizeof(DFS_NAME_CONTEXT));
  682. memcpy(pDNCDeferred->UNCFileName.Buffer,
  683. pDNC->UNCFileName.Buffer,
  684. pDNC->UNCFileName.Length);
  685. }
  686. }
  687. FINALLY:
  688. RxDbgTrace(-1, Dbg, ("MRxSmbConstructDeferredOpenContext, Status=%08lx\n",Status));
  689. return Status;
  690. }
  691. VOID
  692. MRxSmbAdjustCreateParameters (
  693. PRX_CONTEXT RxContext,
  694. PMRXSMB_CREATE_PARAMETERS smbcp
  695. )
  696. /*++
  697. Routine Description:
  698. This uses the RxContext as a base to reeach out and get the values of the NT
  699. create parameters. It also (a) implements the SMB idea that unbuffered is
  700. translated to write-through and (b) gets the SMB security flags.
  701. Arguments:
  702. Return Value:
  703. Notes:
  704. --*/
  705. {
  706. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  707. PAGED_CODE();
  708. RxDbgTrace(+1, Dbg, ("MRxSmbAdjustCreateParameters\n"));
  709. if (!FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED)) {
  710. cp->CreateOptions = cp->CreateOptions & ~(FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT);
  711. //the NT SMB spec says we have to change no-intermediate-buffering to write-through
  712. if (FlagOn(cp->CreateOptions,FILE_NO_INTERMEDIATE_BUFFERING)) {
  713. ASSERT (RxContext->CurrentIrpSp!=NULL);
  714. if (RxContext->CurrentIrpSp!=NULL) {
  715. PFILE_OBJECT capFileObject = RxContext->CurrentIrpSp->FileObject;
  716. ClearFlag(cp->CreateOptions,FILE_NO_INTERMEDIATE_BUFFERING);
  717. SetFlag(cp->CreateOptions,FILE_WRITE_THROUGH);
  718. SetFlag(RxContext->Flags,RX_CONTEXT_FLAG_WRITE_THROUGH);
  719. SetFlag(capFileObject->Flags,FO_WRITE_THROUGH);
  720. }
  721. }
  722. smbcp->Pid = RxGetRequestorProcessId(RxContext);
  723. smbcp->SecurityFlags = 0;
  724. if (cp->SecurityContext != NULL) {
  725. if (cp->SecurityContext->SecurityQos != NULL) {
  726. if (cp->SecurityContext->SecurityQos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING) {
  727. smbcp->SecurityFlags |= SMB_SECURITY_DYNAMIC_TRACKING;
  728. }
  729. if (cp->SecurityContext->SecurityQos->EffectiveOnly) {
  730. smbcp->SecurityFlags |= SMB_SECURITY_EFFECTIVE_ONLY;
  731. }
  732. }
  733. }
  734. } else {
  735. //here, we have a defered open!!!
  736. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  737. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  738. //the parameters have already been adjusted...BUT null the security context.......
  739. cp->SecurityContext = NULL;
  740. *smbcp = smbSrvOpen->DeferredOpenContext->SmbCp;
  741. }
  742. RxDbgTrace(-1, Dbg, ("MRxSmbAdjustCreateParameters\n"));
  743. }
  744. INLINE VOID
  745. MRxSmbAdjustReturnedCreateAction(
  746. IN OUT PRX_CONTEXT RxContext
  747. )
  748. /*++
  749. Routine Description:
  750. This routine repairs a bug in NT servers whereby the create action is
  751. contaminated by an oplock break. Basically, we make sure that if the guy
  752. asked for FILE_OPEN and it works then he does not get FILE_SUPERCEDED or
  753. FILE_CREATED as the result.
  754. Arguments:
  755. RxContext - the context for the operation so as to find the place where
  756. info is returned
  757. Return Value:
  758. none
  759. Notes:
  760. --*/
  761. {
  762. ULONG q = RxContext->Create.ReturnedCreateInformation;
  763. PAGED_CODE();
  764. if ((q==FILE_SUPERSEDED)||(q==FILE_CREATED)||(q >FILE_MAXIMUM_DISPOSITION)) {
  765. RxContext->Create.ReturnedCreateInformation = FILE_OPENED;
  766. }
  767. }
  768. UNICODE_STRING UnicodeBackslash = {2,4,L"\\"};
  769. NTSTATUS
  770. MRxSmbBuildNtCreateAndX (
  771. PSMBSTUFFER_BUFFER_STATE StufferState,
  772. PMRXSMB_CREATE_PARAMETERS smbcp
  773. )
  774. /*++
  775. Routine Description:
  776. This builds an NtCreateAndX SMB. we don't have to worry about login id and such
  777. since that is done by the connection engine....pretty neat huh? all we have to do
  778. is to format up the bits
  779. Arguments:
  780. StufferState - the state of the smbbuffer from the stuffer's point of view
  781. Return Value:
  782. NTSTATUS
  783. SUCCESS
  784. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  785. Notes:
  786. --*/
  787. {
  788. NTSTATUS Status;
  789. PRX_CONTEXT RxContext = StufferState->RxContext;
  790. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  791. RxCaptureFcb;
  792. ACCESS_MASK DesiredAccess;
  793. ULONG OplockFlags;
  794. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  795. PSMBCE_SERVER pServer;
  796. PAGED_CODE();
  797. RxDbgTrace(+1, Dbg, ("MRxSmbBuildNtCreateAndX\n", 0 ));
  798. pServer = SmbCeGetExchangeServer(StufferState->Exchange);
  799. if (!(cp->CreateOptions & FILE_DIRECTORY_FILE) &&
  800. (cp->DesiredAccess & (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE )) &&
  801. !MRxSmbOplocksDisabled) {
  802. DesiredAccess = cp->DesiredAccess & ~SYNCHRONIZE;
  803. OplockFlags = (NT_CREATE_REQUEST_OPLOCK | NT_CREATE_REQUEST_OPBATCH);
  804. } else {
  805. DesiredAccess = cp->DesiredAccess;
  806. OplockFlags = 0;
  807. }
  808. if ((RemainingName->Length==0)
  809. && (FlagOn(RxContext->Create.Flags,RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH)) ) {
  810. RemainingName = &UnicodeBackslash;
  811. }
  812. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never,
  813. SMB_COM_NT_CREATE_ANDX, SMB_REQUEST_SIZE(NT_CREATE_ANDX),
  814. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(4,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  815. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  816. );
  817. SmbCeSetFullProcessIdInHeader(
  818. StufferState->Exchange,
  819. smbcp->Pid,
  820. ((PNT_SMB_HEADER)StufferState->BufferBase));
  821. MRxSmbStuffSMB (StufferState,
  822. "XmwdddDdddDddyB",
  823. // X UCHAR WordCount; // Count of parameter words = 24
  824. // . UCHAR AndXCommand; // Secondary command; 0xFF = None
  825. // . UCHAR AndXReserved; // MBZ
  826. // . _USHORT( AndXOffset ); // Offset to next command wordcount
  827. // m UCHAR Reserved; // MBZ
  828. BooleanFlagOn(pServer->DialectFlags,DF_UNICODE)?
  829. RemainingName->Length:RtlxUnicodeStringToOemSize(RemainingName),
  830. // w _USHORT( NameLength ); // Length of Name[] in bytes
  831. OplockFlags, // d _ULONG( Flags ); // Create flags
  832. 0, //not used // d _ULONG( RootDirectoryFid ); // If non-zero, open is relative to this directory
  833. DesiredAccess, // d ACCESS_MASK DesiredAccess; // NT access desired
  834. // Dd LARGE_INTEGER AllocationSize; // Initial allocation size
  835. SMB_OFFSET_CHECK(NT_CREATE_ANDX,AllocationSize)
  836. cp->AllocationSize.LowPart, cp->AllocationSize.HighPart,
  837. cp->FileAttributes, // d _ULONG( FileAttributes ); // File attributes for creation
  838. cp->ShareAccess, // d _ULONG( ShareAccess ); // Type of share access
  839. // D _ULONG( CreateDisposition ); // Action to take if file exists or not
  840. SMB_OFFSET_CHECK(NT_CREATE_ANDX,CreateDisposition)
  841. cp->Disposition,
  842. cp->CreateOptions, // d _ULONG( CreateOptions ); // Options to use if creating a file
  843. cp->ImpersonationLevel,// d _ULONG( ImpersonationLevel ); // Security QOS information
  844. smbcp->SecurityFlags, // y UCHAR SecurityFlags; // Security QOS information
  845. SMB_WCT_CHECK(24) 0 // B _USHORT( ByteCount ); // Length of byte parameters
  846. // . UCHAR Buffer[1];
  847. // . //UCHAR Name[]; // File to open or create
  848. );
  849. //proceed with the stuff because we know here that the name fits
  850. MRxSmbStuffSMB(StufferState,
  851. BooleanFlagOn(pServer->DialectFlags,DF_UNICODE)?"u!":"z!",
  852. RemainingName);
  853. MRxSmbDumpStufferState (700,"SMB w/ NTOPEN&X after stuffing",StufferState);
  854. FINALLY:
  855. RxDbgTraceUnIndent(-1,Dbg);
  856. return(Status);
  857. }
  858. NTSTATUS
  859. MRxSmbBuildOpenAndX (
  860. PSMBSTUFFER_BUFFER_STATE StufferState,
  861. PMRXSMB_CREATE_PARAMETERS smbcp
  862. )
  863. /*++
  864. Routine Description:
  865. This builds an OpenAndX SMB. we don't have to worry about login id and such
  866. since that is done by the connection engine....pretty neat huh? all we have to do
  867. is to format up the bits
  868. Arguments:
  869. StufferState - the state of the smbbuffer from the stuffer's point of view
  870. Return Value:
  871. RXSTATUS
  872. SUCCESS
  873. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  874. Notes:
  875. --*/
  876. {
  877. NTSTATUS Status;
  878. PRX_CONTEXT RxContext = StufferState->RxContext;
  879. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  880. PSMB_EXCHANGE Exchange = StufferState->Exchange;
  881. RxCaptureFcb;
  882. PSMBCE_SERVER pServer;
  883. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  884. USHORT smbDisposition;
  885. USHORT smbSharingMode;
  886. USHORT smbAttributes;
  887. ULONG smbFileSize;
  888. USHORT smbOpenMode;
  889. USHORT OpenAndXFlags = (SMB_OPEN_QUERY_INFORMATION);
  890. USHORT SearchAttributes = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN;
  891. LARGE_INTEGER CurrentTime;
  892. ULONG SecondsSince1970;
  893. PAGED_CODE();
  894. RxDbgTrace(+1, Dbg, ("MRxSmbBuildOpenAndX\n", 0 ));
  895. pServer = SmbCeGetExchangeServer(Exchange);
  896. smbDisposition = MRxSmbMapDisposition(cp->Disposition);
  897. smbSharingMode = MRxSmbMapShareAccess(((USHORT)cp->ShareAccess));
  898. smbAttributes = MRxSmbMapFileAttributes(cp->FileAttributes);
  899. smbFileSize = cp->AllocationSize.LowPart;
  900. smbOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
  901. smbSharingMode |= smbOpenMode;
  902. if (cp->CreateOptions & FILE_WRITE_THROUGH) {
  903. smbSharingMode |= SMB_DA_WRITE_THROUGH;
  904. }
  905. //lanman10 servers apparently don't like to get the time passed in.......
  906. if (FlagOn(pServer->DialectFlags,DF_LANMAN20)) {
  907. KeQuerySystemTime(&CurrentTime);
  908. MRxSmbTimeToSecondsSince1970(&CurrentTime,
  909. pServer,
  910. &SecondsSince1970);
  911. } else {
  912. SecondsSince1970 = 0;
  913. }
  914. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never,
  915. SMB_COM_OPEN_ANDX, SMB_REQUEST_SIZE(OPEN_ANDX),
  916. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(4,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  917. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  918. );
  919. MRxSmbStuffSMB (StufferState,
  920. "XwwwwdwDddB",
  921. // X UCHAR WordCount; // Count of parameter words = 15
  922. // . UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
  923. // . UCHAR AndXReserved; // Reserved (must be 0)
  924. // . _USHORT( AndXOffset ); // Offset to next command WordCount
  925. OpenAndXFlags, // w _USHORT( Flags ); // Additional information: bit set-
  926. // // 0 - return additional info
  927. // // 1 - set single user total file lock
  928. // // 2 - server notifies consumer of
  929. // // actions which may change file
  930. smbSharingMode, // w _USHORT( DesiredAccess ); // File open mode
  931. SearchAttributes, // w _USHORT( SearchAttributes );
  932. smbAttributes, // w _USHORT( FileAttributes );
  933. SecondsSince1970, // d _ULONG( CreationTimeInSeconds );
  934. smbDisposition, // w _USHORT( OpenFunction );
  935. // D _ULONG( AllocationSize ); // Bytes to reserve on create or truncate
  936. SMB_OFFSET_CHECK(OPEN_ANDX,AllocationSize)
  937. smbFileSize,
  938. 0xffffffff, // d _ULONG( Timeout ); // Max milliseconds to wait for resource
  939. 0, // d _ULONG( Reserved ); // Reserved (must be 0)
  940. SMB_WCT_CHECK(15) 0 // B _USHORT( ByteCount ); // Count of data bytes; min = 1
  941. // UCHAR Buffer[1]; // File name
  942. );
  943. //proceed with the stuff because we know here that the name fits
  944. MRxSmbStuffSMB (StufferState,"z!", RemainingName);
  945. MRxSmbDumpStufferState (700,"SMB w/ OPEN&X after stuffing",StufferState);
  946. FINALLY:
  947. RxDbgTraceUnIndent(-1,Dbg);
  948. return(Status);
  949. }
  950. typedef enum _SMBPSE_CREATE_METHOD {
  951. CreateAlreadyDone,
  952. CreateUseCore,
  953. CreateUseNT
  954. } SMBPSE_CREATE_METHOD;
  955. NTSTATUS
  956. SmbPseExchangeStart_Create(
  957. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  958. )
  959. /*++
  960. Routine Description:
  961. This is the start routine for net root construction exchanges. This initiates the
  962. construction of the appropriate SMB's if required.
  963. Arguments:
  964. pExchange - the exchange instance
  965. Return Value:
  966. NTSTATUS - The return status for the operation
  967. --*/
  968. {
  969. NTSTATUS Status = (STATUS_NOT_IMPLEMENTED);
  970. NTSTATUS SetupStatus = STATUS_SUCCESS;
  971. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  972. SMBPSE_CREATE_METHOD CreateMethod = CreateAlreadyDone;
  973. PSMBCE_SERVER pServer;
  974. ULONG DialectFlags;
  975. RxCaptureFcb;
  976. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  977. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  978. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  979. PBOOLEAN MustRegainExclusiveResource = &OrdinaryExchange->Create.MustRegainExclusiveResource;
  980. BOOLEAN CreateWithEasSidsOrLongName = OrdinaryExchange->Create.CreateWithEasSidsOrLongName;
  981. BOOLEAN fRetryCore = FALSE;
  982. PAGED_CODE();
  983. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_Create\n", 0 ));
  984. ASSERT_ORDINARY_EXCHANGE(OrdinaryExchange);
  985. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  986. DialectFlags = pServer->DialectFlags;
  987. COVERED_CALL(MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0)));
  988. *MustRegainExclusiveResource = TRUE;
  989. if (!FlagOn(DialectFlags,DF_NT_SMBS)) {
  990. OEM_STRING OemString;
  991. PUNICODE_STRING PathName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  992. if (PathName->Length != 0) {
  993. Status = RtlUnicodeStringToOemString(&OemString, PathName, TRUE);
  994. if (!NT_SUCCESS(Status)) {
  995. goto FINALLY;
  996. }
  997. //
  998. // If we are canonicalizing as FAT, use FAT rules, otherwise use
  999. // HPFS rules.
  1000. //
  1001. if (!FlagOn(DialectFlags,DF_LANMAN20)) {
  1002. if (!FsRtlIsFatDbcsLegal(OemString, FALSE, TRUE, TRUE)) {
  1003. RtlFreeOemString(&OemString);
  1004. Status = STATUS_OBJECT_NAME_INVALID;
  1005. goto FINALLY;
  1006. }
  1007. } else if (!FsRtlIsHpfsDbcsLegal(OemString, FALSE, TRUE, TRUE)) {
  1008. RtlFreeOemString(&OemString);
  1009. Status = STATUS_OBJECT_NAME_INVALID;
  1010. goto FINALLY;
  1011. }
  1012. RtlFreeOemString(&OemString);
  1013. }
  1014. }
  1015. if (StufferState->PreviousCommand != SMB_COM_NO_ANDX_COMMAND) {
  1016. // we have a latent session setup /tree connect command
  1017. //the status of the embedded header commands is passed back in the flags.
  1018. SetupStatus = SmbPseOrdinaryExchange(
  1019. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1020. SMBPSE_OETYPE_LATENT_HEADEROPS
  1021. );
  1022. if(SetupStatus != STATUS_SUCCESS) {
  1023. Status = SetupStatus;
  1024. goto FINALLY;
  1025. }
  1026. // Turn off reconnect attempts now that we have successfully established
  1027. // the session and net root.
  1028. OrdinaryExchange->SmbCeFlags &= ~(SMBCE_EXCHANGE_ATTEMPT_RECONNECTS);
  1029. COVERED_CALL(MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0)));
  1030. }
  1031. if (!CreateWithEasSidsOrLongName) {
  1032. PUNICODE_STRING AlreadyPrefixedName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  1033. PMRXSMB_CREATE_PARAMETERS SmbCp = &OrdinaryExchange->Create.SmbCp;
  1034. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  1035. USHORT mappedOpenMode;
  1036. MRxSmbAdjustCreateParameters(RxContext,SmbCp);
  1037. mappedOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
  1038. if ((!MRxSmbForceNoNtCreate)
  1039. && FlagOn(DialectFlags,DF_NT_SMBS)) {
  1040. BOOLEAN SecurityIsNULL =
  1041. (cp->SecurityContext == NULL) ||
  1042. (cp->SecurityContext->AccessState == NULL) ||
  1043. (cp->SecurityContext->AccessState->SecurityDescriptor == NULL);
  1044. CreateMethod = CreateUseNT;
  1045. //now catch the cases where we want to pseudoopen the file
  1046. if ( MRxSmbDeferredOpensEnabled &&
  1047. !FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED) &&
  1048. (capFcb->pNetRoot->Type == NET_ROOT_DISK) &&
  1049. SecurityIsNULL) {
  1050. ASSERT( RxContext->CurrentIrp != 0 );
  1051. if ((cp->Disposition==FILE_OPEN) &&
  1052. !BooleanFlagOn(cp->CreateOptions, FILE_OPEN_FOR_BACKUP_INTENT) &&
  1053. (MustBeDirectory(cp->CreateOptions) ||
  1054. !(cp->DesiredAccess & ~(SYNCHRONIZE | DELETE | FILE_READ_ATTRIBUTES)))){
  1055. // NT apps expect that you will not succeed the create and then fail the attribs;
  1056. // if we had some way of identifying win32 apps then we could defer these (except
  1057. // for DFS). since we have no way to get that information (and don't even have
  1058. // a good SMB to send..........)
  1059. // we don't need to send the open for DELETE and FILE_READ_ATTRIBUTES requests since
  1060. // there are path basied SMB operations.
  1061. // we can also pseudoopen directories for file_open at the root of the
  1062. // share but otherwise we have to at least check that the directory
  1063. // exists. we might have to push out the open later. BTW, we wouldn't be
  1064. // in here if the name was too long for a GFA or CheckPath
  1065. Status = MRxSmbPseudoOpenTailFromFakeGFAResponse(
  1066. OrdinaryExchange,
  1067. MustBeDirectory(cp->CreateOptions)?FileTypeDirectory:FileTypeFile);
  1068. if (Status == STATUS_SUCCESS && AlreadyPrefixedName->Length > 0) {
  1069. // send query path information to make sure the file exists on the server
  1070. Status = MRxSmbQueryFileInformationFromPseudoOpen(
  1071. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1072. if (Status == STATUS_SUCCESS) {
  1073. if (MustBeDirectory(cp->CreateOptions) &&
  1074. !OrdinaryExchange->Create.FileInfo.Standard.Directory) {
  1075. Status = STATUS_NOT_A_DIRECTORY;
  1076. }
  1077. }
  1078. if (Status != STATUS_SUCCESS) {
  1079. RxFreePool(smbSrvOpen->DeferredOpenContext);
  1080. smbSrvOpen->DeferredOpenContext = NULL;
  1081. }
  1082. }
  1083. CreateMethod = CreateAlreadyDone;
  1084. }
  1085. }
  1086. //if no pseudoopen case was hit, do a real open
  1087. if (CreateMethod == CreateUseNT) {
  1088. //use NT_CREATE&X
  1089. COVERED_CALL(MRxSmbBuildNtCreateAndX(StufferState,SmbCp));
  1090. Status = SmbPseOrdinaryExchange(
  1091. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1092. SMBPSE_OETYPE_CREATE
  1093. );
  1094. if (Status == STATUS_SUCCESS && RxContext->pFobx == NULL) {
  1095. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1096. }
  1097. if ((Status == STATUS_SUCCESS) && (cp->Disposition == FILE_OPEN)) {
  1098. MRxSmbAdjustReturnedCreateAction(RxContext);
  1099. }
  1100. }
  1101. } else if (FlagOn(DialectFlags, DF_LANMAN10) &&
  1102. (mappedOpenMode != ((USHORT)-1)) &&
  1103. !MustBeDirectory(cp->CreateOptions)) {
  1104. if (MRxSmbDeferredOpensEnabled &&
  1105. capFcb->pNetRoot->Type == NET_ROOT_DISK &&
  1106. !FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_MINIRDR_INITIATED) &&
  1107. (cp->Disposition==FILE_OPEN) &&
  1108. ((cp->DesiredAccess & ~(SYNCHRONIZE | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)) == 0) ){
  1109. // we don't need to send the open for DELETE and FILE_READ_ATTRIBUTES requests since
  1110. // there are path basied SMB operations.
  1111. // we should do pseudo open for FILE_WRITE_ATTRIBUTES. Othewise the server will return
  1112. // sharing violation
  1113. // send query path information to make sure the file exists on the server
  1114. Status = MRxSmbPseudoOpenTailFromFakeGFAResponse(
  1115. OrdinaryExchange,
  1116. MustBeDirectory(cp->CreateOptions)?FileTypeDirectory:FileTypeFile);
  1117. if (Status == STATUS_SUCCESS && AlreadyPrefixedName->Length > 0) {
  1118. Status = MRxSmbQueryFileInformationFromPseudoOpen(
  1119. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1120. if (Status != STATUS_SUCCESS) {
  1121. RxFreePool(smbSrvOpen->DeferredOpenContext);
  1122. smbSrvOpen->DeferredOpenContext = NULL;
  1123. }
  1124. }
  1125. CreateMethod = CreateAlreadyDone;
  1126. } else {
  1127. //use OPEN&X
  1128. COVERED_CALL(MRxSmbBuildOpenAndX(StufferState,SmbCp));
  1129. Status = SmbPseOrdinaryExchange(
  1130. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1131. SMBPSE_OETYPE_CREATE
  1132. );
  1133. if (Status == STATUS_ACCESS_DENIED && !FlagOn(DialectFlags,DF_NT_SMBS)) {
  1134. CreateMethod = CreateUseCore;
  1135. fRetryCore = TRUE;
  1136. }
  1137. }
  1138. } else {
  1139. CreateMethod = CreateUseCore;
  1140. }
  1141. if (CreateMethod == CreateUseCore) {
  1142. Status = MRxSmbDownlevelCreate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1143. // put back the real error code if we are retrying open&x
  1144. if ((Status != STATUS_SUCCESS) && fRetryCore)
  1145. {
  1146. Status = STATUS_ACCESS_DENIED;
  1147. }
  1148. }
  1149. }
  1150. FINALLY:
  1151. if (*MustRegainExclusiveResource) {
  1152. RxAcquireExclusiveFcbResourceInMRx( capFcb );
  1153. }
  1154. // now that we have the fcb exclusive, we can do some updates
  1155. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE)) {
  1156. smbFcb->WriteOnlySrvOpenCount++;
  1157. }
  1158. MRxSmbMungeBufferingIfWriteOnlyHandles(
  1159. smbFcb->WriteOnlySrvOpenCount,
  1160. SrvOpen
  1161. );
  1162. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Create exit w %08lx\n", Status ));
  1163. return Status;
  1164. }
  1165. VOID
  1166. MRxSmbSetSrvOpenFlags (
  1167. PRX_CONTEXT RxContext,
  1168. RX_FILE_TYPE StorageType,
  1169. PMRX_SRV_OPEN SrvOpen,
  1170. PMRX_SMB_SRV_OPEN smbSrvOpen
  1171. )
  1172. {
  1173. PAGED_CODE();
  1174. RxDbgTrace( 0, Dbg, ("MRxSmbSetSrvOpenFlags oplockstate =%08lx\n", smbSrvOpen->OplockLevel ));
  1175. SrvOpen->BufferingFlags = 0;
  1176. switch (smbSrvOpen->OplockLevel) {
  1177. case SMB_OPLOCK_LEVEL_II:
  1178. SrvOpen->BufferingFlags |= (FCB_STATE_READBUFFERING_ENABLED |
  1179. FCB_STATE_READCACHING_ENABLED);
  1180. break;
  1181. case SMB_OPLOCK_LEVEL_BATCH:
  1182. if (StorageType == FileTypeFile) {
  1183. SrvOpen->BufferingFlags |= FCB_STATE_COLLAPSING_ENABLED;
  1184. }
  1185. // lack of break intentional
  1186. case SMB_OPLOCK_LEVEL_EXCLUSIVE:
  1187. SrvOpen->BufferingFlags |= (FCB_STATE_WRITECACHING_ENABLED |
  1188. FCB_STATE_FILESIZECACHEING_ENABLED |
  1189. FCB_STATE_FILETIMECACHEING_ENABLED |
  1190. FCB_STATE_WRITEBUFFERING_ENABLED |
  1191. FCB_STATE_LOCK_BUFFERING_ENABLED |
  1192. FCB_STATE_READBUFFERING_ENABLED |
  1193. FCB_STATE_READCACHING_ENABLED);
  1194. break;
  1195. default:
  1196. ASSERT(!"Valid Oplock Level for Open");
  1197. case SMB_OPLOCK_LEVEL_NONE:
  1198. break;
  1199. }
  1200. SrvOpen->Flags |= MRxSmbInitialSrvOpenFlags;
  1201. }
  1202. NTSTATUS
  1203. MRxSmbCreateFileSuccessTail (
  1204. PRX_CONTEXT RxContext,
  1205. PBOOLEAN MustRegainExclusiveResource,
  1206. RX_FILE_TYPE StorageType,
  1207. SMB_FILE_ID Fid,
  1208. ULONG ServerVersion,
  1209. UCHAR OplockLevel,
  1210. ULONG CreateAction,
  1211. PSMBPSE_FILEINFO_BUNDLE FileInfo
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. This routine finishes the initialization of the fcb and srvopen for a successful open.
  1216. Arguments:
  1217. Return Value:
  1218. NTSTATUS - The return status for the operation
  1219. --*/
  1220. {
  1221. NTSTATUS Status = STATUS_SUCCESS;
  1222. RxCaptureFcb;
  1223. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1224. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1225. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1226. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)RxContext->Create.pSrvCall->Context;
  1227. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)SrvOpen->pVNetRoot->Context;
  1228. BOOLEAN ThisIsAPseudoOpen;
  1229. FCB_INIT_PACKET LocalInitPacket, *InitPacket;
  1230. PAGED_CODE();
  1231. RxDbgTrace(+1, Dbg, ("MRxSmbCreateFileSuccessTail\n", 0 ));
  1232. smbSrvOpen->Fid = Fid;
  1233. smbSrvOpen->Version = ServerVersion;
  1234. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  1235. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  1236. if (*MustRegainExclusiveResource) {
  1237. //this is required because of oplock breaks
  1238. RxAcquireExclusiveFcbResourceInMRx( capFcb );
  1239. *MustRegainExclusiveResource = FALSE;
  1240. }
  1241. if (RxContext->pFobx==NULL) {
  1242. RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
  1243. }
  1244. ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
  1245. RxDbgTrace(
  1246. 0, Dbg,
  1247. ("Storagetype %08lx/Fid %08lx/Action %08lx\n", StorageType, Fid, CreateAction ));
  1248. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(SrvOpen->pVNetRoot);
  1249. SrvOpen->Key = MRxSmbMakeSrvOpenKey(pVNetRootContext->TreeId,Fid);
  1250. smbSrvOpen->OplockLevel = OplockLevel;
  1251. RxContext->Create.ReturnedCreateInformation = CreateAction;
  1252. if ( ((FileInfo->Standard.AllocationSize.HighPart == FileInfo->Standard.EndOfFile.HighPart)
  1253. && (FileInfo->Standard.AllocationSize.LowPart < FileInfo->Standard.EndOfFile.LowPart))
  1254. || (FileInfo->Standard.AllocationSize.HighPart < FileInfo->Standard.EndOfFile.HighPart)
  1255. ) {
  1256. FileInfo->Standard.AllocationSize = FileInfo->Standard.EndOfFile;
  1257. }
  1258. smbFcb->dwFileAttributes = FileInfo->Basic.FileAttributes;
  1259. if (smbSrvOpen->OplockLevel > smbFcb->LastOplockLevel) {
  1260. ClearFlag(
  1261. capFcb->FcbState,
  1262. FCB_STATE_TIME_AND_SIZE_ALREADY_SET);
  1263. }
  1264. smbFcb->LastOplockLevel = smbSrvOpen->OplockLevel;
  1265. //the thing is this: if we have good info (not a pseudoopen) then we make the
  1266. //finish call passing the init packet; otherwise, we make the call NOT passing an init packet
  1267. ThisIsAPseudoOpen = BooleanFlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  1268. if (!ThisIsAPseudoOpen) {
  1269. MRxSmbIncrementSrvOpenCount(pServerEntry,SrvOpen);
  1270. }
  1271. if ((capFcb->OpenCount == 0) ||
  1272. (!ThisIsAPseudoOpen &&
  1273. !FlagOn(capFcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET))) {
  1274. if (!ThisIsAPseudoOpen) {
  1275. RxFormInitPacket(
  1276. LocalInitPacket,
  1277. &FileInfo->Basic.FileAttributes,
  1278. &FileInfo->Standard.NumberOfLinks,
  1279. &FileInfo->Basic.CreationTime,
  1280. &FileInfo->Basic.LastAccessTime,
  1281. &FileInfo->Basic.LastWriteTime,
  1282. &FileInfo->Basic.ChangeTime,
  1283. &FileInfo->Standard.AllocationSize,
  1284. &FileInfo->Standard.EndOfFile,
  1285. &FileInfo->Standard.EndOfFile);
  1286. InitPacket = &LocalInitPacket;
  1287. } else {
  1288. InitPacket = NULL;
  1289. }
  1290. RxFinishFcbInitialization( capFcb,
  1291. RDBSS_STORAGE_NTC(StorageType),
  1292. InitPacket
  1293. );
  1294. if (FlagOn( capFcb->FcbState, FCB_STATE_PAGING_FILE )) {
  1295. PPAGING_FILE_CONTEXT PagingFileContext;
  1296. ASSERT(FALSE);
  1297. PagingFileContext = RxAllocatePoolWithTag(NonPagedPool,
  1298. sizeof(PAGING_FILE_CONTEXT),
  1299. MRXSMB_MISC_POOLTAG);
  1300. if (PagingFileContext != NULL) {
  1301. PagingFileContext->pSrvOpen = SrvOpen;
  1302. PagingFileContext->pFobx = RxContext->pFobx;
  1303. InsertHeadList(
  1304. &MRxSmbPagingFilesSrvOpenList,
  1305. &PagingFileContext->ContextList);
  1306. } else {
  1307. Status = STATUS_INSUFFICIENT_RESOURCES;
  1308. }
  1309. }
  1310. }
  1311. MRxSmbSetSrvOpenFlags(RxContext,StorageType,SrvOpen,smbSrvOpen);
  1312. //(wrapperFcb->Condition) = Condition_Good;
  1313. RxContext->pFobx->OffsetOfNextEaToReturn = 1;
  1314. //transition happens later
  1315. RxDbgTrace(-1, Dbg, ("MRxSmbFinishCreateFile returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1316. return Status;
  1317. }
  1318. NTSTATUS
  1319. MRxSmbFinishNTCreateAndX (
  1320. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1321. PRESP_NT_CREATE_ANDX Response
  1322. )
  1323. /*++
  1324. Routine Description:
  1325. This routine actually gets the stuff out of the NTCreate_AndX response.
  1326. Arguments:
  1327. OrdinaryExchange - the exchange instance
  1328. Response - the response
  1329. Return Value:
  1330. RXSTATUS - The return status for the operation
  1331. --*/
  1332. {
  1333. NTSTATUS Status = STATUS_SUCCESS;
  1334. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1335. RxCaptureFcb;
  1336. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1337. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1338. PSMBCE_SESSION pSession = SmbCeGetExchangeSession(OrdinaryExchange);
  1339. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = SmbCeGetExchangeNetRootEntry(OrdinaryExchange);
  1340. RX_FILE_TYPE StorageType;
  1341. SMB_FILE_ID Fid;
  1342. ULONG CreateAction;
  1343. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1344. PAGED_CODE();
  1345. RxDbgTrace(+1, Dbg, ("MRxSmbFinishNTCreateAndX\n", 0 ));
  1346. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  1347. if (RxContext->Create.NtCreateParameters.CreateOptions & FILE_DELETE_ON_CLOSE) {
  1348. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1349. SetFlag((smbFcb)->MFlags,SMB_FCB_FLAG_SENT_DISPOSITION_INFO);
  1350. }
  1351. StorageType = RxInferFileType(RxContext);
  1352. if (StorageType == 0) {
  1353. StorageType = Response->Directory
  1354. ?(FileTypeDirectory)
  1355. :(FileTypeFile);
  1356. RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
  1357. }
  1358. Fid = SmbGetUshort(&Response->Fid);
  1359. CreateAction = SmbGetUlong(&Response->CreateAction);
  1360. pFileInfo->Basic.FileAttributes = SmbGetUlong(&Response->FileAttributes);
  1361. pFileInfo->Standard.NumberOfLinks = 1;
  1362. pFileInfo->Basic.CreationTime.LowPart = SmbGetUlong(&Response->CreationTime.LowPart);
  1363. pFileInfo->Basic.CreationTime.HighPart = SmbGetUlong(&Response->CreationTime.HighPart);
  1364. pFileInfo->Basic.LastAccessTime.LowPart = SmbGetUlong(&Response->LastAccessTime.LowPart);
  1365. pFileInfo->Basic.LastAccessTime.HighPart = SmbGetUlong(&Response->LastAccessTime.HighPart);
  1366. pFileInfo->Basic.LastWriteTime.LowPart = SmbGetUlong(&Response->LastWriteTime.LowPart);
  1367. pFileInfo->Basic.LastWriteTime.HighPart = SmbGetUlong(&Response->LastWriteTime.HighPart);
  1368. pFileInfo->Basic.ChangeTime.LowPart = SmbGetUlong(&Response->ChangeTime.LowPart);
  1369. pFileInfo->Basic.ChangeTime.HighPart = SmbGetUlong(&Response->ChangeTime.HighPart);
  1370. pFileInfo->Standard.AllocationSize.LowPart = SmbGetUlong(&Response->AllocationSize.LowPart);
  1371. pFileInfo->Standard.AllocationSize.HighPart = SmbGetUlong(&Response->AllocationSize.HighPart);
  1372. pFileInfo->Standard.EndOfFile.LowPart = SmbGetUlong(&Response->EndOfFile.LowPart);
  1373. pFileInfo->Standard.EndOfFile.HighPart = SmbGetUlong(&Response->EndOfFile.HighPart);
  1374. pFileInfo->Standard.Directory = Response->Directory;
  1375. // If the NT_CREATE_ANDX was to a downlevel server the access rights
  1376. // information is not available. Currently we default to maximum
  1377. // access for the current user and no access to other users in the
  1378. // disconnected mode for such files
  1379. smbSrvOpen->MaximalAccessRights = FILE_ALL_ACCESS;
  1380. smbSrvOpen->GuestMaximalAccessRights = 0;
  1381. if (Response->OplockLevel > SMB_OPLOCK_LEVEL_NONE) {
  1382. smbSrvOpen->FileStatusFlags = Response->FileStatusFlags;
  1383. smbSrvOpen->IsNtCreate = TRUE;
  1384. }
  1385. MRxSmbCreateFileSuccessTail (
  1386. RxContext,
  1387. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  1388. StorageType,
  1389. Fid,
  1390. OrdinaryExchange->ServerVersion,
  1391. Response->OplockLevel,
  1392. CreateAction,
  1393. pFileInfo
  1394. );
  1395. RxDbgTrace(-1, Dbg, ("MRxSmbFinishNTCreateAndX returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1396. return Status;
  1397. }
  1398. NTSTATUS
  1399. MRxSmbFinishOpenAndX (
  1400. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1401. PRESP_OPEN_ANDX Response
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. This routine actually gets the stuff out of the NTCreate_AndX response.
  1406. Arguments:
  1407. OrdinaryExchange - the exchange instance
  1408. Response - the response
  1409. Return Value:
  1410. NTSTATUS - The return status for the operation
  1411. --*/
  1412. {
  1413. NTSTATUS Status = STATUS_SUCCESS;
  1414. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1415. ULONG Disposition = RxContext->Create.NtCreateParameters.Disposition;
  1416. RxCaptureFcb;
  1417. RX_FILE_TYPE StorageType;
  1418. SMB_FILE_ID Fid;
  1419. UCHAR OplockLevel = SMB_OPLOCK_LEVEL_NONE;
  1420. ULONG CreateAction;
  1421. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1422. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1423. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1424. PAGED_CODE();
  1425. RxDbgTrace(+1, Dbg, ("MRxSmbFinishOpenAndX\n", 0 ));
  1426. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  1427. StorageType = RxInferFileType(RxContext);
  1428. if (StorageType == 0) {
  1429. StorageType = FileTypeFile;
  1430. RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
  1431. }
  1432. ASSERT (StorageType == FileTypeFile);
  1433. Fid = SmbGetUshort(&Response->Fid);
  1434. if (SmbGetUshort(&Response->Action) & SMB_OACT_OPLOCK) {
  1435. OplockLevel = SMB_OPLOCK_LEVEL_BATCH; //we only ever ask for batch currently!!!
  1436. }
  1437. CreateAction = MRxSmbUnmapDisposition(SmbGetUshort(&Response->Action),Disposition);
  1438. pFileInfo->Basic.FileAttributes =
  1439. MRxSmbMapSmbAttributes(SmbGetUshort(&Response->FileAttributes));
  1440. // This is a downlevel server, the access rights
  1441. // information is not available. Currently we default to maximum
  1442. // access for the current user and no access to other users in the
  1443. // disconnected mode for such files
  1444. smbSrvOpen->MaximalAccessRights = FILE_ALL_ACCESS;
  1445. smbSrvOpen->GuestMaximalAccessRights = 0;
  1446. MRxSmbSecondsSince1970ToTime(
  1447. SmbGetUlong(&Response->LastWriteTimeInSeconds),
  1448. SmbCeGetExchangeServer(OrdinaryExchange),
  1449. &pFileInfo->Basic.LastWriteTime);
  1450. pFileInfo->Standard.NumberOfLinks = 1;
  1451. pFileInfo->Basic.CreationTime.HighPart = 0;
  1452. pFileInfo->Basic.CreationTime.LowPart = 0;
  1453. pFileInfo->Basic.LastAccessTime.HighPart = 0;
  1454. pFileInfo->Basic.LastAccessTime.LowPart = 0;
  1455. pFileInfo->Basic.ChangeTime.HighPart = 0;
  1456. pFileInfo->Basic.ChangeTime.LowPart = 0;
  1457. pFileInfo->Standard.EndOfFile.HighPart = 0;
  1458. pFileInfo->Standard.EndOfFile.LowPart = SmbGetUlong(&Response->DataSize);
  1459. pFileInfo->Standard.AllocationSize.QuadPart = pFileInfo->Standard.EndOfFile.QuadPart;
  1460. pFileInfo->Standard.Directory = (StorageType == FileTypeDirectory);
  1461. MRxSmbCreateFileSuccessTail (
  1462. RxContext,
  1463. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  1464. StorageType,
  1465. Fid,
  1466. OrdinaryExchange->ServerVersion,
  1467. OplockLevel,
  1468. CreateAction,
  1469. pFileInfo );
  1470. RxDbgTrace(-1, Dbg, ("MRxSmbFinishOpenAndX returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1471. return Status;
  1472. }
  1473. NTSTATUS
  1474. MRxSmbFinishT2OpenFile (
  1475. IN OUT PRX_CONTEXT RxContext,
  1476. IN PRESP_OPEN2 Response,
  1477. IN OUT PBOOLEAN MustRegainExclusiveResource,
  1478. IN ULONG ServerVersion
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. This routine actually gets the stuff out of the T2/Open response.
  1483. Arguments:
  1484. RxContext - the context of the operation being performed
  1485. Response - the response
  1486. Return Value:
  1487. RXSTATUS - The return status for the operation
  1488. --*/
  1489. {
  1490. NTSTATUS Status = STATUS_SUCCESS;
  1491. RxCaptureFcb;
  1492. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1493. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1494. RX_FILE_TYPE StorageType;
  1495. SMB_FILE_ID Fid;
  1496. ULONG CreateAction;
  1497. ULONG Disposition = RxContext->Create.NtCreateParameters.Disposition;
  1498. ULONG FileAttributes;
  1499. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1500. PAGED_CODE();
  1501. RxDbgTrace(+1, Dbg, ("MRxSmbFinishT2OpenFile\n", 0 ));
  1502. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  1503. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  1504. FileAttributes = MRxSmbMapSmbAttributes(Response->FileAttributes);
  1505. StorageType = RxInferFileType(RxContext);
  1506. if (StorageType == 0) {
  1507. StorageType = (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1508. ? FileTypeDirectory
  1509. : FileTypeFile;
  1510. }
  1511. if ((capFcb->OpenCount != 0) &&
  1512. (StorageType != 0) &&
  1513. (NodeType(capFcb) != RDBSS_STORAGE_NTC(StorageType))) {
  1514. return STATUS_OBJECT_TYPE_MISMATCH;
  1515. }
  1516. Fid = Response->Fid;
  1517. CreateAction = MRxSmbUnmapDisposition(Response->Action,Disposition);
  1518. RxDbgTrace( 0, Dbg, ("Storagetype %08lx/Fid %08lx/Action %08lx\n", StorageType, Fid, CreateAction ));
  1519. if (Response->Action & SMB_OACT_OPLOCK) {
  1520. smbSrvOpen->OplockLevel = SMB_OPLOCK_LEVEL_BATCH; //we only ever ask for batch currently!!!
  1521. }
  1522. RxContext->Create.ReturnedCreateInformation = CreateAction;
  1523. if (capFcb->OpenCount == 0) {
  1524. //
  1525. // Please note that we mask off the low bit on the time stamp here.
  1526. //
  1527. // We do this since the time stamps returned from other smbs (notably SmbGetAttrE and
  1528. // T2QueryDirectory) have a granularity of 2 seconds, while this
  1529. // time stamp has a granularity of 1 second. In order to make these
  1530. // two times consistant, we mask off the low order second in the
  1531. // timestamp. this idea was lifted from rdr1.
  1532. //
  1533. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1534. pServerEntry = SmbCeReferenceAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1535. ASSERT(pServerEntry != NULL);
  1536. MRxSmbSecondsSince1970ToTime(Response->CreationTimeInSeconds&0xfffffffe,
  1537. &pServerEntry->Server,
  1538. &pFileInfo->Basic.CreationTime);
  1539. SmbCeDereferenceServerEntry(pServerEntry);
  1540. }
  1541. pFileInfo->Basic.FileAttributes = FileAttributes;
  1542. pFileInfo->Basic.LastAccessTime.QuadPart = 0;
  1543. pFileInfo->Basic.LastWriteTime.QuadPart = 0;
  1544. pFileInfo->Basic.ChangeTime.QuadPart = 0;
  1545. pFileInfo->Standard.NumberOfLinks = 1;
  1546. pFileInfo->Standard.AllocationSize.QuadPart =
  1547. pFileInfo->Standard.EndOfFile.QuadPart = Response->DataSize;
  1548. pFileInfo->Standard.Directory = (StorageType == FileTypeDirectory);
  1549. MRxSmbCreateFileSuccessTail(
  1550. RxContext,
  1551. MustRegainExclusiveResource,
  1552. StorageType,
  1553. Fid,
  1554. ServerVersion,
  1555. smbSrvOpen->OplockLevel,
  1556. CreateAction,
  1557. pFileInfo);
  1558. RxDbgTrace(-1, Dbg, ("MRxSmbFinishT2OpenFile returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1559. return Status;
  1560. }
  1561. //#define MULTI_EA_MDL
  1562. NTSTATUS
  1563. MRxSmbT2OpenFile(
  1564. IN OUT PRX_CONTEXT RxContext
  1565. )
  1566. /*++
  1567. Routine Description:
  1568. This routine opens a file across the network that has
  1569. 1) EAs,
  1570. 2) a name so long that it wont fit in an ordinary packet
  1571. We silently ignore it if SDs are specified.
  1572. Arguments:
  1573. RxContext - the RDBSS context
  1574. Return Value:
  1575. NTSTATUS - The return status for the operation
  1576. --*/
  1577. {
  1578. NTSTATUS Status;
  1579. RxCaptureFcb;
  1580. USHORT Setup = TRANS2_OPEN2;
  1581. BOOLEAN MustRegainExclusiveResource = FALSE;
  1582. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1583. SMB_TRANSACTION_SEND_PARAMETERS SendParameters;
  1584. SMB_TRANSACTION_RECEIVE_PARAMETERS ReceiveParameters;
  1585. SMB_TRANSACTION_OPTIONS TransactionOptions;
  1586. PREQ_OPEN2 pCreateRequest = NULL;
  1587. RESP_OPEN2 CreateResponse;
  1588. PBYTE SendParamsBuffer,ReceiveParamsBuffer;
  1589. ULONG SendParamsBufferLength,ReceiveParamsBufferLength;
  1590. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  1591. MRXSMB_CREATE_PARAMETERS SmbCp;
  1592. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  1593. USHORT smbDisposition;
  1594. USHORT smbSharingMode;
  1595. USHORT smbAttributes;
  1596. ULONG smbFileSize;
  1597. USHORT smbOpenMode;
  1598. USHORT OpenFlags = SMB_OPEN_QUERY_INFORMATION;
  1599. USHORT SearchAttributes = SMB_FILE_ATTRIBUTE_DIRECTORY | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN;
  1600. ULONG SecondsSince1970;
  1601. BOOLEAN IsUnicode;
  1602. ULONG OS2_EaLength = 0;
  1603. PFEALIST ServerEaList = NULL;
  1604. ULONG EaLength = RxContext->Create.EaLength;
  1605. PFILE_FULL_EA_INFORMATION EaBuffer = RxContext->Create.EaBuffer;
  1606. ULONG FileNameLength,AllocationLength;
  1607. PAGED_CODE();
  1608. RxDbgTrace(0, Dbg, ("MRxSmbT2Open---\n"));
  1609. DbgPrint("MRxSmbT2Open---%08lx %08lx\n",EaBuffer,EaLength);
  1610. MRxSmbAdjustCreateParameters(RxContext,&SmbCp);
  1611. FileNameLength = RemainingName->Length;
  1612. AllocationLength = WordAlign(FIELD_OFFSET(REQ_OPEN2,Buffer[0])) +
  1613. FileNameLength+sizeof(WCHAR);
  1614. pCreateRequest = (PREQ_OPEN2)
  1615. RxAllocatePoolWithTag(
  1616. PagedPool,
  1617. AllocationLength,
  1618. 'bmsX' );
  1619. if (pCreateRequest==NULL) {
  1620. RxDbgTrace(0, Dbg, (" --> Couldn't get the pCreateRequest!\n"));
  1621. Status = STATUS_INSUFFICIENT_RESOURCES;
  1622. goto FINALLY;
  1623. }
  1624. smbDisposition = MRxSmbMapDisposition(cp->Disposition);
  1625. smbSharingMode = MRxSmbMapShareAccess(((USHORT)cp->ShareAccess));
  1626. smbAttributes = MRxSmbMapFileAttributes(cp->FileAttributes);
  1627. smbFileSize = cp->AllocationSize.LowPart;
  1628. smbOpenMode = MRxSmbMapDesiredAccess(cp->DesiredAccess);
  1629. smbSharingMode |= smbOpenMode;
  1630. if (cp->CreateOptions & FILE_WRITE_THROUGH) {
  1631. smbSharingMode |= SMB_DA_WRITE_THROUGH;
  1632. }
  1633. if (capFcb->pNetRoot->Type == NET_ROOT_DISK) {
  1634. OpenFlags |= (SMB_OPEN_OPLOCK | SMB_OPEN_OPBATCH);
  1635. }
  1636. {
  1637. BOOLEAN GoodTime;
  1638. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1639. LARGE_INTEGER CurrentTime;
  1640. pServerEntry = SmbCeReferenceAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1641. ASSERT(pServerEntry != NULL);
  1642. IsUnicode = BooleanFlagOn(pServerEntry->Server.DialectFlags,DF_UNICODE);
  1643. KeQuerySystemTime(&CurrentTime);
  1644. GoodTime = MRxSmbTimeToSecondsSince1970(
  1645. &CurrentTime,
  1646. &pServerEntry->Server,
  1647. &SecondsSince1970
  1648. );
  1649. SmbCeDereferenceServerEntry(pServerEntry);
  1650. if (!GoodTime) {
  1651. SecondsSince1970 = 0;
  1652. }
  1653. }
  1654. pCreateRequest->Flags = OpenFlags; // Creation flags
  1655. pCreateRequest->DesiredAccess = smbSharingMode;
  1656. pCreateRequest->SearchAttributes = SearchAttributes;
  1657. pCreateRequest->FileAttributes = smbAttributes;
  1658. pCreateRequest->CreationTimeInSeconds = SecondsSince1970;
  1659. pCreateRequest->OpenFunction = smbDisposition;
  1660. pCreateRequest->AllocationSize = smbFileSize;
  1661. RtlZeroMemory(
  1662. &pCreateRequest->Reserved[0],
  1663. sizeof(pCreateRequest->Reserved));
  1664. {
  1665. NTSTATUS StringStatus;
  1666. PBYTE NameBuffer = &pCreateRequest->Buffer[0];
  1667. ULONG OriginalLengthRemaining = FileNameLength+sizeof(WCHAR);
  1668. ULONG LengthRemaining = OriginalLengthRemaining;
  1669. if (IsUnicode) {
  1670. StringStatus = SmbPutUnicodeString(&NameBuffer,RemainingName,&LengthRemaining);
  1671. } else {
  1672. StringStatus = SmbPutUnicodeStringAsOemString(&NameBuffer,RemainingName,&LengthRemaining);
  1673. DbgPrint("This is the name <%s>\n",&pCreateRequest->Buffer[0]);
  1674. }
  1675. ASSERT(StringStatus==STATUS_SUCCESS);
  1676. SendParamsBufferLength = FIELD_OFFSET(REQ_OPEN2,Buffer[0])
  1677. +OriginalLengthRemaining-LengthRemaining;
  1678. }
  1679. SendParamsBuffer = (PBYTE)pCreateRequest;
  1680. //SendParamsBufferLength = qweee;
  1681. ReceiveParamsBuffer = (PBYTE)&CreateResponse;
  1682. ReceiveParamsBufferLength = sizeof(CreateResponse);
  1683. if (EaLength!=0) {
  1684. //
  1685. // Convert Nt format FEALIST to OS/2 format
  1686. //
  1687. DbgPrint("MRxSmbT2Open again---%08lx %08lx\n",EaBuffer,EaLength);
  1688. OS2_EaLength = MRxSmbNtFullEaSizeToOs2 ( EaBuffer );
  1689. if ( OS2_EaLength > 0x0000ffff ) {
  1690. Status = STATUS_EA_TOO_LARGE;
  1691. goto FINALLY;
  1692. }
  1693. ServerEaList = RxAllocatePoolWithTag (PagedPool, OS2_EaLength, 'Ebms');
  1694. if ( ServerEaList == NULL ) {
  1695. Status = STATUS_INSUFFICIENT_RESOURCES;
  1696. goto FINALLY;
  1697. }
  1698. MRxSmbNtFullListToOs2 ( EaBuffer, ServerEaList );
  1699. } else {
  1700. OS2_EaLength = 0;
  1701. ServerEaList = NULL;
  1702. }
  1703. RxDbgTrace(0, Dbg, ("MRxSmbT2Open---os2ea %d buf %x\n", OS2_EaLength,ServerEaList));
  1704. DbgPrint("MRxSmbT2Open OS2 eastuff---%08lx %08lx\n",ServerEaList,OS2_EaLength);
  1705. TransactionOptions = RxDefaultTransactionOptions;
  1706. TransactionOptions.Flags |= SMB_XACT_FLAGS_FID_NOT_NEEDED;
  1707. if (BooleanFlagOn(capFcb->pNetRoot->Flags,NETROOT_FLAG_DFS_AWARE_NETROOT) &&
  1708. (RxContext->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT))) {
  1709. TransactionOptions.Flags |= SMB_XACT_FLAGS_DFS_AWARE;
  1710. }
  1711. ASSERT (MrxSmbCreateTransactPacketSize>=100); //don't try something strange
  1712. TransactionOptions.MaximumTransmitSmbBufferSize = MrxSmbCreateTransactPacketSize;
  1713. RxReleaseFcbResourceInMRx( capFcb );
  1714. MustRegainExclusiveResource = TRUE;
  1715. Status = SmbCeTransact(
  1716. RxContext,
  1717. &TransactionOptions,
  1718. &Setup,
  1719. sizeof(Setup),
  1720. NULL,
  1721. 0,
  1722. SendParamsBuffer,
  1723. SendParamsBufferLength,
  1724. ReceiveParamsBuffer,
  1725. ReceiveParamsBufferLength,
  1726. ServerEaList,
  1727. OS2_EaLength,
  1728. NULL,
  1729. 0,
  1730. &ResumptionContext);
  1731. if (NT_SUCCESS(Status)) {
  1732. MRxSmbFinishT2OpenFile (
  1733. RxContext,
  1734. &CreateResponse,
  1735. &MustRegainExclusiveResource,
  1736. ResumptionContext.ServerVersion);
  1737. if (cp->Disposition == FILE_OPEN) {
  1738. MRxSmbAdjustReturnedCreateAction(RxContext);
  1739. }
  1740. }
  1741. FINALLY:
  1742. ASSERT (Status != (STATUS_PENDING));
  1743. if (pCreateRequest != NULL) {
  1744. RxFreePool(pCreateRequest);
  1745. }
  1746. if (ServerEaList != NULL) {
  1747. RxFreePool(ServerEaList);
  1748. }
  1749. if (MustRegainExclusiveResource) {
  1750. //this is required because of oplock breaks
  1751. RxAcquireExclusiveFcbResourceInMRx(capFcb );
  1752. }
  1753. RxDbgTraceUnIndent(-1,Dbg);
  1754. return Status;
  1755. }
  1756. NTSTATUS
  1757. MRxSmbFinishLongNameCreateFile (
  1758. IN OUT PRX_CONTEXT RxContext,
  1759. IN PRESP_CREATE_WITH_SD_OR_EA Response,
  1760. IN PBOOLEAN MustRegainExclusiveResource,
  1761. IN ULONG ServerVersion
  1762. )
  1763. /*++
  1764. Routine Description:
  1765. This routine actually gets the stuff out of the NTTransact/NTCreateWithEAsOrSDs response.
  1766. Arguments:
  1767. RxContext - the context of the operation being performed
  1768. Response - the response
  1769. Return Value:
  1770. RXSTATUS - The return status for the operation
  1771. --*/
  1772. {
  1773. NTSTATUS Status = STATUS_SUCCESS;
  1774. RxCaptureFcb;
  1775. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1776. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1777. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)SrvOpen->pVNetRoot->Context;
  1778. RX_FILE_TYPE StorageType;
  1779. SMB_FILE_ID Fid;
  1780. ULONG CreateAction;
  1781. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1782. FCB_INIT_PACKET InitPacket;
  1783. PAGED_CODE();
  1784. RxDbgTrace(+1, Dbg, ("MRxSmbFinishLongNameCreateFile\n", 0 ));
  1785. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  1786. ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  1787. if (RxContext->Create.NtCreateParameters.CreateOptions & FILE_DELETE_ON_CLOSE) {
  1788. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  1789. SetFlag((smbFcb)->MFlags,SMB_FCB_FLAG_SENT_DISPOSITION_INFO);
  1790. }
  1791. StorageType = RxInferFileType(RxContext);
  1792. if (StorageType == 0) {
  1793. StorageType = Response->Directory
  1794. ?FileTypeDirectory
  1795. :FileTypeFile;
  1796. RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
  1797. }
  1798. if ((capFcb->OpenCount != 0) &&
  1799. (StorageType != 0) &&
  1800. (NodeType(capFcb) != RDBSS_STORAGE_NTC(StorageType))) {
  1801. return STATUS_OBJECT_TYPE_MISMATCH;
  1802. }
  1803. Fid = SmbGetUshort(&Response->Fid);
  1804. CreateAction = SmbGetUlong(&Response->CreateAction);
  1805. pFileInfo->Basic.FileAttributes = Response->FileAttributes;
  1806. pFileInfo->Basic.CreationTime = Response->CreationTime;
  1807. pFileInfo->Basic.LastAccessTime = Response->LastAccessTime;
  1808. pFileInfo->Basic.LastWriteTime = Response->LastWriteTime;
  1809. pFileInfo->Basic.ChangeTime = Response->ChangeTime;
  1810. pFileInfo->Standard.NumberOfLinks = 1;
  1811. pFileInfo->Standard.AllocationSize = Response->AllocationSize;
  1812. pFileInfo->Standard.EndOfFile = Response->EndOfFile;
  1813. pFileInfo->Standard.Directory = Response->Directory;
  1814. if (((pFileInfo->Standard.AllocationSize.HighPart == pFileInfo->Standard.EndOfFile.HighPart) &&
  1815. (pFileInfo->Standard.AllocationSize.LowPart < pFileInfo->Standard.EndOfFile.LowPart)) ||
  1816. (pFileInfo->Standard.AllocationSize.HighPart < pFileInfo->Standard.EndOfFile.HighPart)) {
  1817. pFileInfo->Standard.AllocationSize = pFileInfo->Standard.EndOfFile;
  1818. }
  1819. smbSrvOpen->MaximalAccessRights = (USHORT)0x1ff;
  1820. smbSrvOpen->GuestMaximalAccessRights = (USHORT)0;
  1821. MRxSmbCreateFileSuccessTail(
  1822. RxContext,
  1823. MustRegainExclusiveResource,
  1824. StorageType,
  1825. Fid,
  1826. ServerVersion,
  1827. Response->OplockLevel,
  1828. CreateAction,
  1829. pFileInfo);
  1830. RxDbgTrace(-1, Dbg, ("MRxSmbFinishLongNameCreateFile returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1831. return Status;
  1832. }
  1833. //force_t2_open doesn't work on an NT server......sigh........
  1834. #define ForceT2Open FALSE
  1835. NTSTATUS
  1836. MRxSmbCreateWithEasSidsOrLongName (
  1837. IN OUT PRX_CONTEXT RxContext
  1838. )
  1839. /*++
  1840. Routine Description:
  1841. This routine opens a file across the network that has
  1842. 1) EAs,
  1843. 2) SIDs, or
  1844. 3) a name so long that it wont fit in an ordinary packet
  1845. Arguments:
  1846. RxContext - the RDBSS context
  1847. Return Value:
  1848. RXSTATUS - The return status for the operation
  1849. --*/
  1850. {
  1851. NTSTATUS Status;
  1852. RxCaptureFcb;
  1853. BOOLEAN MustRegainExclusiveResource = FALSE;
  1854. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1855. SMB_TRANSACTION_SEND_PARAMETERS SendParameters;
  1856. SMB_TRANSACTION_RECEIVE_PARAMETERS ReceiveParameters;
  1857. SMB_TRANSACTION_OPTIONS TransactionOptions;
  1858. PREQ_CREATE_WITH_SD_OR_EA pCreateRequest = NULL;
  1859. PBYTE SendParamsBuffer,ReceiveParamsBuffer,SendDataBuffer;
  1860. ULONG SendParamsBufferLength,ReceiveParamsBufferLength,SendDataBufferLength;
  1861. PRESP_CREATE_WITH_SD_OR_EA CreateResponse;
  1862. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1863. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  1864. MRXSMB_CREATE_PARAMETERS SmbCp;
  1865. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  1866. ULONG EaLength,SdLength,PadLength,TotalLength;
  1867. PBYTE CombinedBuffer = NULL;
  1868. #ifdef MULTI_EA_MDL
  1869. PRX_BUFFER EaMdl2 = NULL;
  1870. PRX_BUFFER EaMdl3 = NULL;
  1871. #endif
  1872. PMDL EaMdl = NULL;
  1873. PMDL SdMdl = NULL; BOOLEAN SdMdlLocked = FALSE;
  1874. PMDL PadMdl = NULL;
  1875. PMDL DataMdl = NULL;
  1876. ULONG FileNameLength,AllocationLength;
  1877. PAGED_CODE();
  1878. RxDbgTrace(0, Dbg, ("!!MRxSmbCreateWithEasSidsOrLongName---\n"));
  1879. {
  1880. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1881. BOOLEAN DoesNtSmbs;
  1882. pServerEntry = SmbCeReferenceAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1883. ASSERT(pServerEntry != NULL);
  1884. DoesNtSmbs = BooleanFlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS);
  1885. SmbCeDereferenceServerEntry(pServerEntry);
  1886. if (!DoesNtSmbs || ForceT2Open) {
  1887. Status = MRxSmbT2OpenFile(RxContext);
  1888. if (ForceT2Open && (Status!=STATUS_SUCCESS)) {
  1889. DbgPrint("BadStatus = %08lx\n",Status);
  1890. }
  1891. return(Status);
  1892. }
  1893. }
  1894. MRxSmbAdjustCreateParameters(RxContext,&SmbCp);
  1895. RxDbgTrace(0, Dbg, ("MRxSmbCreateWithEasSidsOrLongName---\n"));
  1896. FileNameLength = RemainingName->Length;
  1897. AllocationLength = WordAlign(FIELD_OFFSET(REQ_CREATE_WITH_SD_OR_EA,Buffer[0]))
  1898. +FileNameLength;
  1899. pCreateRequest = (PREQ_CREATE_WITH_SD_OR_EA)RxAllocatePoolWithTag( PagedPool,
  1900. AllocationLength,'bmsX' );
  1901. if (pCreateRequest==NULL) {
  1902. RxDbgTrace(0, Dbg, (" --> Couldn't get the pCreateRequest!\n"));
  1903. Status = STATUS_INSUFFICIENT_RESOURCES;
  1904. goto FINALLY;
  1905. }
  1906. RtlCopyMemory((PBYTE)WordAlignPtr(&pCreateRequest->Buffer[0]),RemainingName->Buffer,FileNameLength);
  1907. EaLength = RxContext->Create.EaLength;
  1908. SdLength = RxContext->Create.SdLength;
  1909. pCreateRequest->Flags = 0; //norelopen // Optional directory for relative open
  1910. pCreateRequest->RootDirectoryFid = 0; //norelopen // Optional directory for relative open
  1911. pCreateRequest->DesiredAccess = cp->DesiredAccess; // Desired access (NT format)
  1912. pCreateRequest->AllocationSize = cp->AllocationSize; // The initial allocation size in bytes
  1913. pCreateRequest->FileAttributes = cp->FileAttributes; // The file attributes
  1914. pCreateRequest->ShareAccess = cp->ShareAccess; // The share access
  1915. pCreateRequest->CreateDisposition = cp->Disposition; // Action to take if file exists or not
  1916. pCreateRequest->CreateOptions = cp->CreateOptions; // Options for creating a new file
  1917. pCreateRequest->SecurityDescriptorLength = SdLength; // Length of SD in bytes
  1918. pCreateRequest->EaLength = EaLength; // Length of EA in bytes
  1919. pCreateRequest->NameLength = FileNameLength; // Length of name in characters
  1920. pCreateRequest->ImpersonationLevel = cp->ImpersonationLevel; // Security QOS information
  1921. pCreateRequest->SecurityFlags = SmbCp.SecurityFlags; // Security QOS information
  1922. // UCHAR Buffer[1];
  1923. // //UCHAR Name[]; // The name of the file (not NUL terminated)
  1924. SendParamsBuffer = (PBYTE)pCreateRequest;
  1925. SendParamsBufferLength = AllocationLength;
  1926. ReceiveParamsBuffer = (PBYTE)&CreateResponse;
  1927. ReceiveParamsBufferLength = sizeof(CreateResponse);
  1928. if ((EaLength==0)||(SdLength==0)) {
  1929. PadLength = 0;
  1930. if (EaLength) {
  1931. // the EaBuffer is in nonpaged pool...so we dont lock or unlock
  1932. PBYTE EaBuffer = RxContext->Create.EaBuffer;
  1933. #ifdef MULTI_EA_MDL
  1934. ULONG EaLength0,EaLength2,EaLength3;
  1935. PBYTE EaBuffer2,EaBuffer3;
  1936. ASSERT(EaLength>11);
  1937. RxDbgTrace(0, Dbg, ("MRxSmbCreateWithEasSidsOrLongName--MULTIEAMDL\n"));
  1938. EaLength0 = (EaLength - 4)>>1;
  1939. EaBuffer2 = EaBuffer + EaLength0;
  1940. EaLength2 = 4;
  1941. EaBuffer3 = EaBuffer2 + EaLength2;
  1942. EaLength3 = EaLength - (EaBuffer3 - EaBuffer);
  1943. EaMdl = RxAllocateMdl(EaBuffer,EaLength0);
  1944. EaMdl2 = RxAllocateMdl(EaBuffer2,EaLength2);
  1945. EaMdl3 = RxAllocateMdl(EaBuffer3,EaLength3);
  1946. if ( (EaMdl==NULL) || (EaMdl2==NULL) || (EaMdl3==NULL) ) {
  1947. Status = STATUS_INSUFFICIENT_RESOURCES;
  1948. goto FINALLY;
  1949. }
  1950. MmBuildMdlForNonPagedPool(EaMdl);
  1951. MmBuildMdlForNonPagedPool(EaMdl2);
  1952. MmBuildMdlForNonPagedPool(EaMdl3);
  1953. EaMdl3->Next = NULL;
  1954. EaMdl2->Next = EaMdl3;
  1955. EaMdl->Next = EaMdl2;
  1956. #else
  1957. EaMdl = RxAllocateMdl(EaBuffer,EaLength);
  1958. if (EaMdl == NULL) {
  1959. Status = STATUS_INSUFFICIENT_RESOURCES;
  1960. goto FINALLY;
  1961. }
  1962. MmBuildMdlForNonPagedPool(EaMdl);
  1963. EaMdl->Next = NULL;
  1964. #endif
  1965. DataMdl = EaMdl;
  1966. }
  1967. if (SdLength) {
  1968. SdMdl = RxAllocateMdl(cp->SecurityContext->AccessState->SecurityDescriptor,SdLength);
  1969. if (SdMdl == NULL) {
  1970. Status = STATUS_INSUFFICIENT_RESOURCES;
  1971. } else {
  1972. RxProbeAndLockPages(SdMdl,KernelMode,IoModifyAccess,Status);
  1973. }
  1974. if (!NT_SUCCESS(Status)) goto FINALLY;
  1975. SdMdlLocked = TRUE;
  1976. PadLength = LongAlign(SdLength) - SdLength;
  1977. if (PadLength && EaLength) {
  1978. PadMdl = RxAllocateMdl(0,(sizeof(DWORD) + PAGE_SIZE - 1));
  1979. if (PadMdl == NULL) {
  1980. Status = STATUS_INSUFFICIENT_RESOURCES;
  1981. goto FINALLY;
  1982. }
  1983. RxBuildPaddingPartialMdl(PadMdl,PadLength);
  1984. PadMdl->Next = DataMdl;
  1985. DataMdl = PadMdl;
  1986. }
  1987. SdMdl->Next = DataMdl;
  1988. DataMdl = SdMdl;
  1989. }
  1990. } else {
  1991. ULONG EaOffset = LongAlign(SdLength);
  1992. ULONG CombinedBufferLength = EaOffset + EaLength;
  1993. CombinedBuffer = RxAllocatePoolWithTag(PagedPool,CombinedBufferLength,'bms');
  1994. if (CombinedBuffer==NULL) {
  1995. Status = STATUS_INSUFFICIENT_RESOURCES;
  1996. goto FINALLY;
  1997. }
  1998. SdMdl = RxAllocateMdl(CombinedBuffer,CombinedBufferLength);
  1999. if (SdMdl == NULL) {
  2000. Status = STATUS_INSUFFICIENT_RESOURCES;
  2001. } else {
  2002. RxProbeAndLockPages(SdMdl,KernelMode,IoModifyAccess,Status);
  2003. }
  2004. if (!NT_SUCCESS(Status)) goto FINALLY;
  2005. SdMdlLocked = TRUE;
  2006. RtlCopyMemory(CombinedBuffer,cp->SecurityContext->AccessState->SecurityDescriptor,SdLength);
  2007. RtlZeroMemory(CombinedBuffer+SdLength,EaOffset-SdLength);
  2008. RtlCopyMemory(CombinedBuffer+EaOffset,RxContext->Create.EaBuffer,EaLength);
  2009. DataMdl = SdMdl;
  2010. }
  2011. RxDbgTrace(0, Dbg, ("MRxSmbCreateWithEasSidsOrLongName---s,p,ea %d,%d,%d buf %x\n",
  2012. SdLength,PadLength,EaLength,RxContext->Create.EaBuffer));
  2013. TransactionOptions = RxDefaultTransactionOptions;
  2014. TransactionOptions.NtTransactFunction = NT_TRANSACT_CREATE;
  2015. TransactionOptions.Flags |= SMB_XACT_FLAGS_FID_NOT_NEEDED;
  2016. //dfs is only for nt servers........
  2017. //if (BooleanFlagOn(capFcb->pNetRoot->Flags,NETROOT_FLAG_DFS_AWARE_NETROOT)
  2018. // && (RxContext->Create.NtCreateParameters.DfsContext == (PVOID)DFS_OPEN_CONTEXT)) {
  2019. // TransactionOptions.Flags |= SMB_XACT_FLAGS_DFS_AWARE;
  2020. //}
  2021. ASSERT (MrxSmbCreateTransactPacketSize>=100); //don't try something strange
  2022. TransactionOptions.MaximumTransmitSmbBufferSize = MrxSmbCreateTransactPacketSize;
  2023. if (DataMdl!=NULL) {
  2024. SendDataBuffer = MmGetSystemAddressForMdlSafe(DataMdl,LowPagePriority);
  2025. if (SendDataBuffer == NULL) {
  2026. Status = STATUS_INSUFFICIENT_RESOURCES;
  2027. goto FINALLY;
  2028. }
  2029. SendDataBufferLength = EaLength+SdLength+PadLength;
  2030. } else {
  2031. SendDataBuffer = NULL;
  2032. SendDataBufferLength = 0;
  2033. }
  2034. RxReleaseFcbResourceInMRx(capFcb );
  2035. MustRegainExclusiveResource = TRUE;
  2036. Status = SmbCeTransact(
  2037. RxContext,
  2038. &TransactionOptions,
  2039. NULL,
  2040. 0,
  2041. NULL,
  2042. 0,
  2043. SendParamsBuffer,
  2044. SendParamsBufferLength,
  2045. ReceiveParamsBuffer,
  2046. ReceiveParamsBufferLength,
  2047. SendDataBuffer,
  2048. SendDataBufferLength,
  2049. NULL,
  2050. 0,
  2051. &ResumptionContext);
  2052. if (NT_SUCCESS(Status)) {
  2053. MRxSmbFinishLongNameCreateFile (
  2054. RxContext,
  2055. (PRESP_CREATE_WITH_SD_OR_EA)&CreateResponse,
  2056. &MustRegainExclusiveResource,
  2057. ResumptionContext.ServerVersion);
  2058. if (cp->Disposition == FILE_OPEN) {
  2059. MRxSmbAdjustReturnedCreateAction(RxContext);
  2060. }
  2061. }
  2062. FINALLY:
  2063. ASSERT (Status != (STATUS_PENDING));
  2064. if (SdMdlLocked) MmUnlockPages(SdMdl);
  2065. if (EaMdl != NULL) { IoFreeMdl(EaMdl); }
  2066. #ifdef MULTI_EA_MDL
  2067. if (EaMdl2 != NULL) { IoFreeMdl(EaMdl2); }
  2068. if (EaMdl3 != NULL) { IoFreeMdl(EaMdl3); }
  2069. #endif
  2070. if (PadMdl != NULL) { IoFreeMdl(PadMdl); }
  2071. if (SdMdl != NULL) { IoFreeMdl(SdMdl); }
  2072. if (pCreateRequest != NULL) {
  2073. RxFreePool(pCreateRequest);
  2074. }
  2075. if (CombinedBuffer != NULL) {
  2076. RxFreePool(CombinedBuffer);
  2077. }
  2078. if (MustRegainExclusiveResource) {
  2079. //this is required because of oplock breaks
  2080. RxAcquireExclusiveFcbResourceInMRx(capFcb );
  2081. }
  2082. RxDbgTraceUnIndent(-1,Dbg);
  2083. return Status;
  2084. }
  2085. NTSTATUS
  2086. MRxSmbZeroExtend(
  2087. IN PRX_CONTEXT pRxContext)
  2088. /*++
  2089. Routine Description:
  2090. This routine extends the data stream of a file system object
  2091. Arguments:
  2092. pRxContext - the RDBSS context
  2093. Return Value:
  2094. RXSTATUS - The return status for the operation
  2095. --*/
  2096. {
  2097. return STATUS_NOT_IMPLEMENTED;
  2098. }
  2099. NTSTATUS
  2100. MRxSmbTruncate(
  2101. IN PRX_CONTEXT pRxContext)
  2102. /*++
  2103. Routine Description:
  2104. This routine truncates the contents of a file system object
  2105. Arguments:
  2106. pRxContext - the RDBSS context
  2107. Return Value:
  2108. RXSTATUS - The return status for the operation
  2109. --*/
  2110. {
  2111. ASSERT(!"Found a truncate");
  2112. return STATUS_NOT_IMPLEMENTED;
  2113. }
  2114. NTSTATUS
  2115. MRxSmbCleanupFobx(
  2116. IN PRX_CONTEXT RxContext)
  2117. /*++
  2118. Routine Description:
  2119. This routine cleansup a file system object...normally a noop.
  2120. Arguments:
  2121. pRxContext - the RDBSS context
  2122. Return Value:
  2123. RXSTATUS - The return status for the operation
  2124. --*/
  2125. {
  2126. PUNICODE_STRING RemainingName;
  2127. RxCaptureFcb;
  2128. RxCaptureFobx;
  2129. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  2130. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  2131. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2132. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  2133. PSMBCEDB_SERVER_ENTRY pServerEntry;
  2134. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  2135. PAGED_CODE();
  2136. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  2137. ASSERT ( NodeTypeIsFcb(capFcb) );
  2138. RxDbgTrace(+1, Dbg, ("MRxSmbCleanup\n", 0 ));
  2139. MRxSmbDeallocateSideBuffer(RxContext,smbFobx,"Cleanup");
  2140. if (FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED)) {
  2141. RxDbgTrace(-1, Dbg, ("File orphaned\n"));
  2142. } else {
  2143. RxDbgTrace(-1, Dbg, ("File not for closing at cleanup\n"));
  2144. }
  2145. return (STATUS_SUCCESS);
  2146. }
  2147. NTSTATUS
  2148. MRxSmbForcedClose(
  2149. IN PMRX_SRV_OPEN pSrvOpen)
  2150. /*++
  2151. Routine Description:
  2152. This routine closes a file system object
  2153. Arguments:
  2154. pSrvOpen - the instance to be closed
  2155. Return Value:
  2156. RXSTATUS - The return status for the operation
  2157. Notes:
  2158. --*/
  2159. {
  2160. PAGED_CODE();
  2161. return STATUS_NOT_IMPLEMENTED;
  2162. }
  2163. #undef Dbg
  2164. #define Dbg (DEBUG_TRACE_CLOSE)
  2165. NTSTATUS
  2166. MRxSmbCloseSrvOpen(
  2167. IN PRX_CONTEXT RxContext
  2168. )
  2169. /*++
  2170. Routine Description:
  2171. This routine closes a file across the network
  2172. Arguments:
  2173. RxContext - the RDBSS context
  2174. Return Value:
  2175. NTSTATUS - The return status for the operation
  2176. --*/
  2177. {
  2178. NTSTATUS Status = STATUS_SUCCESS;
  2179. PUNICODE_STRING RemainingName;
  2180. RxCaptureFcb;
  2181. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  2182. RxCaptureFobx;
  2183. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  2184. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  2185. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2186. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  2187. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)(capFcb->pNetRoot->pSrvCall->Context);
  2188. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  2189. BOOLEAN NeedDelete;
  2190. BOOLEAN SearchHandleOpen = FALSE;
  2191. PAGED_CODE();
  2192. ASSERT ( NodeTypeIsFcb(capFcb) );
  2193. RxDbgTrace(+1, Dbg, ("MRxSmbClose\n", 0 ));
  2194. if (TypeOfOpen==RDBSS_NTC_STORAGE_TYPE_DIRECTORY) {
  2195. SearchHandleOpen = BooleanFlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN);
  2196. MRxSmbDeallocateSideBuffer(RxContext,smbFobx,"Close");
  2197. if (smbFobx->Enumeration.ResumeInfo!=NULL) {
  2198. RxFreePool(smbFobx->Enumeration.ResumeInfo);
  2199. smbFobx->Enumeration.ResumeInfo = NULL;
  2200. }
  2201. }
  2202. if (!smbSrvOpen->DeferredOpenInProgress &&
  2203. smbSrvOpen->DeferredOpenContext != NULL) {
  2204. RxFreePool(smbSrvOpen->DeferredOpenContext);
  2205. smbSrvOpen->DeferredOpenContext = NULL;
  2206. RxDbgTrace(0, Dbg, ("Free deferred open context for file %wZ %lX\n",GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),smbSrvOpen));
  2207. }
  2208. //Remove the open context from the list if it is a paging file
  2209. if (FlagOn( capFcb->FcbState, FCB_STATE_PAGING_FILE )) {
  2210. PLIST_ENTRY pListHead = &MRxSmbPagingFilesSrvOpenList;
  2211. PLIST_ENTRY pListEntry = pListHead->Flink;
  2212. ASSERT(FALSE);
  2213. while (pListEntry != pListHead) {
  2214. PPAGING_FILE_CONTEXT PagingFileContext;
  2215. PagingFileContext = (PPAGING_FILE_CONTEXT)CONTAINING_RECORD(pListEntry,PAGING_FILE_CONTEXT,ContextList);
  2216. if (PagingFileContext->pSrvOpen == SrvOpen) {
  2217. RemoveEntryList(pListEntry);
  2218. break;
  2219. }
  2220. }
  2221. }
  2222. if (FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED)) {
  2223. RxDbgTrace(-1, Dbg, ("File orphan\n"));
  2224. goto FINALLY;
  2225. }
  2226. if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_FILE_RENAMED) ||
  2227. FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_FILE_DELETED) ){
  2228. RxDbgTrace(-1, Dbg, ("File already closed by ren/del\n"));
  2229. goto FINALLY;
  2230. }
  2231. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  2232. if (smbSrvOpen->Fid == 0xffff) {
  2233. // File has already been closed on the server.
  2234. goto FINALLY;
  2235. }
  2236. NeedDelete = FlagOn(capFcb->FcbState,FCB_STATE_DELETE_ON_CLOSE) && (capFcb->OpenCount == 0);
  2237. if (!NeedDelete &&
  2238. !SearchHandleOpen &&
  2239. FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)){
  2240. RxDbgTrace(-1, Dbg, ("File was not really open\n"));
  2241. goto FINALLY;
  2242. }
  2243. if (smbSrvOpen->Version == pServerEntry->Server.Version) {
  2244. Status = SmbPseCreateOrdinaryExchange(
  2245. RxContext,
  2246. SrvOpen->pVNetRoot,
  2247. SMBPSE_OE_FROM_CLOSESRVCALL,
  2248. SmbPseExchangeStart_Close,
  2249. &OrdinaryExchange
  2250. );
  2251. if (Status != STATUS_SUCCESS) {
  2252. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  2253. goto FINALLY;
  2254. }
  2255. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  2256. ASSERT (Status != (STATUS_PENDING));
  2257. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  2258. }
  2259. RxDbgTrace(-1, Dbg, ("MRxSmbClose exit with status=%08lx\n", Status ));
  2260. FINALLY:
  2261. if (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN) &&
  2262. (pServerEntry != NULL)) {
  2263. MRxSmbDecrementSrvOpenCount(
  2264. pServerEntry,
  2265. smbSrvOpen->Version,
  2266. SrvOpen);
  2267. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  2268. }
  2269. return(Status);
  2270. }
  2271. NTSTATUS
  2272. MRxSmbBuildClose (
  2273. PSMBSTUFFER_BUFFER_STATE StufferState
  2274. )
  2275. /*++
  2276. Routine Description:
  2277. This builds a Close SMB. we don't have to worry about login id and such
  2278. since that is done by the connection engine....pretty neat huh? all we have to do
  2279. is to format up the bits.
  2280. Arguments:
  2281. StufferState - the state of the smbbuffer from the stuffer's point of view
  2282. Return Value:
  2283. RXSTATUS
  2284. SUCCESS
  2285. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  2286. Notes:
  2287. --*/
  2288. {
  2289. NTSTATUS Status;
  2290. PRX_CONTEXT RxContext = StufferState->RxContext;
  2291. RxCaptureFcb;
  2292. RxCaptureFobx;
  2293. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  2294. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2295. PAGED_CODE();
  2296. RxDbgTrace(+1, Dbg, ("MRxSmbBuildClose\n", 0 ));
  2297. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  2298. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse, SMB_COM_CLOSE,
  2299. SMB_REQUEST_SIZE(CLOSE),
  2300. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  2301. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  2302. );
  2303. MRxSmbDumpStufferState (1100,"SMB w/ CLOSE before stuffing",StufferState);
  2304. MRxSmbStuffSMB (StufferState,
  2305. "0wdB!",
  2306. // 0 UCHAR WordCount; // Count of parameter words = 3
  2307. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  2308. 0xffffffff, // d _ULONG( LastWriteTimeInSeconds ); // Time of last write, low and high
  2309. SMB_WCT_CHECK(3) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
  2310. // UCHAR Buffer[1]; // empty
  2311. );
  2312. MRxSmbDumpStufferState (700,"SMB w/ close after stuffing",StufferState);
  2313. FINALLY:
  2314. RxDbgTraceUnIndent(-1,Dbg);
  2315. return(Status);
  2316. }
  2317. NTSTATUS
  2318. MRxSmbBuildFindClose (
  2319. PSMBSTUFFER_BUFFER_STATE StufferState
  2320. )
  2321. /*++
  2322. Routine Description:
  2323. This builds a Close SMB. we don't have to worry about login id and such
  2324. since that is done by the connection engine....pretty neat huh? all we have to do
  2325. is to format up the bits.
  2326. Arguments:
  2327. StufferState - the state of the smbbuffer from the stuffer's point of view
  2328. Return Value:
  2329. RXSTATUS
  2330. SUCCESS
  2331. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  2332. Notes:
  2333. --*/
  2334. {
  2335. NTSTATUS Status;
  2336. PRX_CONTEXT RxContext = StufferState->RxContext;
  2337. RxCaptureFcb;RxCaptureFobx;
  2338. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  2339. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  2340. PAGED_CODE();
  2341. RxDbgTrace(+1, Dbg, ("MRxSmbBuildFindClose\n", 0 ));
  2342. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse, SMB_COM_FIND_CLOSE2,
  2343. SMB_REQUEST_SIZE(FIND_CLOSE2),
  2344. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  2345. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  2346. );
  2347. MRxSmbDumpStufferState (1100,"SMB w/ CLOSE before stuffing",StufferState);
  2348. MRxSmbStuffSMB (StufferState,
  2349. "0wB!",
  2350. // 0 UCHAR WordCount; // Count of parameter words = 1
  2351. // w _USHORT( Sid ); // Find handle
  2352. smbFobx->Enumeration.SearchHandle,
  2353. SMB_WCT_CHECK(1) 0 // B! _USHORT( ByteCount ); // Count of data bytes = 0
  2354. // UCHAR Buffer[1]; // empty
  2355. );
  2356. MRxSmbDumpStufferState (700,"SMB w/ FindClose2 after stuffing",StufferState);
  2357. FINALLY:
  2358. RxDbgTraceUnIndent(-1,Dbg);
  2359. return(Status);
  2360. }
  2361. NTSTATUS
  2362. MRxSmbCoreDeleteForSupercedeOrClose(
  2363. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  2364. BOOLEAN DeleteDirectory
  2365. );
  2366. NTSTATUS
  2367. SmbPseExchangeStart_Close(
  2368. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  2369. )
  2370. /*++
  2371. Routine Description:
  2372. This is the start routine for close.
  2373. Arguments:
  2374. pExchange - the exchange instance
  2375. Return Value:
  2376. RXSTATUS - The return status for the operation
  2377. --*/
  2378. {
  2379. NTSTATUS Status = STATUS_SUCCESS;
  2380. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  2381. RxCaptureFcb;
  2382. RxCaptureFobx;
  2383. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  2384. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
  2385. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2386. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  2387. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  2388. PSMBCEDB_SERVER_ENTRY pServerEntry= SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  2389. PAGED_CODE();
  2390. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_Close\n", 0 ));
  2391. ASSERT(OrdinaryExchange->Type == ORDINARY_EXCHANGE);
  2392. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  2393. if(TypeOfOpen==RDBSS_NTC_STORAGE_TYPE_DIRECTORY){
  2394. if (FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN)) {
  2395. // we have a search handle open.....close it
  2396. Status = MRxSmbBuildFindClose(StufferState);
  2397. if (Status == STATUS_SUCCESS) {
  2398. PSMBCE_SERVER pServer;
  2399. // Ensure that the searchhandle is valid
  2400. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  2401. if (smbFobx->Enumeration.Version == pServer->Version) {
  2402. NTSTATUS InnerStatus;
  2403. InnerStatus = SmbPseOrdinaryExchange(
  2404. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  2405. SMBPSE_OETYPE_FINDCLOSE
  2406. );
  2407. }
  2408. }
  2409. // if this didn't work, there's nothing you can do............
  2410. ClearFlag(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN);
  2411. ClearFlag(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST);
  2412. }
  2413. }
  2414. if (OrdinaryExchange->EntryPoint == SMBPSE_OE_FROM_CLEANUPFOBX) {
  2415. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Close exit after searchhandle close %08lx\n", Status ));
  2416. return Status;
  2417. }
  2418. if ( !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN) ) {
  2419. //even if it didn't work there's nothing i can do......keep going
  2420. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN);
  2421. MRxSmbDecrementSrvOpenCount(pServerEntry,pServerEntry->Server.Version,SrvOpen);
  2422. Status = MRxSmbBuildClose(StufferState);
  2423. if (Status == STATUS_SUCCESS) {
  2424. // Ensure that the Fid is validated
  2425. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID);
  2426. Status = SmbPseOrdinaryExchange(
  2427. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  2428. SMBPSE_OETYPE_CLOSE
  2429. );
  2430. // Ensure that the Fid validation is disabled
  2431. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID);
  2432. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_WRITE_ONLY_HANDLE)) {
  2433. smbFcb->WriteOnlySrvOpenCount--;
  2434. }
  2435. }
  2436. }
  2437. if ((Status!=STATUS_SUCCESS) ||
  2438. (capFcb->OpenCount > 0) ||
  2439. !FlagOn(capFcb->FcbState,FCB_STATE_DELETE_ON_CLOSE)) {
  2440. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Close exit w %08lx\n", Status ));
  2441. return Status;
  2442. }
  2443. RxDbgTrace(0, Dbg, ("SmbPseExchangeStart_Close delete on close\n" ));
  2444. if ( !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_FILE_DELETED)) {
  2445. if (!FlagOn(smbFcb->MFlags,SMB_FCB_FLAG_SENT_DISPOSITION_INFO)) {
  2446. //no need for setinitsmb here because coredelete does a init-on-resuse.....
  2447. //it's not good to pass the name this way...........
  2448. OrdinaryExchange->pPathArgument1 = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  2449. Status = MRxSmbCoreDeleteForSupercedeOrClose(
  2450. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  2451. ((BOOLEAN)( NodeType(capFcb)==RDBSS_NTC_STORAGE_TYPE_DIRECTORY )));
  2452. if (Status == STATUS_FILE_IS_A_DIRECTORY) {
  2453. Status = MRxSmbCoreDeleteForSupercedeOrClose(
  2454. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  2455. TRUE);
  2456. }
  2457. } else {
  2458. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_FILE_DELETED);
  2459. }
  2460. }
  2461. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Close exit w %08lx\n", Status ));
  2462. return Status;
  2463. }
  2464. NTSTATUS
  2465. MRxSmbFinishClose (
  2466. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  2467. PRESP_CLOSE Response
  2468. )
  2469. /*++
  2470. Routine Description:
  2471. This routine actually gets the stuff out of the Close response and finishes
  2472. the close.
  2473. Arguments:
  2474. OrdinaryExchange - the exchange instance
  2475. Response - the response
  2476. Return Value:
  2477. NTSTATUS - The return status for the operation
  2478. --*/
  2479. {
  2480. NTSTATUS Status = STATUS_SUCCESS;
  2481. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  2482. RxCaptureFcb;
  2483. RxCaptureFobx;
  2484. PAGED_CODE();
  2485. RxDbgTrace(+1, Dbg, ("MRxSmbFinishClose\n", 0 ));
  2486. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishClose:");
  2487. if (Response->WordCount != 0 ||
  2488. SmbGetUshort(&Response->ByteCount) !=0) {
  2489. Status = STATUS_INVALID_NETWORK_RESPONSE;
  2490. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  2491. } else {
  2492. if (OrdinaryExchange->OEType == SMBPSE_OETYPE_CLOSE) {
  2493. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  2494. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  2495. smbSrvOpen->Fid = 0xffff;
  2496. }
  2497. }
  2498. RxDbgTrace(-1, Dbg, ("MRxSmbFinishClose returning %08lx\n", Status ));
  2499. return Status;
  2500. }
  2501. BOOLEAN
  2502. MRxSmbIsStreamFile(
  2503. PUNICODE_STRING FileName,
  2504. PUNICODE_STRING AdjustFileName
  2505. )
  2506. /*++
  2507. Routine Description:
  2508. This routine checks if it is a stream file and return the root file name if true.
  2509. Arguments:
  2510. FileName - the file name needs to be parsed
  2511. AdjustFileName - the file name contains only root name of the stream
  2512. Return Value:
  2513. BOOLEAN - stream file
  2514. --*/
  2515. {
  2516. USHORT i;
  2517. BOOLEAN IsStream = FALSE;
  2518. NTSTATUS Status = STATUS_SUCCESS;
  2519. for (i=0;i<FileName->Length/sizeof(WCHAR);i++) {
  2520. if (FileName->Buffer[i] == L':') {
  2521. IsStream = TRUE;
  2522. break;
  2523. }
  2524. }
  2525. if (AdjustFileName != NULL) {
  2526. if (IsStream) {
  2527. AdjustFileName->Length =
  2528. AdjustFileName->MaximumLength = i * sizeof(WCHAR);
  2529. AdjustFileName->Buffer = FileName->Buffer;
  2530. } else {
  2531. AdjustFileName->Length =
  2532. AdjustFileName->MaximumLength = 0;
  2533. AdjustFileName->Buffer = NULL;
  2534. }
  2535. }
  2536. return IsStream;
  2537. }