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.

873 lines
28 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. smbcedb.c
  5. Abstract:
  6. This module implements all functions related to accessing the SMB connection engine
  7. database
  8. Revision History:
  9. Balan Sethu Raman [SethuR] 6-March-1995
  10. Notes:
  11. The mapping between MRX_V_NET_ROOT and a mini rdr data structure is a many to
  12. one relationship, i.e., more than one MRX_V_NET_ROOT instance can be associated with the
  13. same mini rdr data structure.
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include "exsessup.h"
  18. #include "secext.h"
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, SmbCeCompleteVNetRootContextInitialization)
  21. #pragma alloc_text(PAGE, SmbCeDestroyAssociatedVNetRootContext)
  22. #pragma alloc_text(PAGE, SmbCeTearDownVNetRootContext)
  23. #endif
  24. RXDT_Extern(SMBCEDB);
  25. #define Dbg (DEBUG_TRACE_SMBCEDB)
  26. extern BOOLEAN Win9xSessionRestriction;
  27. PSMBCE_V_NET_ROOT_CONTEXT
  28. SmbCeFindVNetRootContext(
  29. PSMBCE_V_NET_ROOT_CONTEXTS pVNetRootContexts,
  30. PSMBCEDB_SERVER_ENTRY pServerEntry,
  31. PSMBCEDB_SESSION_ENTRY pSessionEntry,
  32. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry,
  33. BOOLEAN fCscAgentOpen)
  34. /*++
  35. Routine Description:
  36. This routine finds a SMBCE_V_NET_ROOT_CONTEXT instance
  37. Arguments:
  38. pVNetRootContexts - list of VNetRootContexts for searching
  39. PServerEntry - the ServerEntry should be the same as the one on found VNetRootContext
  40. PSessionEntry - the SessionEntry should be the same as the one on found VNetRootContext
  41. pNetRootEntry - the NetRootEntry should be the same as the one on found VNetRootContext
  42. fCscAgentOpen - this V_NET_ROOT_CONTEXT instance is being created for the CSC
  43. agent
  44. Return Value:
  45. VNetRootContext if found
  46. Notes:
  47. --*/
  48. {
  49. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = NULL;
  50. pVNetRootContext = SmbCeGetFirstVNetRootContext(
  51. pVNetRootContexts);
  52. while (pVNetRootContext != NULL) {
  53. if ((pVNetRootContext->pServerEntry == pServerEntry) &&
  54. (pVNetRootContext->pSessionEntry == pSessionEntry) &&
  55. (pVNetRootContext->pNetRootEntry == pNetRootEntry) &&
  56. (BooleanFlagOn(pVNetRootContext->Flags,
  57. SMBCE_V_NET_ROOT_CONTEXT_CSCAGENT_INSTANCE) == fCscAgentOpen)) {
  58. SmbCeRemoveVNetRootContext(
  59. pVNetRootContexts,
  60. pVNetRootContext);
  61. SmbCeAddVNetRootContext(
  62. &pServerEntry->VNetRootContexts,
  63. pVNetRootContext);
  64. InterlockedDecrement(&pServerEntry->Server.NumberOfVNetRootContextsForScavenging);
  65. SmbCeLog(("CachedVNRContext(S) %lx\n",pVNetRootContext));
  66. SmbLog(LOG,
  67. SmbCeFindVNetRootContext,
  68. LOGPTR(pVNetRootContext));
  69. break;
  70. } else {
  71. pVNetRootContext = SmbCeGetNextVNetRootContext(
  72. pVNetRootContexts,
  73. pVNetRootContext);
  74. }
  75. }
  76. return pVNetRootContext;
  77. }
  78. NTSTATUS
  79. SmbCeFindOrConstructVNetRootContext(
  80. PMRX_V_NET_ROOT pVNetRoot,
  81. BOOLEAN fDeferNetworkInitialization,
  82. BOOLEAN fCscAgentOpen)
  83. /*++
  84. Routine Description:
  85. This routine finds or constructs a SMBCE_V_NET_ROOT_CONTEXT instance
  86. Arguments:
  87. pVNetRoot - the MRX_V_NET_ROOT instance
  88. fDeferNetworkInitialization - a directive to delay network initialization for new
  89. instances.
  90. fCscAgentOpen - this V_NET_ROOT_CONTEXT instance is being created for the CSC
  91. agent
  92. Return Value:
  93. STATUS_SUCCESS if the MRX_V_NET_ROOT instance was successfully initialized
  94. Notes:
  95. The algorithm that has been implemented tries to delay the construction of a
  96. new instance as much as possible. It does this be either reusing a context
  97. that has already been active or a context instance that has been marked for
  98. scavenging but has not been scavenged.
  99. --*/
  100. {
  101. NTSTATUS Status;
  102. PMRX_SRV_CALL pSrvCall;
  103. PMRX_NET_ROOT pNetRoot;
  104. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = NULL;
  105. PSMBCEDB_SERVER_ENTRY pServerEntry = NULL;
  106. PSMBCEDB_SESSION_ENTRY pSessionEntry = NULL;
  107. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry = NULL;
  108. BOOLEAN fInitializeNetRoot;
  109. BOOLEAN fDereferenceSessionEntry = FALSE;
  110. BOOLEAN fDereferenceNetRootEntry = FALSE;
  111. pNetRoot = pVNetRoot->pNetRoot;
  112. pSrvCall = pNetRoot->pSrvCall;
  113. SmbCeAcquireResource();
  114. pServerEntry = SmbCeGetAssociatedServerEntry(pSrvCall);
  115. // The V_NET_ROOT is associated with a NET_ROOT. The two cases of interest are as
  116. // follows
  117. // 1) the V_NET_ROOT and the associated NET_ROOT are being newly created.
  118. // 2) a new V_NET_ROOT associated with an existing NET_ROOT is being created.
  119. //
  120. // These two cases can be distinguished by checking if the context associated with
  121. // NET_ROOT is NULL. Since the construction of NET_ROOT's/V_NET_ROOT's are serialized
  122. // by the wrapper this is a safe check.
  123. // ( The wrapper cannot have more then one thread tryingto initialize the same
  124. // NET_ROOT).
  125. pNetRootEntry = (PSMBCEDB_NET_ROOT_ENTRY)pNetRoot->Context;
  126. fInitializeNetRoot = (pNetRootEntry == NULL);
  127. pVNetRoot->Context = NULL;
  128. // Find or construct the session entry that will be associated with the context. The
  129. // one error that deserves special consideration is STATUS_NETWORK_CREDENTIAL_CONFLICT.
  130. // This error signifies that the credentials presented with the MRX_V_NET_ROOT instance
  131. // conflicted with an existing session. This conflict could be either becuase there
  132. // exists an active session or because a previously active session is awaiting
  133. // scavenging. In the former case the error needs to be propagated back but in the
  134. // later case the contexts must be selectively scavenged.
  135. //
  136. // The scavenging should be limited only to those contexts to the appropriate server.
  137. Status = SmbCeFindOrConstructSessionEntry(
  138. pVNetRoot,
  139. &pSessionEntry);
  140. if (Status == STATUS_NETWORK_CREDENTIAL_CONFLICT) {
  141. NTSTATUS ScavengingStatus;
  142. SmbCeReleaseResource();
  143. ScavengingStatus = SmbCeScavengeRelatedContexts(pServerEntry);
  144. if (ScavengingStatus == STATUS_SUCCESS) {
  145. SmbCeAcquireResource();
  146. Status = SmbCeFindOrConstructSessionEntry(
  147. pVNetRoot,
  148. &pSessionEntry);
  149. } else {
  150. return Status;
  151. }
  152. }
  153. fDereferenceSessionEntry = (Status == STATUS_SUCCESS);
  154. if (Status == STATUS_SUCCESS) {
  155. if (fInitializeNetRoot) {
  156. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
  157. // Initialize the device type and state for a new MRX_NET_ROOT instance
  158. switch (pNetRoot->Type) {
  159. case NET_ROOT_DISK:
  160. {
  161. pNetRoot->DeviceType = RxDeviceType(DISK);
  162. RxInitializeNetRootThrottlingParameters(
  163. &pNetRoot->DiskParameters.LockThrottlingParameters,
  164. MRxSmbConfiguration.LockIncrement,
  165. MRxSmbConfiguration.MaximumLock
  166. );
  167. }
  168. break;
  169. case NET_ROOT_PIPE:
  170. {
  171. pNetRoot->DeviceType = RxDeviceType(NAMED_PIPE);
  172. RxInitializeNetRootThrottlingParameters(
  173. &pNetRoot->NamedPipeParameters.PipeReadThrottlingParameters,
  174. MRxSmbConfiguration.PipeIncrement,
  175. MRxSmbConfiguration.PipeMaximum
  176. );
  177. }
  178. break;
  179. case NET_ROOT_COMM:
  180. pNetRoot->DeviceType = RxDeviceType(SERIAL_PORT);
  181. break;
  182. case NET_ROOT_PRINT:
  183. pNetRoot->DeviceType = RxDeviceType(PRINTER);
  184. break;
  185. case NET_ROOT_MAILSLOT:
  186. pNetRoot->DeviceType = RxDeviceType(MAILSLOT);
  187. break;
  188. case NET_ROOT_WILD:
  189. break;
  190. default:
  191. ASSERT(!"Valid Net Root Type");
  192. }
  193. Status = SmbCeFindOrConstructNetRootEntry(
  194. pNetRoot,
  195. &pNetRootEntry);
  196. RxDbgTrace( 0, Dbg, ("SmbCeOpenNetRoot %lx\n",Status));
  197. } else {
  198. SmbCeLog(("ReuseNREntry %lx\n",pNetRootEntry));
  199. SmbLog(LOG,
  200. SmbCeFindOrConstructVNetRootContext_1,
  201. LOGPTR(pNetRootEntry));
  202. SmbCeReferenceNetRootEntry(pNetRootEntry);
  203. }
  204. fDereferenceNetRootEntry = (Status == STATUS_SUCCESS);
  205. }
  206. if (Status == STATUS_SUCCESS) {
  207. pVNetRootContext = SmbCeFindVNetRootContext(
  208. &pServerEntry->VNetRootContexts,
  209. pServerEntry,
  210. pSessionEntry,
  211. pNetRootEntry,
  212. fCscAgentOpen);
  213. if (pVNetRootContext == NULL) {
  214. pVNetRootContext = SmbCeFindVNetRootContext(
  215. &MRxSmbScavengerServiceContext.VNetRootContexts,
  216. pServerEntry,
  217. pSessionEntry,
  218. pNetRootEntry,
  219. fCscAgentOpen);
  220. }
  221. if (pVNetRootContext != NULL) {
  222. // An existing instance can be reused. No more work to be done
  223. SmbCeReferenceVNetRootContext(pVNetRootContext);
  224. } else {
  225. // None of the existing instances can be reused. A new instance needs to be
  226. // constructed.
  227. pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)
  228. RxAllocatePoolWithTag(
  229. NonPagedPool,
  230. sizeof(SMBCE_V_NET_ROOT_CONTEXT),
  231. MRXSMB_VNETROOT_POOLTAG);
  232. if (pVNetRootContext != NULL) {
  233. // Initialize the new instance
  234. RtlZeroMemory(
  235. pVNetRootContext,
  236. sizeof(SMBCE_V_NET_ROOT_CONTEXT));
  237. // Transfer the references made during the construction of the session and
  238. // the net root entries to the new context. Disable the dereferencing at
  239. // the end of this routine.
  240. fDereferenceSessionEntry = FALSE;
  241. fDereferenceNetRootEntry = FALSE;
  242. SmbCeReferenceServerEntry(pServerEntry);
  243. pVNetRootContext->Header.NodeType = SMB_CONNECTION_ENGINE_NTC(
  244. SMBCEDB_OT_VNETROOTCONTEXT);
  245. if (pNetRootEntry->NetRoot.NetRootType == NET_ROOT_MAILSLOT) {
  246. pVNetRootContext->Header.State = SMBCEDB_ACTIVE;
  247. } else {
  248. pVNetRootContext->Header.State = SMBCEDB_INVALID;
  249. }
  250. pVNetRootContext->Flags = 0;
  251. if (fCscAgentOpen) {
  252. pVNetRootContext->Flags |= SMBCE_V_NET_ROOT_CONTEXT_CSCAGENT_INSTANCE;
  253. }
  254. InitializeListHead(&pVNetRootContext->Requests.ListHead);
  255. pVNetRootContext->pServerEntry = pServerEntry;
  256. pVNetRootContext->pSessionEntry = pSessionEntry;
  257. pVNetRootContext->pNetRootEntry = pNetRootEntry;
  258. SmbCeReferenceVNetRootContext(pVNetRootContext);
  259. // Add it to the list of active contexts
  260. SmbCeAddVNetRootContext(
  261. &pServerEntry->VNetRootContexts,
  262. pVNetRootContext);
  263. SmbCeLog(("NewVNetRootContext %lx\n",pVNetRootContext));
  264. SmbLog(LOG,
  265. SmbCeFindOrConstructVNetRootContext_2,
  266. LOGPTR(pVNetRootContext));
  267. } else {
  268. Status = STATUS_INSUFFICIENT_RESOURCES;
  269. }
  270. }
  271. }
  272. if (Status == STATUS_SUCCESS) {
  273. // If everything was successful set up the MRX_V_NET_ROOT and MRX_NET_ROOT
  274. // instances
  275. pVNetRoot->Context = pVNetRootContext;
  276. pVNetRootContext->pRdbssVNetRoot = pVNetRoot;
  277. if (fInitializeNetRoot) {
  278. ASSERT(pNetRootEntry->pRdbssNetRoot == NULL);
  279. InterlockedExchangePointer(
  280. &pNetRootEntry->pRdbssNetRoot,
  281. pNetRoot);
  282. SmbCeUpdateNetRoot(pNetRootEntry,pNetRoot);
  283. SmbCeReferenceNetRootEntry(pNetRootEntry);
  284. pNetRoot->Context = pNetRootEntry;
  285. } else {
  286. if (FlagOn(pNetRoot->Flags,NETROOT_FLAG_FINALIZE_INVOKED)) {
  287. ClearFlag(pNetRoot->Flags,NETROOT_FLAG_FINALIZE_INVOKED);
  288. SmbCeReferenceNetRootEntry(pNetRootEntry);
  289. }
  290. }
  291. InterlockedIncrement(&pSessionEntry->Session.NumberOfActiveVNetRoot);
  292. } else {
  293. pVNetRoot->Context = NULL;
  294. if (fInitializeNetRoot) {
  295. pNetRoot->Context = NULL;
  296. }
  297. }
  298. SmbCeReleaseResource();
  299. if (fDereferenceSessionEntry) {
  300. SmbCeDereferenceSessionEntry(pSessionEntry);
  301. }
  302. if (fDereferenceNetRootEntry) {
  303. SmbCeDereferenceNetRootEntry(pNetRootEntry);
  304. }
  305. if (!fDeferNetworkInitialization &&
  306. (Status == STATUS_SUCCESS)) {
  307. Status = STATUS_MORE_PROCESSING_REQUIRED;
  308. }
  309. if (SmbCeGetServerType(pServerEntry) == SMBCEDB_FILE_SERVER) {
  310. ASSERT((Status != STATUS_SUCCESS) || (pVNetRoot->Context != NULL));
  311. }
  312. return Status;
  313. }
  314. VOID
  315. SmbCeCompleteVNetRootContextInitialization(
  316. PVOID pContext)
  317. /*++
  318. Routine Description:
  319. This routine is invoked in the context of a worker thread to finalize the
  320. construction of a SMBCE_V_NET_ROOT_CONTEXT instance
  321. Arguments:
  322. pContext - the SMBCE_V_NET_ROOT_CONTEXT instance
  323. Notes:
  324. PRE_CONDITION: The VNetRootContext must have been referenced to ensure that
  325. even it has been finalized it will not be deleted.
  326. --*/
  327. {
  328. NTSTATUS Status;
  329. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  330. PSMBCEDB_REQUEST_ENTRY pRequestEntry;
  331. SMBCEDB_REQUESTS Requests;
  332. PAGED_CODE();
  333. RxDbgTrace( 0, Dbg, ("Net Root Entry Finalization\n"));
  334. pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)pContext;
  335. ASSERT(pVNetRootContext->Header.ObjectType == SMBCEDB_OT_VNETROOTCONTEXT);
  336. SmbCeAcquireResource();
  337. pVNetRootContext->pExchange = NULL;
  338. SmbCeTransferRequests(&Requests,&pVNetRootContext->Requests);
  339. if (pVNetRootContext->Header.State == SMBCEDB_ACTIVE) {
  340. Status = STATUS_SUCCESS;
  341. } else {
  342. Status = STATUS_INVALID_CONNECTION;
  343. SmbCeUpdateVNetRootContextState(
  344. pVNetRootContext,
  345. SMBCEDB_INVALID);
  346. }
  347. SmbCeReleaseResource();
  348. // Iterate over the list of pending requests and resume all of them
  349. SmbCeResumeOutstandingRequests(&Requests,Status);
  350. SmbCeDereferenceVNetRootContext(pVNetRootContext);
  351. }
  352. VOID
  353. SmbCepDereferenceVNetRootContext(
  354. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext)
  355. /*++
  356. Routine Description:
  357. This routine dereferences a SMBCE_V_NET_ROOT_CONTEXT instance
  358. Arguments:
  359. pVNetRootContext - the SMBCE_V_NET_ROOT_CONTEXT instance
  360. Notes:
  361. There are two intersting points to note. A mini redirector can avoid potential
  362. network traffic by delaying the scavenging of the SMBCE_V_NET_ROOT_CONTEXT
  363. instance since it contains all the relevant network setup to satisfy requests.
  364. This is a policy that is implemented in the mini redirector and is different from
  365. the wrapper policies.
  366. Once the decision to delay scavenging has been made, there are two options. The
  367. successful and unsuccessful instances can be delayed or only the successful
  368. instances. The current algorithm is to delay the scavenging of the successful
  369. SMBCE_V_NET_ROOT_CONTEXT instances only.
  370. Also there are three components to a VNetRootContext that can be scavenged
  371. independently. If the server exists and a session setup to the server fails
  372. because of wrong credentials there is no point in throwing away the server
  373. entry eagerly. This routine selectively gathers the failed fields for eager
  374. scavenging and retains the VNetRootContext skeleton alongwith the other
  375. structures that can be deferred.
  376. --*/
  377. {
  378. if (pVNetRootContext != NULL) {
  379. LONG FinalRefCount;
  380. FinalRefCount = InterlockedDecrement(
  381. &pVNetRootContext->Header.SwizzleCount);
  382. if (FinalRefCount == 0) {
  383. LARGE_INTEGER CurrentTime;
  384. BOOLEAN TearDownVNetRootContext = FALSE;
  385. PSMBCE_SERVER pServer = &pVNetRootContext->pServerEntry->Server;
  386. PSMBCE_SESSION pSession = &pVNetRootContext->pSessionEntry->Session;
  387. SmbCeAcquireResource();
  388. if (pVNetRootContext->Header.SwizzleCount == 0) {
  389. // Remove the instance from the active list of contexts to the server.
  390. SmbCeRemoveVNetRootContext(
  391. &pVNetRootContext->pSessionEntry->pServerEntry->VNetRootContexts,
  392. pVNetRootContext);
  393. // if it was a successful instance mark it for scavenging, otherwise
  394. // tear it down immediately
  395. if ((pVNetRootContext->pSessionEntry != NULL) &&
  396. (pVNetRootContext->pSessionEntry->Header.State != SMBCEDB_ACTIVE ||
  397. pSession->pUserName != NULL ||
  398. pSession->pPassword != NULL ||
  399. pSession->pUserDomainName != NULL)) {
  400. TearDownVNetRootContext = TRUE;
  401. }
  402. if ((pVNetRootContext->pNetRootEntry != NULL) &&
  403. (pVNetRootContext->pNetRootEntry->Header.State != SMBCEDB_ACTIVE ||
  404. TearDownVNetRootContext)) {
  405. TearDownVNetRootContext = TRUE;
  406. }
  407. if (Win9xSessionRestriction &&
  408. (pVNetRootContext->pServerEntry != NULL) &&
  409. FlagOn(pVNetRootContext->pServerEntry->Server.DialectFlags,DF_W95)) {
  410. TearDownVNetRootContext = TRUE;
  411. }
  412. InterlockedIncrement(&pServer->NumberOfVNetRootContextsForScavenging);
  413. if (!TearDownVNetRootContext &&
  414. (pVNetRootContext->pNetRootEntry != NULL) &&
  415. (pVNetRootContext->pSessionEntry != NULL) &&
  416. pServer->NumberOfVNetRootContextsForScavenging < MaximumNumberOfVNetRootContextsForScavenging) {
  417. ClearFlag(pVNetRootContext->Flags, SMBCE_V_NET_ROOT_CONTEXT_CSCAGENT_INSTANCE);
  418. KeQueryTickCount( &CurrentTime );
  419. pVNetRootContext->ExpireTime.QuadPart = CurrentTime.QuadPart +
  420. (LONGLONG) ((MRXSMB_V_NETROOT_CONTEXT_SCAVENGER_INTERVAL * 10 * 1000 * 1000) / KeQueryTimeIncrement());
  421. SmbCeAddVNetRootContext(
  422. &MRxSmbScavengerServiceContext.VNetRootContexts,
  423. pVNetRootContext);
  424. MRxSmbActivateRecurrentService(
  425. (PRECURRENT_SERVICE_CONTEXT)&MRxSmbScavengerServiceContext);
  426. SmbCeLog(("ScavngVNetRootCntxt %lx\n",pVNetRootContext));
  427. SmbLog(LOG,
  428. SmbCepDereferenceVNetRootContext,
  429. LOGPTR(pVNetRootContext));
  430. } else {
  431. TearDownVNetRootContext = TRUE;
  432. }
  433. }
  434. SmbCeReleaseResource();
  435. if (TearDownVNetRootContext) {
  436. pVNetRootContext->Header.State = SMBCEDB_MARKED_FOR_DELETION;
  437. SmbCeTearDownVNetRootContext(pVNetRootContext);
  438. }
  439. }
  440. }
  441. }
  442. NTSTATUS
  443. SmbCeDestroyAssociatedVNetRootContext(
  444. PMRX_V_NET_ROOT pVNetRoot)
  445. /*++
  446. Routine Description:
  447. This routine derferences a SMBCE_V_NET_ROOT_CONTEXT instance
  448. Arguments:
  449. pVNetRootContext - the SMBCE_V_NET_ROOT_CONTEXT instance to be dereferenced
  450. --*/
  451. {
  452. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  453. PAGED_CODE();
  454. pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)pVNetRoot->Context;
  455. if (pVNetRootContext != NULL) {
  456. pVNetRootContext->pRdbssVNetRoot = NULL;
  457. SmbCeDecrementNumberOfActiveVNetRootOnSession(pVNetRootContext);
  458. SmbCeDereferenceVNetRootContext(pVNetRootContext);
  459. }
  460. pVNetRoot->Context = NULL;
  461. return STATUS_SUCCESS;
  462. }
  463. VOID
  464. SmbCeTearDownVNetRootContext(
  465. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext)
  466. /*++
  467. Routine Description:
  468. This routine tears down a SMBCE_V_NET_ROOT_CONTEXT instance
  469. Arguments:
  470. pVNetRootContext - the SMBCE_V_NET_ROOT_CONTEXT instance to be torn down
  471. --*/
  472. {
  473. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  474. PAGED_CODE();
  475. SmbCeLog(("TearVNetRootContext %lx\n",pVNetRootContext));
  476. SmbLog(LOG,
  477. SmbCeTearDownVNetRootContext,
  478. LOGPTR(pVNetRootContext));
  479. pNetRootEntry = pVNetRootContext->pNetRootEntry;
  480. if ((pNetRootEntry != NULL) &&
  481. BooleanFlagOn(pVNetRootContext->Flags,SMBCE_V_NET_ROOT_CONTEXT_FLAG_VALID_TID) &&
  482. (SmbCeGetServerType(pVNetRootContext->pServerEntry) == SMBCEDB_FILE_SERVER)) {
  483. SmbCeDisconnect(pVNetRootContext);
  484. }
  485. if (pNetRootEntry != NULL) {
  486. pVNetRootContext->pNetRootEntry = NULL;
  487. SmbCeDereferenceNetRootEntry(pNetRootEntry);
  488. }
  489. if (pVNetRootContext->pSessionEntry != NULL) {
  490. SmbCeDereferenceSessionEntry(pVNetRootContext->pSessionEntry);
  491. }
  492. InterlockedDecrement(&pVNetRootContext->pServerEntry->Server.NumberOfVNetRootContextsForScavenging);
  493. SmbCeDereferenceServerEntry(pVNetRootContext->pServerEntry);
  494. RxFreePool(pVNetRootContext);
  495. }
  496. NTSTATUS
  497. SmbCeScavenger(
  498. PVOID pContext)
  499. /*++
  500. Routine Description:
  501. This routine scavenges SMBCE_V_NET_ROOT_CONTEXT instances
  502. Arguments:
  503. pContext - the scavenger service context
  504. Notes:
  505. Since the contexts for scavenging are threaded together in an entry that
  506. is managed in a FIFO fashion, if the first entry fails the time interval
  507. test ( expiry time has not elapsed ) all the other entries in the list
  508. are guaranteed to fail the test. This is an important property that eases
  509. the implementation of scavenging.
  510. --*/
  511. {
  512. NTSTATUS Status = STATUS_SUCCESS;
  513. PMRXSMB_SCAVENGER_SERVICE_CONTEXT pScavengerServiceContext;
  514. LARGE_INTEGER CurrentTime;
  515. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  516. BOOLEAN fTerminateScavenging = FALSE;
  517. pScavengerServiceContext = (PMRXSMB_SCAVENGER_SERVICE_CONTEXT)pContext;
  518. do {
  519. SmbCeAcquireResource();
  520. KeQueryTickCount( &CurrentTime );
  521. pVNetRootContext = SmbCeGetFirstVNetRootContext(
  522. &pScavengerServiceContext->VNetRootContexts);
  523. fTerminateScavenging = (pVNetRootContext == NULL);
  524. if (!fTerminateScavenging) {
  525. if ((CurrentTime.QuadPart >= pVNetRootContext->ExpireTime.QuadPart) ||
  526. (pScavengerServiceContext->RecurrentServiceContext.State == RECURRENT_SERVICE_SHUTDOWN)) {
  527. SmbCeRemoveVNetRootContext(
  528. &pScavengerServiceContext->VNetRootContexts,
  529. pVNetRootContext);
  530. } else {
  531. fTerminateScavenging = TRUE;
  532. }
  533. }
  534. SmbCeReleaseResource();
  535. if (!fTerminateScavenging &&
  536. (pVNetRootContext != NULL)) {
  537. SmbCeTearDownVNetRootContext(pVNetRootContext);
  538. }
  539. } while (!fTerminateScavenging);
  540. return Status;
  541. }
  542. NTSTATUS
  543. SmbCeScavengeRelatedContexts(
  544. PSMBCEDB_SERVER_ENTRY pServerEntry)
  545. /*++
  546. Routine Description:
  547. This routine scavenges SMBCE_V_NET_ROOT_CONTEXT instances for a given
  548. server entry
  549. Arguments:
  550. pServerEntry - the server entry
  551. Notes:
  552. --*/
  553. {
  554. NTSTATUS Status;
  555. SMBCE_V_NET_ROOT_CONTEXTS VNetRootContexts;
  556. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  557. InitializeListHead(&VNetRootContexts.ListHead);
  558. SmbCeAcquireResource();
  559. pVNetRootContext = SmbCeGetFirstVNetRootContext(
  560. &MRxSmbScavengerServiceContext.VNetRootContexts);
  561. while (pVNetRootContext != NULL) {
  562. PSMBCE_V_NET_ROOT_CONTEXT pNextVNetRootContext;
  563. pNextVNetRootContext = SmbCeGetNextVNetRootContext(
  564. &MRxSmbScavengerServiceContext.VNetRootContexts,
  565. pVNetRootContext);
  566. if (pVNetRootContext->pServerEntry == pServerEntry) {
  567. SmbCeRemoveVNetRootContext(
  568. &MRxScavengerServiceContext.VNetRootContexts,
  569. pVNetRootContext);
  570. SmbCeAddVNetRootContext(
  571. &VNetRootContexts,
  572. pVNetRootContext);
  573. }
  574. pVNetRootContext = pNextVNetRootContext;
  575. }
  576. SmbCeReleaseResource();
  577. pVNetRootContext = SmbCeGetFirstVNetRootContext(
  578. &VNetRootContexts);
  579. if (pVNetRootContext != NULL) {
  580. do {
  581. SmbCeRemoveVNetRootContext(
  582. &VNetRootContexts,
  583. pVNetRootContext);
  584. SmbCeTearDownVNetRootContext(pVNetRootContext);
  585. pVNetRootContext = SmbCeGetFirstVNetRootContext(
  586. &VNetRootContexts);
  587. } while ( pVNetRootContext != NULL );
  588. Status = STATUS_SUCCESS;
  589. } else {
  590. Status = STATUS_UNSUCCESSFUL;
  591. }
  592. SmbCeLog(("Scavctxts Srv %lx Status %lx\n",pServerEntry,Status));
  593. SmbLog(LOG,
  594. SmbCeScavengeRelatedContexts,
  595. LOGULONG(Status)
  596. LOGPTR(pServerEntry)
  597. LOGUSTR(pServerEntry->Name));
  598. return Status;
  599. }
  600. VOID
  601. SmbCeDecrementNumberOfActiveVNetRootOnSession(
  602. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext
  603. )
  604. {
  605. ULONG NumberOfVNetRoot;
  606. BOOLEAN fLogOffRequired = FALSE;
  607. PSMBCEDB_SERVER_ENTRY pServerEntry = NULL;
  608. PSMBCEDB_SESSION_ENTRY pSessionEntry = NULL;
  609. SmbCeAcquireResource();
  610. NumberOfVNetRoot = InterlockedDecrement(&pVNetRootContext->pSessionEntry->Session.NumberOfActiveVNetRoot);
  611. if (NumberOfVNetRoot == 0) {
  612. pSessionEntry = pVNetRootContext->pSessionEntry;
  613. pServerEntry = pVNetRootContext->pServerEntry;
  614. if (!FlagOn(pSessionEntry->Session.Flags,SMBCE_SESSION_FLAGS_LOGGED_OFF)) {
  615. SmbCeRemoveSessionEntry(pServerEntry,pSessionEntry);
  616. SmbCeRemoveDefaultSessionEntry(pSessionEntry);
  617. }
  618. if ((pSessionEntry->Session.UserId != (SMB_USER_ID)(SMBCE_SHARE_LEVEL_SERVER_USERID)) &&
  619. (pSessionEntry->Session.UserId != 0) &&
  620. (pSessionEntry->Header.State == SMBCEDB_ACTIVE) &&
  621. !FlagOn(pSessionEntry->Session.Flags,SMBCE_SESSION_FLAGS_LOGGED_OFF)) {
  622. SmbCeReferenceServerEntry(pServerEntry);
  623. SmbCeReferenceSessionEntry(pSessionEntry);
  624. fLogOffRequired = TRUE;
  625. }
  626. // all the consequent requests on this session should fail
  627. pSessionEntry->Header.State = SMBCEDB_MARKED_FOR_DELETION;
  628. pSessionEntry->Session.Flags |= SMBCE_SESSION_FLAGS_LOGGED_OFF;
  629. pSessionEntry->Session.Flags |= SMBCE_SESSION_FLAGS_MARKED_FOR_DELETION;
  630. }
  631. SmbCeReleaseResource();
  632. if (fLogOffRequired) {
  633. SmbCeLogOff(pServerEntry,pSessionEntry);
  634. SmbCeDereferenceServerEntry(pServerEntry);
  635. }
  636. }
  637.