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.

972 lines
39 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 Microsoft Corporation
  3. Module Name:
  4. locks.c
  5. Abstract:
  6. This module implements the mini redirector call down routines pertaining to locks
  7. of file system objects.
  8. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. #pragma warning(error:4101) // Unreferenced local variable
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE, MRxSmbLocks)
  14. #pragma alloc_text(PAGE, MRxSmbBuildLocksAndX)
  15. #pragma alloc_text(PAGE, MRxSmbBuildLockAssert)
  16. #pragma alloc_text(PAGE, SmbPseExchangeStart_Locks)
  17. #pragma alloc_text(PAGE, MRxSmbFinishLocks)
  18. #pragma alloc_text(PAGE, MRxSmbUnlockRoutine)
  19. #pragma alloc_text(PAGE, MRxSmbCompleteBufferingStateChangeRequest)
  20. #pragma alloc_text(PAGE, MRxSmbBuildFlush)
  21. #pragma alloc_text(PAGE, MRxSmbFlush)
  22. #pragma alloc_text(PAGE, MRxSmbIsLockRealizable)
  23. #pragma alloc_text(PAGE, MRxSmbFinishFlush)
  24. #endif
  25. //
  26. // The local debug trace level
  27. //
  28. #define Dbg (DEBUG_TRACE_LOCKCTRL)
  29. NTSTATUS
  30. SmbPseExchangeStart_Locks(
  31. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  32. );
  33. ULONG MRxSmbSrvLockBufSize = 0xffff;
  34. ULONG MRxSmbLockSendOptions = 0; //use the default options
  35. NTSTATUS
  36. MRxSmbBuildFlush (
  37. PSMBSTUFFER_BUFFER_STATE StufferState
  38. );
  39. NTSTATUS
  40. MRxSmbLocks(
  41. IN PRX_CONTEXT RxContext)
  42. /*++
  43. Routine Description:
  44. This routine handles network requests for filelocks
  45. Arguments:
  46. RxContext - the RDBSS context
  47. Return Value:
  48. RXSTATUS - The return status for the operation
  49. --*/
  50. {
  51. NTSTATUS Status = STATUS_SUCCESS;
  52. RxCaptureFcb;
  53. RxCaptureFobx;
  54. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  55. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  56. PAGED_CODE();
  57. RxDbgTrace(+1, Dbg, ("MRxSmbLocks\n", 0 ));
  58. ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN );
  59. Status = SmbPseCreateOrdinaryExchange(RxContext,
  60. SrvOpen->pVNetRoot,
  61. SMBPSE_OE_FROM_LOCKS,
  62. SmbPseExchangeStart_Locks,
  63. &OrdinaryExchange
  64. );
  65. if (Status != STATUS_SUCCESS) {
  66. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  67. return(Status);
  68. }
  69. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  70. if (Status!=STATUS_PENDING) {
  71. BOOLEAN FinalizationComplete = SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  72. ASSERT(FinalizationComplete);
  73. }
  74. RxDbgTrace(-1, Dbg, ("MRxSmbLocks exit with status=%08lx\n", Status ));
  75. return(Status);
  76. }
  77. NTSTATUS
  78. MRxSmbBuildLocksAndX (
  79. PSMBSTUFFER_BUFFER_STATE StufferState
  80. )
  81. /*++
  82. Routine Description:
  83. This builds a LockingAndX SMB for a single unlock or a single lock.
  84. Arguments:
  85. StufferState - the state of the smbbuffer from the stuffer's point of view
  86. Return Value:
  87. RXSTATUS
  88. SUCCESS
  89. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  90. Notes:
  91. --*/
  92. {
  93. NTSTATUS Status;
  94. PRX_CONTEXT RxContext = StufferState->RxContext;
  95. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  96. RxCaptureFcb;RxCaptureFobx;
  97. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = (PSMB_PSE_ORDINARY_EXCHANGE)StufferState->Exchange;
  98. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(StufferState->Exchange);
  99. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  100. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  101. PLARGE_INTEGER ByteOffsetAsLI,LengthAsLI;
  102. USHORT NumberOfLocks,NumberOfUnlocks;
  103. BOOLEAN UseLockList = FALSE;
  104. //ULONG OffsetLow,OffsetHigh;
  105. PAGED_CODE();
  106. RxDbgTrace(+1, Dbg, ("MRxSmbBuildLocksAndX\n"));
  107. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  108. switch (LowIoContext->Operation) {
  109. case LOWIO_OP_SHAREDLOCK:
  110. case LOWIO_OP_EXCLUSIVELOCK:
  111. NumberOfLocks = 1; NumberOfUnlocks = 0;
  112. break;
  113. case LOWIO_OP_UNLOCK:
  114. NumberOfLocks = 0; NumberOfUnlocks = 1;
  115. break;
  116. case LOWIO_OP_UNLOCK_MULTIPLE:
  117. NumberOfLocks = 0; NumberOfUnlocks = 1;
  118. UseLockList = TRUE;
  119. break;
  120. }
  121. if (!UseLockList) {
  122. ByteOffsetAsLI = (PLARGE_INTEGER)&LowIoContext->ParamsFor.Locks.ByteOffset;
  123. LengthAsLI = (PLARGE_INTEGER)&LowIoContext->ParamsFor.Locks.Length;
  124. } else {
  125. //it's okay that this code is big.....see the C.I. above
  126. PSMB_PSE_OE_READWRITE rw = &OrdinaryExchange->ReadWrite;
  127. PLOWIO_LOCK_LIST LockList = rw->LockList;
  128. ByteOffsetAsLI = (PLARGE_INTEGER)&LockList->ByteOffset;
  129. LengthAsLI = (PLARGE_INTEGER)&LockList->Length;
  130. RxDbgTrace(0, Dbg, ("MRxSmbBuildLocksAndX using locklist, byteoffptr,lengthptr=%08lx,%08lx\n",
  131. ByteOffsetAsLI, LengthAsLI ));
  132. //DbgBreakPoint();
  133. }
  134. if (FlagOn(pServer->DialectFlags,DF_LANMAN20)) {
  135. ULONG SharedLock = (LowIoContext->Operation==LOWIO_OP_SHAREDLOCK);
  136. ULONG Timeout = (LowIoContext->ParamsFor.Locks.Flags&LOWIO_LOCKSFLAG_FAIL_IMMEDIATELY)?0:0xffffffff;
  137. ULONG UseLargeOffsets = LOCKING_ANDX_LARGE_FILES;
  138. if (!FlagOn(pServer->DialectFlags,DF_NT_SMBS)) {
  139. UseLargeOffsets = 0;
  140. }
  141. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never, SMB_COM_LOCKING_ANDX,
  142. SMB_REQUEST_SIZE(LOCKING_ANDX),
  143. NO_EXTRA_DATA,NO_SPECIAL_ALIGNMENT,RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  144. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  145. );
  146. MRxSmbDumpStufferState (1000,"SMB w/ NTLOCKS&X before stuffing",StufferState);
  147. MRxSmbStuffSMB (StufferState,
  148. "XwwDwwB?",
  149. // X UCHAR WordCount; // Count of parameter words = 8
  150. // UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
  151. // UCHAR AndXReserved; // Reserved (must be 0)
  152. // _USHORT( AndXOffset ); // Offset to next command WordCount
  153. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  154. //
  155. // //
  156. // // When NT protocol is not negotiated the OplockLevel field is
  157. // // omitted, and LockType field is a full word. Since the upper
  158. // // bits of LockType are never used, this definition works for
  159. // // all protocols.
  160. // //
  161. //
  162. SharedLock // w UCHAR( LockType ); // Locking mode:
  163. +UseLargeOffsets,
  164. // // bit 0: 0 = lock out all access
  165. // // 1 = read OK while locked
  166. // // bit 1: 1 = 1 user total file unlock
  167. // UCHAR( OplockLevel ); // The new oplock level
  168. SMB_OFFSET_CHECK(LOCKING_ANDX,Timeout)
  169. Timeout, // D _ULONG( Timeout );
  170. NumberOfUnlocks, // w _USHORT( NumberOfUnlocks ); // Num. unlock range structs following
  171. NumberOfLocks, // w _USHORT( NumberOfLocks ); // Num. lock range structs following
  172. SMB_WCT_CHECK(8) 0
  173. // B? _USHORT( ByteCount ); // Count of data bytes
  174. // UCHAR Buffer[1]; // Buffer containing:
  175. // //LOCKING_ANDX_RANGE Unlocks[]; // Unlock ranges
  176. // //LOCKING_ANDX_RANGE Locks[]; // Lock ranges
  177. );
  178. if (UseLargeOffsets) {
  179. //NTversion
  180. MRxSmbStuffSMB (StufferState,
  181. "wwdddd!",
  182. // typedef struct _NT_LOCKING_ANDX_RANGE {
  183. MRXSMB_PROCESS_ID , // w _USHORT( Pid ); // PID of process "owning" lock
  184. 0, // w _USHORT( Pad ); // Pad to DWORD align (mbz)
  185. ByteOffsetAsLI->HighPart,// d _ULONG( OffsetHigh ); // Ofset to bytes to [un]lock (high)
  186. ByteOffsetAsLI->LowPart, // d _ULONG( OffsetLow ); // Ofset to bytes to [un]lock (low)
  187. LengthAsLI->HighPart, // d _ULONG( LengthHigh ); // Number of bytes to [un]lock (high)
  188. LengthAsLI->LowPart // d _ULONG( LengthLow ); // Number of bytes to [un]lock (low)
  189. // } NTLOCKING_ANDX_RANGE;
  190. );
  191. } else {
  192. MRxSmbStuffSMB (StufferState,
  193. "wdd!",
  194. MRXSMB_PROCESS_ID , // typedef struct _LOCKING_ANDX_RANGE {
  195. // w _USHORT( Pid ); // PID of process "owning" lock
  196. // d _ULONG( Offset ); // Ofset to bytes to [un]lock
  197. ByteOffsetAsLI->LowPart,
  198. // d _ULONG( Length ); // Number of bytes to [un]lock
  199. LengthAsLI->LowPart
  200. // } LOCKING_ANDX_RANGE;
  201. );
  202. }
  203. MRxSmbDumpStufferState (700,"SMB w/ NTLOCKS&X after stuffing",StufferState);
  204. } else {
  205. //lockbyterange and unlockbyterange have the same format......
  206. COVERED_CALL(MRxSmbStartSMBCommand ( StufferState, SetInitialSMB_Never,
  207. (UCHAR)((NumberOfLocks==0)?SMB_COM_UNLOCK_BYTE_RANGE
  208. :SMB_COM_LOCK_BYTE_RANGE),
  209. SMB_REQUEST_SIZE(LOCK_BYTE_RANGE),
  210. NO_EXTRA_DATA,NO_SPECIAL_ALIGNMENT,RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  211. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  212. );
  213. MRxSmbDumpStufferState (1000,"SMB w/ corelocking before stuffing",StufferState);
  214. ASSERT(ByteOffsetAsLI->HighPart==0);
  215. ASSERT(LengthAsLI->HighPart==0);
  216. MRxSmbStuffSMB (StufferState,
  217. "0wddB!",
  218. // 0 UCHAR WordCount; // Count of parameter words = 5
  219. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  220. LengthAsLI->LowPart, // d _ULONG( Count ); // Count of bytes to lock
  221. ByteOffsetAsLI->LowPart, // d _ULONG( Offset ); // Offset from start of file
  222. // B! _USHORT( ByteCount ); // Count of data bytes = 0
  223. SMB_WCT_CHECK(5) 0
  224. // UCHAR Buffer[1]; // empty
  225. );
  226. MRxSmbDumpStufferState (700,"SMB w/ corelocking after stuffing",StufferState);
  227. }
  228. FINALLY:
  229. RxDbgTraceUnIndent(-1, Dbg);
  230. return(Status);
  231. }
  232. NTSTATUS
  233. MRxSmbBuildLockAssert (
  234. PSMBSTUFFER_BUFFER_STATE StufferState
  235. )
  236. /*++
  237. Routine Description:
  238. This builds a LockingAndX SMB for multiple locks by calling the lock enumerator.
  239. Arguments:
  240. StufferState - the state of the smbbuffer from the stuffer's point of view
  241. Return Value:
  242. RXSTATUS
  243. SUCCESS
  244. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  245. --*/
  246. {
  247. NTSTATUS Status;
  248. PRX_CONTEXT RxContext = StufferState->RxContext;
  249. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  250. RxCaptureFcb;RxCaptureFobx;
  251. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = (PSMB_PSE_ORDINARY_EXCHANGE)StufferState->Exchange;
  252. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(StufferState->Exchange);
  253. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  254. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  255. PRX_LOCK_ENUMERATOR LockEnumerator = OrdinaryExchange->AssertLocks.LockEnumerator;
  256. ULONG UseLargeOffsets;
  257. BOOLEAN LocksExclusiveForThisPacket = TRUE;
  258. PBYTE PtrToLockCount;
  259. PAGED_CODE();
  260. RxDbgTrace(+1, Dbg, ("MRxSmbBuildLockAssert enum=%08lx\n",LockEnumerator));
  261. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  262. if (smbSrvOpen->Fid == 0xffff) {
  263. return STATUS_FILE_CLOSED;
  264. }
  265. RxDbgTrace(0,Dbg,("Oplock response for FID(%lx)\n",smbSrvOpen->Fid));
  266. UseLargeOffsets = FlagOn(pServer->DialectFlags,DF_NT_SMBS)?LOCKING_ANDX_LARGE_FILES:0;
  267. //UseLargeOffsets = FALSE;
  268. OrdinaryExchange->AssertLocks.NumberOfLocksPlaced = 0;
  269. for (;;) {
  270. ASSERT_ORDINARY_EXCHANGE ( OrdinaryExchange );
  271. RxDbgTrace(0, Dbg, ("top of loop %08lx %08lx %08lx\n",
  272. OrdinaryExchange->AssertLocks.NumberOfLocksPlaced,
  273. OrdinaryExchange->AssertLocks.LockAreaNonEmpty,
  274. OrdinaryExchange->AssertLocks.EndOfListReached
  275. ));
  276. if (!OrdinaryExchange->AssertLocks.EndOfListReached
  277. && !OrdinaryExchange->AssertLocks.LockAreaNonEmpty) {
  278. //get a new lock
  279. //DbgBreakPoint();
  280. if (LockEnumerator(
  281. OrdinaryExchange->AssertLocks.SrvOpen,
  282. &OrdinaryExchange->AssertLocks.ContinuationHandle,
  283. &OrdinaryExchange->AssertLocks.NextLockOffset,
  284. &OrdinaryExchange->AssertLocks.NextLockRange,
  285. &OrdinaryExchange->AssertLocks.NextLockIsExclusive
  286. )){
  287. OrdinaryExchange->AssertLocks.LockAreaNonEmpty = TRUE;
  288. } else {
  289. OrdinaryExchange->AssertLocks.LockAreaNonEmpty = FALSE;
  290. OrdinaryExchange->AssertLocks.EndOfListReached = TRUE;
  291. OrdinaryExchange->AssertLocks.NextLockIsExclusive = TRUE;
  292. }
  293. }
  294. RxDbgTrace(0, Dbg, ("got a lockorempty %08lx %08lx %08lx\n",
  295. OrdinaryExchange->AssertLocks.NumberOfLocksPlaced,
  296. OrdinaryExchange->AssertLocks.LockAreaNonEmpty,
  297. OrdinaryExchange->AssertLocks.EndOfListReached
  298. ));
  299. //DbgBreakPoint();
  300. if (OrdinaryExchange->AssertLocks.NumberOfLocksPlaced == 0){
  301. ULONG Timeout = 0xffffffff;
  302. ULONG SharedLock = !OrdinaryExchange->AssertLocks.NextLockIsExclusive;
  303. LocksExclusiveForThisPacket = OrdinaryExchange->AssertLocks.NextLockIsExclusive;
  304. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_Never, SMB_COM_LOCKING_ANDX,
  305. SMB_REQUEST_SIZE(LOCKING_ANDX),
  306. NO_EXTRA_DATA,NO_SPECIAL_ALIGNMENT,RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  307. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  308. );
  309. MRxSmbDumpStufferState (1000,"SMB w/ NTLOCKS&X(assertbuf) before stuffing",StufferState);
  310. MRxSmbStuffSMB (StufferState,
  311. "XwrwDwrwB?",
  312. // X UCHAR WordCount; // Count of parameter words = 8
  313. // UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
  314. // UCHAR AndXReserved; // Reserved (must be 0)
  315. // _USHORT( AndXOffset ); // Offset to next command WordCount
  316. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  317. //
  318. // //
  319. // // When NT protocol is not negotiated the OplockLevel field is
  320. // // omitted, and LockType field is a full word. Since the upper
  321. // // bits of LockType are never used, this definition works for
  322. // // all protocols.
  323. // //
  324. //
  325. // rw UCHAR( LockType ); // Locking mode:
  326. &OrdinaryExchange->AssertLocks.PtrToLockType,0,
  327. SharedLock+UseLargeOffsets,
  328. // // bit 0: 0 = lock out all access
  329. // // 1 = read OK while locked
  330. // // bit 1: 1 = 1 user total file unlock
  331. // UCHAR( OplockLevel ); // The new oplock level
  332. SMB_OFFSET_CHECK(LOCKING_ANDX,Timeout)
  333. Timeout, // D _ULONG( Timeout );
  334. 0, // w _USHORT( NumberOfUnlocks ); // Num. unlock range structs following
  335. // rw _USHORT( NumberOfLocks ); // Num. lock range structs following
  336. &PtrToLockCount,0,
  337. 0,
  338. SMB_WCT_CHECK(8) 0
  339. // B? _USHORT( ByteCount ); // Count of data bytes
  340. // UCHAR Buffer[1]; // Buffer containing:
  341. // //LOCKING_ANDX_RANGE Unlocks[]; // Unlock ranges
  342. // //LOCKING_ANDX_RANGE Locks[]; // Lock ranges
  343. );
  344. ASSERT_ORDINARY_EXCHANGE ( OrdinaryExchange );
  345. RxDbgTrace(0, Dbg, ("PTRS %08lx %08lx\n",
  346. OrdinaryExchange->AssertLocks.PtrToLockType,
  347. PtrToLockCount
  348. ));
  349. }
  350. if (OrdinaryExchange->AssertLocks.EndOfListReached
  351. || (LocksExclusiveForThisPacket != OrdinaryExchange->AssertLocks.NextLockIsExclusive)
  352. || (OrdinaryExchange->AssertLocks.NumberOfLocksPlaced >= 20)
  353. // the lock limit will have to take cognizance of the remaining space in the buffer. this will be
  354. // different depending on whether a full buffer is used or a vestigial buffer. SO, this cannot just
  355. // be turned into another constant
  356. ){
  357. break;
  358. }
  359. ASSERT_ORDINARY_EXCHANGE ( OrdinaryExchange );
  360. if (UseLargeOffsets) {
  361. MRxSmbStuffSMB (StufferState,
  362. "wwdddd?",
  363. // typedef struct _NT_LOCKING_ANDX_RANGE {
  364. MRXSMB_PROCESS_ID , // w _USHORT( Pid ); // PID of process "owning" lock
  365. 0, // w _USHORT( Pad ); // Pad to DWORD align (mbz)
  366. // d _ULONG( OffsetHigh ); // Ofset to bytes to [un]lock (high)
  367. OrdinaryExchange->AssertLocks.NextLockOffset.HighPart,
  368. // d _ULONG( OffsetLow ); // Ofset to bytes to [un]lock (low)
  369. OrdinaryExchange->AssertLocks.NextLockOffset.LowPart,
  370. // d _ULONG( LengthHigh ); // Number of bytes to [un]lock (high)
  371. OrdinaryExchange->AssertLocks.NextLockRange.HighPart,
  372. // d _ULONG( LengthLow ); // Number of bytes to [un]lock (low)
  373. OrdinaryExchange->AssertLocks.NextLockRange.LowPart,
  374. // } NTLOCKING_ANDX_RANGE;
  375. 0
  376. );
  377. } else {
  378. MRxSmbStuffSMB (StufferState,
  379. "wdd?",
  380. MRXSMB_PROCESS_ID , // typedef struct _LOCKING_ANDX_RANGE {
  381. // w _USHORT( Pid ); // PID of process "owning" lock
  382. // d _ULONG( Offset ); // Ofset to bytes to [un]lock
  383. OrdinaryExchange->AssertLocks.NextLockOffset.LowPart,
  384. // d _ULONG( Length ); // Number of bytes to [un]lock
  385. OrdinaryExchange->AssertLocks.NextLockRange.LowPart,
  386. // } LOCKING_ANDX_RANGE;
  387. 0
  388. );
  389. }
  390. ASSERT_ORDINARY_EXCHANGE ( OrdinaryExchange );
  391. OrdinaryExchange->AssertLocks.NumberOfLocksPlaced += 1;
  392. SmbPutUshort(PtrToLockCount, (USHORT)(OrdinaryExchange->AssertLocks.NumberOfLocksPlaced));
  393. OrdinaryExchange->AssertLocks.LockAreaNonEmpty = FALSE;
  394. ASSERT_ORDINARY_EXCHANGE ( OrdinaryExchange );
  395. }
  396. MRxSmbStuffSMB (StufferState, "!", 0); //fill in the bytecount
  397. MRxSmbDumpStufferState (700,"SMB w/ NTLOCKS&X(assertingbuffered) after stuffing",StufferState);
  398. FINALLY:
  399. RxDbgTraceUnIndent(-1, Dbg);
  400. return(Status);
  401. }
  402. NTSTATUS
  403. SmbPseExchangeStart_Locks(
  404. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  405. )
  406. /*++
  407. Routine Description:
  408. This is the start routine for locks AND for flush.
  409. Arguments:
  410. pExchange - the exchange instance
  411. Return Value:
  412. RXSTATUS - The return status for the operation
  413. --*/
  414. {
  415. NTSTATUS Status;
  416. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  417. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  418. ULONG StartEntryCount;
  419. SMB_PSE_ORDINARY_EXCHANGE_TYPE OEType;
  420. PSMB_PSE_OE_READWRITE rw = &OrdinaryExchange->ReadWrite;
  421. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  422. RxCaptureFcb; RxCaptureFobx;
  423. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  424. BOOLEAN SynchronousIo = !BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION);
  425. PAGED_CODE();
  426. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_Locks\n", 0 ));
  427. ASSERT(OrdinaryExchange->Type == ORDINARY_EXCHANGE);
  428. ASSERT( (OrdinaryExchange->SmbCeFlags&SMBCE_EXCHANGE_ATTEMPT_RECONNECTS) == 0 );
  429. OrdinaryExchange->StartEntryCount++;
  430. StartEntryCount = OrdinaryExchange->StartEntryCount;
  431. // Ensure that the Fid is validated
  432. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID);
  433. for (;;) {
  434. switch (OrdinaryExchange->OpSpecificState) {
  435. case SmbPseOEInnerIoStates_Initial:
  436. OrdinaryExchange->OpSpecificState = SmbPseOEInnerIoStates_ReadyToSend;
  437. if (!SynchronousIo) {
  438. OrdinaryExchange->AsyncResumptionRoutine = SmbPseExchangeStart_Locks;
  439. }
  440. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  441. rw->LockList = LowIoContext->ParamsFor.Locks.LockList;
  442. //lack of break is intentional
  443. case SmbPseOEInnerIoStates_ReadyToSend:
  444. OrdinaryExchange->OpSpecificState = SmbPseOEInnerIoStates_OperationOutstanding;
  445. OrdinaryExchange->SendOptions = MRxSmbLockSendOptions;
  446. switch (OrdinaryExchange->EntryPoint) {
  447. case SMBPSE_OE_FROM_FLUSH:
  448. OEType = SMBPSE_OETYPE_FLUSH;
  449. COVERED_CALL(MRxSmbBuildFlush(StufferState));
  450. break;
  451. case SMBPSE_OE_FROM_ASSERTBUFFEREDLOCKS:
  452. OEType = SMBPSE_OETYPE_ASSERTBUFFEREDLOCKS;
  453. COVERED_CALL(MRxSmbBuildLockAssert(StufferState));
  454. if ((OrdinaryExchange->AssertLocks.EndOfListReached)
  455. && (OrdinaryExchange->AssertLocks.NumberOfLocksPlaced == 0) ) {
  456. OrdinaryExchange->SendOptions = RXCE_SEND_SYNCHRONOUS;
  457. OrdinaryExchange->SmbCeFlags |= SMBCE_EXCHANGE_MID_VALID;
  458. OrdinaryExchange->Mid = SMBCE_OPLOCK_RESPONSE_MID;
  459. OrdinaryExchange->Flags |= SMBPSE_OE_FLAG_NO_RESPONSE_EXPECTED;
  460. *(OrdinaryExchange->AssertLocks.PtrToLockType) |= 2;
  461. }
  462. break;
  463. case SMBPSE_OE_FROM_LOCKS:
  464. OEType = SMBPSE_OETYPE_LOCKS;
  465. switch (LowIoContext->Operation) {
  466. case LOWIO_OP_SHAREDLOCK:
  467. case LOWIO_OP_EXCLUSIVELOCK:
  468. ASSERT (MRxSmbIsLockRealizable(
  469. capFcb,
  470. (PLARGE_INTEGER)&LowIoContext->ParamsFor.Locks.ByteOffset,
  471. (PLARGE_INTEGER)&LowIoContext->ParamsFor.Locks.Length,
  472. LowIoContext->ParamsFor.Locks.Flags
  473. )
  474. == STATUS_SUCCESS);
  475. //lack of break is intentional...........
  476. case LOWIO_OP_UNLOCK:
  477. rw->LockList = NULL;
  478. COVERED_CALL(MRxSmbBuildLocksAndX(StufferState));
  479. break;
  480. case LOWIO_OP_UNLOCK_MULTIPLE: {
  481. RxDbgTrace(0, Dbg, ("--->in locks_start, remaining locklist=%08lx\n", rw->LockList));
  482. ASSERT( rw->LockList != NULL );
  483. COVERED_CALL(MRxSmbBuildLocksAndX(StufferState));
  484. break;
  485. }
  486. default:
  487. ASSERT(!"Bad lowio op for locks\n");
  488. Status = STATUS_NOT_IMPLEMENTED;
  489. goto FINALLY;
  490. }
  491. break;
  492. default:
  493. ASSERT(!"Bad entrypoint for locks_start\n");
  494. Status = STATUS_NOT_IMPLEMENTED;
  495. goto FINALLY;
  496. }
  497. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  498. OEType
  499. );
  500. if (Status==STATUS_PENDING) {
  501. ASSERT(!SynchronousIo);
  502. goto FINALLY;
  503. }
  504. //lack of break is intentional
  505. case SmbPseOEInnerIoStates_OperationOutstanding:
  506. OrdinaryExchange->OpSpecificState = SmbPseOEInnerIoStates_ReadyToSend;
  507. Status = OrdinaryExchange->SmbStatus;
  508. switch (OrdinaryExchange->EntryPoint) {
  509. case SMBPSE_OE_FROM_FLUSH:
  510. goto FINALLY;
  511. //break;
  512. case SMBPSE_OE_FROM_ASSERTBUFFEREDLOCKS:
  513. if ((OrdinaryExchange->AssertLocks.EndOfListReached)
  514. && (OrdinaryExchange->AssertLocks.NumberOfLocksPlaced == 0) ) {
  515. goto FINALLY;
  516. }
  517. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0));
  518. break;
  519. case SMBPSE_OE_FROM_LOCKS:
  520. // if the locklist is empty. we can get out. this can happen either because we're not using
  521. // the locklist OR because we advance to the end of the list. that's why there are two checks
  522. if (rw->LockList == NULL) goto FINALLY;
  523. rw->LockList = rw->LockList->Next;
  524. if (rw->LockList == 0) goto FINALLY;
  525. if (Status != STATUS_SUCCESS) { goto FINALLY; }
  526. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0));
  527. break;
  528. //default:
  529. // ASSERT(!"Bad entrypoint for locks_start\n");
  530. // Status = RxStatus(NOT_IMPLEMENTED);
  531. // goto FINALLY;
  532. }
  533. break;
  534. }
  535. }
  536. FINALLY:
  537. if ( Status != STATUS_PENDING ) {
  538. SmbPseAsyncCompletionIfNecessary(OrdinaryExchange,RxContext);
  539. }
  540. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_Locks exit w %08lx\n", Status ));
  541. return Status;
  542. }
  543. NTSTATUS
  544. MRxSmbFinishLocks (
  545. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  546. PRESP_LOCKING_ANDX Response
  547. )
  548. /*++
  549. Routine Description:
  550. This routine actually gets the stuff out of the Close response and finishes the locks.
  551. Arguments:
  552. OrdinaryExchange - the exchange instance
  553. Response - the response
  554. Return Value:
  555. RXSTATUS - The return status for the operation
  556. --*/
  557. {
  558. NTSTATUS Status = STATUS_SUCCESS;
  559. PAGED_CODE();
  560. RxDbgTrace(+1, Dbg, ("MRxSmbFinishLocks\n"));
  561. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishLocks:");
  562. if (Response->WordCount != 2) {
  563. Status = STATUS_INVALID_NETWORK_RESPONSE;
  564. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  565. }
  566. RxDbgTrace(-1, Dbg, ("MRxSmbFinishLocks returning %08lx\n", Status ));
  567. return Status;
  568. }
  569. NTSTATUS
  570. MRxSmbCompleteBufferingStateChangeRequest(
  571. IN OUT PRX_CONTEXT RxContext,
  572. IN OUT PMRX_SRV_OPEN SrvOpen,
  573. IN PVOID pContext
  574. )
  575. /*++
  576. Routine Description:
  577. This routine is called to assert the locks that the wrapper has buffered. currently, it is synchronous!
  578. Arguments:
  579. RxContext - the open instance
  580. SrvOpen - tells which fcb is to be used.
  581. LockEnumerator - the routine to call to get the locks
  582. Return Value:
  583. RXSTATUS - The return status for the operation
  584. --*/
  585. {
  586. NTSTATUS Status = STATUS_SUCCESS;
  587. PSMBSTUFFER_BUFFER_STATE StufferState = NULL;
  588. PMRX_FCB Fcb = SrvOpen->pFcb;
  589. PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(Fcb);
  590. USHORT NewOplockLevel = (USHORT)(pContext);
  591. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  592. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  593. PAGED_CODE();
  594. RxDbgTrace(+1, Dbg, ("MRxSmbCompleteBufferingStateChangeRequest\n", 0 ));
  595. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  596. RxDbgTrace(0,Dbg,("@@@@@@ Old Level (%lx) to New Level %lx @@@@\n",smbSrvOpen->OplockLevel,NewOplockLevel));
  597. smbFcb->LastOplockLevel = NewOplockLevel;
  598. if ((smbSrvOpen->OplockLevel == SMB_OPLOCK_LEVEL_II) &&
  599. (NewOplockLevel == SMB_OPLOCK_LEVEL_NONE)) {
  600. return STATUS_SUCCESS;
  601. }
  602. smbSrvOpen->OplockLevel = (UCHAR)NewOplockLevel;
  603. Status = SmbPseCreateOrdinaryExchange(RxContext,
  604. SrvOpen->pVNetRoot,
  605. SMBPSE_OE_FROM_ASSERTBUFFEREDLOCKS,
  606. SmbPseExchangeStart_Locks,
  607. &OrdinaryExchange
  608. );
  609. if (Status != STATUS_SUCCESS) {
  610. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  611. return(Status);
  612. }
  613. // The SERVER has a time window of 45 seconds associated with OPLOCK responses.
  614. // During this period oplock responses ( the last packet ) do not elicit any
  615. // response. If the response at the server is received after this window has
  616. // elapsed the OPLOCK response will elicit a normal LOCKING_ANDX response from
  617. // the server. In order to simplify the MID reuse logic at the clients without
  618. // violating the OPLOCK semantics, all the final responses are sent on a special
  619. // MID(0xffff). Any response received with this MID is accepted by default and this
  620. // MID is not used further.
  621. OrdinaryExchange->SmbCeFlags &= ~SMBCE_EXCHANGE_REUSE_MID;
  622. OrdinaryExchange->AssertLocks.LockEnumerator = RxLockEnumerator;
  623. OrdinaryExchange->AssertLocks.SrvOpen = SrvOpen;
  624. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  625. ASSERT (Status!=STATUS_PENDING);
  626. if (Status!=STATUS_PENDING) {
  627. BOOLEAN FinalizationComplete = SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  628. ASSERT(FinalizationComplete);
  629. }
  630. RxDbgTrace(-1, Dbg, ("MRxSmbAssertBufferedFileLocks exit with status=%08lx\n", Status ));
  631. return(Status);
  632. }
  633. #undef Dbg
  634. #define Dbg (DEBUG_TRACE_FLUSH)
  635. NTSTATUS
  636. MRxSmbBuildFlush (
  637. PSMBSTUFFER_BUFFER_STATE StufferState
  638. )
  639. /*++
  640. Routine Description:
  641. This builds a Flush SMB. we don't have to worry about login id and such
  642. since that is done by the connection engine....pretty neat huh? all we have to do
  643. is to format up the bits.
  644. Arguments:
  645. StufferState - the state of the smbbuffer from the stuffer's point of view
  646. Return Value:
  647. RXSTATUS
  648. SUCCESS
  649. NOT_IMPLEMENTED something has appeared in the arguments that i can't handle
  650. Notes:
  651. --*/
  652. {
  653. NTSTATUS Status;
  654. PRX_CONTEXT RxContext = StufferState->RxContext;
  655. RxCaptureFcb;RxCaptureFobx;
  656. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  657. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  658. PAGED_CODE();
  659. RxDbgTrace(+1, Dbg, ("MRxSmbBuildFlush\n", 0 ));
  660. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  661. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_Never, SMB_COM_FLUSH,
  662. SMB_REQUEST_SIZE(FLUSH),
  663. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  664. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  665. );
  666. MRxSmbDumpStufferState (1100,"SMB w/ FLUSH before stuffing",StufferState);
  667. MRxSmbStuffSMB (StufferState,
  668. "0wB!",
  669. // 0 UCHAR WordCount; // Count of parameter words = 1
  670. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  671. SMB_WCT_CHECK(1) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
  672. // UCHAR Buffer[1]; // empty
  673. );
  674. MRxSmbDumpStufferState (700,"SMB w/ FLUSH after stuffing",StufferState);
  675. FINALLY:
  676. RxDbgTraceUnIndent(-1,Dbg);
  677. return(Status);
  678. }
  679. NTSTATUS
  680. MRxSmbFlush(
  681. IN PRX_CONTEXT RxContext)
  682. /*++
  683. Routine Description:
  684. This routine handles network requests for file flush
  685. Arguments:
  686. RxContext - the RDBSS context
  687. Return Value:
  688. RXSTATUS - The return status for the operation
  689. --*/
  690. {
  691. NTSTATUS Status = STATUS_SUCCESS;
  692. RxCaptureFcb;
  693. RxCaptureFobx;
  694. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  695. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  696. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  697. PAGED_CODE();
  698. RxDbgTrace(+1, Dbg, ("MRxSmbFlush\n"));
  699. if (TypeOfOpen == RDBSS_NTC_SPOOLFILE) {
  700. //we don't buffer spoolfiles....just get out....
  701. RxDbgTrace(-1, Dbg, ("MRxSmbFlush exit on spoolfile\n"));
  702. return(STATUS_SUCCESS);
  703. }
  704. ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN );
  705. Status = SmbPseCreateOrdinaryExchange(RxContext,
  706. SrvOpen->pVNetRoot,
  707. SMBPSE_OE_FROM_FLUSH,
  708. SmbPseExchangeStart_Locks,
  709. &OrdinaryExchange
  710. );
  711. if (Status != STATUS_SUCCESS) {
  712. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  713. return(Status);
  714. }
  715. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  716. ASSERT (Status!=STATUS_PENDING);
  717. if (Status!=STATUS_PENDING) {
  718. BOOLEAN FinalizationComplete = SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  719. ASSERT(FinalizationComplete);
  720. }
  721. RxDbgTrace(-1, Dbg, ("MRxSmbFlush exit with status=%08lx\n", Status ));
  722. return(Status);
  723. }
  724. NTSTATUS
  725. MRxSmbIsLockRealizable (
  726. IN OUT PMRX_FCB pFcb,
  727. IN PLARGE_INTEGER ByteOffset,
  728. IN PLARGE_INTEGER Length,
  729. IN ULONG LowIoLockFlags
  730. )
  731. {
  732. PSMBCEDB_SERVER_ENTRY pServerEntry;
  733. ULONG DialectFlags;
  734. PAGED_CODE();
  735. pServerEntry = SmbCeGetAssociatedServerEntry(pFcb->pNetRoot->pSrvCall);
  736. DialectFlags = pServerEntry->Server.DialectFlags;
  737. //nt servers implement all types of locks
  738. if (FlagOn(DialectFlags,DF_NT_SMBS)) {
  739. return(STATUS_SUCCESS);
  740. }
  741. //nonnt servers do not handle 64bit locks or 0-length locks
  742. if ( (ByteOffset->HighPart!=0)
  743. || (Length->HighPart!=0)
  744. || (Length->QuadPart==0) ) {
  745. return(STATUS_NOT_SUPPORTED);
  746. }
  747. // Lanman 2.0 pinball servers don't support shared locks (even
  748. // though Lanman 2.0 FAT servers support them). As a result,
  749. // we cannot support shared locks to Lanman servers.
  750. //
  751. if (!FlagOn(DialectFlags,DF_LANMAN21)
  752. && !FlagOn(LowIoLockFlags,LOWIO_LOCKSFLAG_EXCLUSIVELOCK)) {
  753. return(STATUS_NOT_SUPPORTED);
  754. }
  755. // if a server cannot do lockingAndX, then we can't do
  756. // !FailImmediately because there's no timeout
  757. if (!FlagOn(DialectFlags,DF_LANMAN20)
  758. && !FlagOn(LowIoLockFlags,LOWIO_LOCKSFLAG_FAIL_IMMEDIATELY)) {
  759. return(STATUS_NOT_SUPPORTED);
  760. }
  761. return(STATUS_SUCCESS);
  762. }
  763.