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.

760 lines
24 KiB

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