Source code of Windows XP (NT5)
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.

4524 lines
134 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. FcbStruc.c
  5. Abstract:
  6. This module implements functions for to create and dereference fcbs
  7. and all of the surrounding paraphenalia. Please read the abstract in
  8. fcb.h. Please see the note about what locks to need to call what.
  9. There are asserts to enforce these conventions.
  10. Author:
  11. Joe Linn (JoeLinn) 8-8-94
  12. Revision History:
  13. Balan Sethu Raman --
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include <ntddnfs2.h>
  18. #include <ntddmup.h>
  19. #ifdef RDBSSLOG
  20. #include <stdio.h>
  21. #endif
  22. #include <dfsfsctl.h>
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text(PAGE, RxDereference)
  25. #pragma alloc_text(PAGE, RxReference)
  26. #pragma alloc_text(PAGE, RxpReferenceNetFcb)
  27. #pragma alloc_text(PAGE, RxpDereferenceNetFcb)
  28. #pragma alloc_text(PAGE, RxpDereferenceAndFinalizeNetFcb)
  29. #pragma alloc_text(PAGE, RxWaitForStableCondition)
  30. #pragma alloc_text(PAGE, RxUpdateCondition)
  31. #pragma alloc_text(PAGE, RxAllocateObject)
  32. #pragma alloc_text(PAGE, RxFreeObject)
  33. #pragma alloc_text(PAGE, RxFinalizeNetTable)
  34. #pragma alloc_text(PAGE, RxFinalizeConnection)
  35. #pragma alloc_text(PAGE, RxInitializeSrvCallParameters)
  36. #pragma alloc_text(PAGE, RxCreateSrvCall)
  37. #pragma alloc_text(PAGE, RxSetSrvCallDomainName)
  38. #pragma alloc_text(PAGE, RxFinalizeSrvCall)
  39. #pragma alloc_text(PAGE, RxCreateNetRoot)
  40. #pragma alloc_text(PAGE, RxFinalizeNetRoot)
  41. #pragma alloc_text(PAGE, RxAddVirtualNetRootToNetRoot)
  42. #pragma alloc_text(PAGE, RxRemoveVirtualNetRootFromNetRoot)
  43. #pragma alloc_text(PAGE, RxInitializeVNetRootParameters)
  44. #pragma alloc_text(PAGE, RxUninitializeVNetRootParameters)
  45. #pragma alloc_text(PAGE, RxCreateVNetRoot)
  46. #pragma alloc_text(PAGE, RxOrphanSrvOpens)
  47. #pragma alloc_text(PAGE, RxFinalizeVNetRoot)
  48. #pragma alloc_text(PAGE, RxAllocateFcbObject)
  49. #pragma alloc_text(PAGE, RxFreeFcbObject)
  50. #pragma alloc_text(PAGE, RxCreateNetFcb)
  51. #pragma alloc_text(PAGE, RxInferFileType)
  52. #pragma alloc_text(PAGE, RxFinishFcbInitialization)
  53. #pragma alloc_text(PAGE, RxRemoveNameNetFcb)
  54. #pragma alloc_text(PAGE, RxPurgeFcb)
  55. #pragma alloc_text(PAGE, RxFinalizeNetFcb)
  56. #pragma alloc_text(PAGE, RxSetFileSizeWithLock)
  57. #pragma alloc_text(PAGE, RxGetFileSizeWithLock)
  58. #pragma alloc_text(PAGE, RxCreateSrvOpen)
  59. #pragma alloc_text(PAGE, RxFinalizeSrvOpen)
  60. #pragma alloc_text(PAGE, RxCreateNetFobx)
  61. #pragma alloc_text(PAGE, RxFinalizeNetFobx)
  62. #pragma alloc_text(PAGE, RxCheckFcbStructuresForAlignment)
  63. #pragma alloc_text(PAGE, RxOrphanThisFcb)
  64. #pragma alloc_text(PAGE, RxOrphanSrvOpensForThisFcb)
  65. #pragma alloc_text(PAGE, RxForceFinalizeAllVNetRoots)
  66. #endif
  67. //
  68. // The Bug check file id for this module
  69. //
  70. #define BugCheckFileId (RDBSS_BUG_CHECK_FCBSTRUC)
  71. //struct _RX_PREFIX_TABLE RxNetNameTable;
  72. ULONG SerialNumber = 1; //zero doesn't work!!!
  73. //
  74. // The debug trace level
  75. //
  76. #define Dbg (DEBUG_TRACE_FCBSTRUCTS)
  77. // SRV_CALL,NET_ROOT,VNET_ROOT,FCB,SRV_OPEN,FOBX are the six key data structures in the RDBSS
  78. // They are organized in the following hierarchy
  79. //
  80. // SRV_CALL
  81. // NET_ROOT
  82. // VNET_ROOT
  83. // FCB
  84. // SRV_OPEN
  85. // FOBX
  86. //
  87. // All these data structures are reference counted. The reference count associated with
  88. // any data structure is atleast 1 + the number of instances of the data structure at the next
  89. // level associated with it, e.g., the reference count associated with a SRV_CALL which
  90. // has two NET_ROOT's associated with it is atleast 3. In addition to the references held
  91. // by the NameTable and the data structure at the next level there are additional references
  92. // acquired as and when required.
  93. //
  94. // These restrictions ensure that a data structure at any given level cannot be finalized till
  95. // all the data structures at the next level have been finalized or have released their
  96. // references, i.e., if a reference to a FCB is held, then it is safe to access the VNET_ROOT,
  97. // NET_ROOT and SRV_CALL associated with it.
  98. //
  99. // The SRV_CALL,NET_ROOT and VNET_ROOT creation/finalization are governed by the acquistion/
  100. // release of the RxNetNameTable lock.
  101. //
  102. // The FCB creation/finalization is governed by the acquistion/release of the NetNameTable
  103. // lock associated with the NET_ROOT.
  104. //
  105. // The FOBX/SRVOPEN creation/finalization is governed by the acquistion/release of the FCB
  106. // resource.
  107. //
  108. // The following table summarizes the locks and the modes in which they need to be acquired
  109. // for creation/finalization of the various data structures.
  110. //
  111. //
  112. // L O C K I N G R E Q U I R E M E N T S
  113. //
  114. // Locking requirements are as follows:
  115. //
  116. // where Xy means Exclusive-on-Y, Sy mean at least Shared-on-Y
  117. // and NNT means global NetNameTable, TL means NetRoot TableLock, and FCB means FCBlock
  118. //
  119. //
  120. //
  121. // SRVCALL NETROOT FCB SRVOPEN FOBX
  122. //
  123. // Create XNNT XNNT XTL XFCB XFCB
  124. // Finalize XNNT XNNT XFCB XFCB XFCB
  125. // & XTL
  126. //
  127. // Referencing and Dereferencing these data structures need to adhere to certain conventions
  128. // as well.
  129. //
  130. // When the reference count associated with any of these data structures drops to 1 ( the sole
  131. // reference being held by the name table in most cases) the data structure is a potential
  132. // candidate for finalization. The data structure can be either finalized immediately or it
  133. // can be marked for scavenging. Both of these methods are implemented. When the locking
  134. // requirements are met during dereferencing the data structures are finalized immediately
  135. // ( the one exception being that when delayed operation optimization is implemented, e.g., FCB)
  136. // otherwise the data structure is marked for scavenging.
  137. //
  138. //
  139. // You are supposed to have the tablelock exclusive to be calling this routine.......I can't
  140. // take it here because you are already supposed to have it. To do a create, you should
  141. // done something like
  142. //
  143. // getshared();lookup();
  144. // if (failed) {
  145. // release(); getexclusive(); lookup();
  146. // if ((failed) { create(); }
  147. // }
  148. // deref();
  149. // release();
  150. //
  151. // so you will already have the lock. what you do is to insert the node into the table, release
  152. // the lock, and then go and see if the server's there. if so, set up the rest of the stuff and unblock
  153. // anyone who's waiting on the same server (or netroot)...i guess i could enforce this by releasing here
  154. // but i do not.
  155. // Forward declarations -- These routines are not meant for use in other
  156. // modules
  157. BOOLEAN
  158. RxFinalizeNetFcb (
  159. OUT PFCB ThisFcb,
  160. IN BOOLEAN RecursiveFinalize,
  161. IN BOOLEAN ForceFinalize,
  162. IN LONG ReferenceCount
  163. );
  164. VOID
  165. RxPurgeFcb(
  166. IN PFCB pFcb);
  167. BOOLEAN
  168. RxIsThisACscAgentOpen(
  169. IN PRX_CONTEXT RxContext
  170. );
  171. VOID
  172. RxDereference(
  173. IN OUT PVOID pInstance,
  174. IN LOCK_HOLDING_STATE LockHoldingState)
  175. /*++
  176. Routine Description:
  177. The routine adjust the reference count on an instance of the reference counted data
  178. structures in RDBSS exlcuding the FCB.
  179. Arguments:
  180. pInstance - the instance being dereferenced
  181. LockHoldingState - the mode in which the appropriate lock is held.
  182. Return Value:
  183. none.
  184. --*/
  185. {
  186. LONG FinalRefCount;
  187. NODE_TYPE_CODE_AND_SIZE *pNode = (PNODE_TYPE_CODE_AND_SIZE)pInstance;
  188. BOOLEAN fFinalizeInstance = FALSE;
  189. PAGED_CODE();
  190. RxAcquireScavengerMutex();
  191. ASSERT((NodeType(pInstance) == RDBSS_NTC_SRVCALL ) ||
  192. (NodeType(pInstance) == RDBSS_NTC_NETROOT ) ||
  193. (NodeType(pInstance) == RDBSS_NTC_V_NETROOT ) ||
  194. (NodeType(pInstance) == RDBSS_NTC_SRVOPEN ) ||
  195. (NodeType(pInstance) == RDBSS_NTC_FOBX ));
  196. FinalRefCount = InterlockedDecrement(&pNode->NodeReferenceCount);
  197. ASSERT(FinalRefCount >= 0);
  198. IF_DEBUG {
  199. switch (NodeType(pInstance)) {
  200. case RDBSS_NTC_SRVCALL :
  201. {
  202. PSRV_CALL ThisSrvCall = (PSRV_CALL)pInstance;
  203. PRINT_REF_COUNT(SRVCALL,ThisSrvCall->NodeReferenceCount);
  204. RxDbgTrace( 0, Dbg, (" RxDereferenceSrvCall %08lx %wZ RefCount=%lx\n", ThisSrvCall
  205. , &ThisSrvCall->PrefixEntry.Prefix
  206. , ThisSrvCall->NodeReferenceCount));
  207. }
  208. break;
  209. case RDBSS_NTC_NETROOT :
  210. {
  211. PNET_ROOT ThisNetRoot = (PNET_ROOT)pInstance;
  212. PRINT_REF_COUNT(NETROOT,ThisNetRoot->NodeReferenceCount);
  213. RxDbgTrace( 0, Dbg, (" RxDereferenceNetRoot %08lx %wZ RefCount=%lx\n", ThisNetRoot
  214. , &ThisNetRoot->PrefixEntry.Prefix
  215. , ThisNetRoot->NodeReferenceCount));
  216. }
  217. break;
  218. case RDBSS_NTC_V_NETROOT:
  219. {
  220. PV_NET_ROOT ThisVNetRoot = (PV_NET_ROOT)pInstance;
  221. PRINT_REF_COUNT(VNETROOT,ThisVNetRoot->NodeReferenceCount);
  222. RxDbgTrace( 0, Dbg, (" RxDereferenceVNetRoot %08lx %wZ RefCount=%lx\n", ThisVNetRoot
  223. , &ThisVNetRoot->PrefixEntry.Prefix
  224. , ThisVNetRoot->NodeReferenceCount));
  225. }
  226. break;
  227. case RDBSS_NTC_SRVOPEN :
  228. {
  229. PSRV_OPEN ThisSrvOpen = (PSRV_OPEN)pInstance;
  230. PRINT_REF_COUNT(SRVOPEN,ThisSrvOpen->NodeReferenceCount);
  231. RxDbgTrace( 0, Dbg, (" RxDereferenceSrvOpen %08lx %wZ RefCount=%lx\n", ThisSrvOpen
  232. , &ThisSrvOpen->Fcb->FcbTableEntry.Path
  233. , ThisSrvOpen->NodeReferenceCount));
  234. }
  235. break;
  236. case RDBSS_NTC_FOBX:
  237. {
  238. PFOBX ThisFobx = (PFOBX)pInstance;
  239. PRINT_REF_COUNT(NETFOBX,ThisFobx->NodeReferenceCount);
  240. RxDbgTrace( 0, Dbg, (" RxDereferenceFobx %08lx %wZ RefCount=%lx\n", ThisFobx
  241. , &ThisFobx->SrvOpen->Fcb->FcbTableEntry.Path
  242. , ThisFobx->NodeReferenceCount));
  243. }
  244. break;
  245. default:
  246. break;
  247. }
  248. }
  249. // if the final reference count was greater then one no finalization is required.
  250. if (FinalRefCount <= 1) {
  251. if (LockHoldingState == LHS_ExclusiveLockHeld) {
  252. // if the reference count was 1 and the lock modes were satisfactory,
  253. // the instance can be finalized immediately.
  254. fFinalizeInstance = TRUE;
  255. if ((pNode->NodeTypeCode & RX_SCAVENGER_MASK) != 0) {
  256. RxpUndoScavengerFinalizationMarking(pInstance);
  257. }
  258. } else {
  259. switch (NodeType(pInstance)) {
  260. case RDBSS_NTC_FOBX:
  261. if (FinalRefCount != 0) {
  262. break;
  263. }
  264. // fall thru intentional if refcount == 1 for FOBXs
  265. case RDBSS_NTC_SRVCALL:
  266. case RDBSS_NTC_NETROOT:
  267. case RDBSS_NTC_V_NETROOT:
  268. // the data structure cannot be freed at this time owing to the mode in which
  269. // the lock has been acquired ( or not having the lock at all ).
  270. RxpMarkInstanceForScavengedFinalization(pInstance);
  271. break;
  272. default:
  273. break;
  274. }
  275. }
  276. }
  277. RxReleaseScavengerMutex();
  278. if (fFinalizeInstance) {
  279. switch (NodeType(pInstance)) {
  280. case RDBSS_NTC_SRVCALL:
  281. {
  282. //ASSERT( RxIsPrefixTableLockAcquired( &RxNetNameTable ));
  283. IF_DEBUG {
  284. PRDBSS_DEVICE_OBJECT RxDeviceObject = ((PSRV_CALL)pInstance)->RxDeviceObject;
  285. ASSERT( RxDeviceObject != NULL );
  286. ASSERT( RxIsPrefixTableLockAcquired( RxDeviceObject->pRxNetNameTable ));
  287. }
  288. RxFinalizeSrvCall((PSRV_CALL)pInstance,TRUE,TRUE);
  289. }
  290. break;
  291. case RDBSS_NTC_NETROOT:
  292. {
  293. //ASSERT( RxIsPrefixTableLockAcquired( &RxNetNameTable ));
  294. IF_DEBUG {
  295. PSRV_CALL SrvCall = ((PNET_ROOT)pInstance)->SrvCall;
  296. PRDBSS_DEVICE_OBJECT RxDeviceObject = SrvCall->RxDeviceObject;
  297. ASSERT( RxDeviceObject != NULL );
  298. ASSERT( RxIsPrefixTableLockAcquired( RxDeviceObject->pRxNetNameTable ));
  299. }
  300. RxFinalizeNetRoot((PNET_ROOT)pInstance,TRUE,TRUE);
  301. }
  302. break;
  303. case RDBSS_NTC_V_NETROOT:
  304. {
  305. //ASSERT( RxIsPrefixTableLockAcquired( &RxNetNameTable ));
  306. IF_DEBUG {
  307. PSRV_CALL SrvCall = ((PV_NET_ROOT)pInstance)->NetRoot->SrvCall;
  308. PRDBSS_DEVICE_OBJECT RxDeviceObject = SrvCall->RxDeviceObject;
  309. ASSERT( RxDeviceObject != NULL );
  310. ASSERT( RxIsPrefixTableLockAcquired( RxDeviceObject->pRxNetNameTable ));
  311. }
  312. RxFinalizeVNetRoot((PV_NET_ROOT)pInstance,TRUE,TRUE);
  313. }
  314. break;
  315. case RDBSS_NTC_SRVOPEN:
  316. {
  317. PSRV_OPEN ThisSrvOpen = (PSRV_OPEN)pInstance;
  318. ASSERT(RxIsFcbAcquired(ThisSrvOpen->Fcb));
  319. if (ThisSrvOpen->OpenCount == 0) {
  320. RxFinalizeSrvOpen(ThisSrvOpen,FALSE,FALSE);
  321. }
  322. }
  323. break;
  324. case RDBSS_NTC_FOBX:
  325. {
  326. PFOBX ThisFobx = (PFOBX)pInstance;
  327. ASSERT(RxIsFcbAcquired( ThisFobx->SrvOpen->Fcb));
  328. RxFinalizeNetFobx(ThisFobx,TRUE,FALSE);
  329. }
  330. break;
  331. default:
  332. break;
  333. }
  334. }
  335. }
  336. VOID
  337. RxReference(
  338. OUT PVOID pInstance)
  339. /*++
  340. Routine Description:
  341. The routine adjusts the reference count on the instance.
  342. Arguments:
  343. pInstance - the instance being referenced
  344. Return Value:
  345. RxStatus(SUCESS) is successful
  346. RxStatus(UNSUCCESSFUL) otherwise.
  347. --*/
  348. {
  349. LONG FinalRefCount;
  350. NODE_TYPE_CODE_AND_SIZE *pNode = (PNODE_TYPE_CODE_AND_SIZE)pInstance;
  351. USHORT InstanceType;
  352. PAGED_CODE();
  353. RxAcquireScavengerMutex();
  354. InstanceType = pNode->NodeTypeCode & ~RX_SCAVENGER_MASK;
  355. ASSERT((InstanceType == RDBSS_NTC_SRVCALL ) ||
  356. (InstanceType == RDBSS_NTC_NETROOT ) ||
  357. (InstanceType == RDBSS_NTC_V_NETROOT ) ||
  358. (InstanceType == RDBSS_NTC_SRVOPEN ) ||
  359. (InstanceType == RDBSS_NTC_FOBX ));
  360. FinalRefCount = InterlockedIncrement(&pNode->NodeReferenceCount);
  361. IF_DEBUG {
  362. if (pNode->NodeTypeCode & RX_SCAVENGER_MASK) {
  363. RxDbgTrace(0,Dbg,("Referencing Scavenged instance -- Type %lx\n",InstanceType));
  364. }
  365. switch (InstanceType) {
  366. case RDBSS_NTC_SRVCALL :
  367. {
  368. PSRV_CALL ThisSrvCall = (PSRV_CALL)pInstance;
  369. PRINT_REF_COUNT(SRVCALL,ThisSrvCall->NodeReferenceCount);
  370. RxDbgTrace( 0, Dbg, (" RxReferenceSrvCall %08lx %wZ RefCount=%lx\n", ThisSrvCall
  371. , &ThisSrvCall->PrefixEntry.Prefix
  372. , ThisSrvCall->NodeReferenceCount));
  373. }
  374. break;
  375. case RDBSS_NTC_NETROOT :
  376. {
  377. PNET_ROOT ThisNetRoot = (PNET_ROOT)pInstance;
  378. PRINT_REF_COUNT(NETROOT,ThisNetRoot->NodeReferenceCount);
  379. RxDbgTrace( 0, Dbg, (" RxReferenceNetRoot %08lx %wZ RefCount=%lx\n", ThisNetRoot
  380. , &ThisNetRoot->PrefixEntry.Prefix
  381. , ThisNetRoot->NodeReferenceCount));
  382. }
  383. break;
  384. case RDBSS_NTC_V_NETROOT:
  385. {
  386. PV_NET_ROOT ThisVNetRoot = (PV_NET_ROOT)pInstance;
  387. PRINT_REF_COUNT(VNETROOT,ThisVNetRoot->NodeReferenceCount);
  388. RxDbgTrace( 0, Dbg, (" RxReferenceVNetRoot %08lx %wZ RefCount=%lx\n", ThisVNetRoot
  389. , &ThisVNetRoot->PrefixEntry.Prefix
  390. , ThisVNetRoot->NodeReferenceCount));
  391. }
  392. break;
  393. case RDBSS_NTC_SRVOPEN :
  394. {
  395. PSRV_OPEN ThisSrvOpen = (PSRV_OPEN)pInstance;
  396. PRINT_REF_COUNT(SRVOPEN,ThisSrvOpen->NodeReferenceCount);
  397. RxDbgTrace( 0, Dbg, (" RxReferenceSrvOpen %08lx %wZ RefCount=%lx\n", ThisSrvOpen
  398. , &ThisSrvOpen->Fcb->FcbTableEntry.Path
  399. , ThisSrvOpen->NodeReferenceCount));
  400. }
  401. break;
  402. case RDBSS_NTC_FOBX:
  403. {
  404. PFOBX ThisFobx = (PFOBX)pInstance;
  405. PRINT_REF_COUNT(NETFOBX,ThisFobx->NodeReferenceCount);
  406. RxDbgTrace( 0, Dbg, (" RxReferenceFobx %08lx %wZ RefCount=%lx\n", ThisFobx
  407. , &ThisFobx->SrvOpen->Fcb->FcbTableEntry.Path
  408. , ThisFobx->NodeReferenceCount));
  409. }
  410. break;
  411. default:
  412. {
  413. ASSERT(!"Valid node type for referencing");
  414. }
  415. break;
  416. }
  417. }
  418. RxpUndoScavengerFinalizationMarking(pInstance);
  419. RxReleaseScavengerMutex();
  420. }
  421. VOID
  422. RxpReferenceNetFcb(
  423. PFCB pFcb)
  424. /*++
  425. Routine Description:
  426. The routine adjusts the reference count on the FCB.
  427. Arguments:
  428. pFcb - the SrvCall being referenced
  429. Return Value:
  430. RxStatus(SUCESS) is successful
  431. RxStatus(UNSUCCESSFUL) otherwise.
  432. --*/
  433. {
  434. LONG FinalRefCount;
  435. PAGED_CODE();
  436. ASSERT(NodeTypeIsFcb(pFcb));
  437. FinalRefCount = InterlockedIncrement(&pFcb->NodeReferenceCount);
  438. IF_DEBUG {
  439. PRINT_REF_COUNT(NETFCB,pFcb->NodeReferenceCount);
  440. RxDbgTrace( 0, Dbg, (" RxReferenceNetFcb %08lx %wZ RefCount=%lx\n", pFcb
  441. , &pFcb->FcbTableEntry.Path
  442. , pFcb->NodeReferenceCount));
  443. }
  444. }
  445. LONG
  446. RxpDereferenceNetFcb(
  447. PFCB pFcb)
  448. /*++
  449. Routine Description:
  450. The routine adjust the reference count on an instance of the reference counted data
  451. structures in RDBSS exlcuding the FCB.
  452. Arguments:
  453. pFcb -- the FCB being dereferenced
  454. Return Value:
  455. none.
  456. Notes:
  457. The referencing and dereferencing of FCB's is different from those of the other data
  458. structures because of the embedded resource in the FCB. This implies that the caller
  459. requires information regarding the status of the FCB ( whether it was finalized or not )
  460. In order to finalize the FCB two locks need to be held, the NET_ROOT's name table lock as
  461. well as the FCB resource.
  462. These considerations lead us to adopt a different approach in dereferencing FCB's. The
  463. dereferencing routine does not even attempt to finalize the FCB
  464. --*/
  465. {
  466. LONG FinalRefCount;
  467. PAGED_CODE();
  468. ASSERT(NodeTypeIsFcb(pFcb));
  469. FinalRefCount = InterlockedDecrement(&pFcb->NodeReferenceCount);
  470. ASSERT(FinalRefCount >= 0);
  471. IF_DEBUG {
  472. PRINT_REF_COUNT(NETFCB,pFcb->NodeReferenceCount);
  473. RxDbgTrace( 0, Dbg, (" RxDereferenceNetFcb %08lx %wZ RefCount=%lx\n", pFcb
  474. , &pFcb->FcbTableEntry.Path
  475. , pFcb->NodeReferenceCount));
  476. }
  477. return(FinalRefCount);
  478. }
  479. BOOLEAN
  480. RxpDereferenceAndFinalizeNetFcb(
  481. PFCB pFcb,
  482. PRX_CONTEXT RxContext,
  483. BOOLEAN RecursiveFinalize,
  484. BOOLEAN ForceFinalize)
  485. /*++
  486. Routine Description:
  487. The routine adjust the reference count aw well as finalizes the FCB if required
  488. Arguments:
  489. pFcb -- the FCB being dereferenced
  490. RxContext -- the context for releasing/acquiring FCB.
  491. RecursiveFinalize -- recursive finalization
  492. ForceFinalize -- force finalization
  493. Return Value:
  494. none.
  495. Notes:
  496. The referencing and dereferencing of FCB's is different from those of the other data
  497. structures because of the embedded resource in the FCB. This implies that the caller
  498. requires information regarding the status of the FCB ( whether it was finalized or not )
  499. In order to finalize the FCB two locks need to be held, the NET_ROOT's name table lock as
  500. well as the FCB resource.
  501. This routine acquires the additional lock if required.
  502. --*/
  503. {
  504. BOOLEAN NodeActuallyFinalized = FALSE;
  505. LONG FinalRefCount;
  506. PAGED_CODE();
  507. ASSERT(!ForceFinalize);
  508. ASSERT(NodeTypeIsFcb(pFcb));
  509. ASSERT(RxIsFcbAcquiredExclusive(pFcb));
  510. FinalRefCount = InterlockedDecrement(&pFcb->NodeReferenceCount);
  511. if (ForceFinalize ||
  512. RecursiveFinalize ||
  513. ((pFcb->OpenCount == 0) &&
  514. (pFcb->UncleanCount == 0) &&
  515. (FinalRefCount <= 1))) {
  516. BOOLEAN PrefixTableLockAcquired = FALSE;
  517. PNET_ROOT pNetRoot;
  518. NTSTATUS Status = (STATUS_SUCCESS);
  519. if (!FlagOn(pFcb->FcbState,FCB_STATE_ORPHANED)) {
  520. pNetRoot = (PNET_ROOT)pFcb->VNetRoot->NetRoot;
  521. // An insurance reference to ensure that the NET ROOT does not dissapear
  522. RxReferenceNetRoot(pNetRoot);
  523. // In all these cases the FCB is likely to be finalized
  524. if (!RxIsFcbTableLockExclusive(&pNetRoot->FcbTable)) {
  525. RxReferenceNetFcb(pFcb); // get ready to refresh the finalrefcount after we get the tablelock
  526. if (!RxAcquireFcbTableLockExclusive(&pNetRoot->FcbTable, FALSE) ) {
  527. if ((RxContext != NULL) &&
  528. (RxContext != CHANGE_BUFFERING_STATE_CONTEXT) &&
  529. (RxContext != CHANGE_BUFFERING_STATE_CONTEXT_WAIT)) {
  530. SetFlag(RxContext->Flags,RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK);
  531. }
  532. RxReleaseFcb(RxContext,pFcb );
  533. (VOID)RxAcquireFcbTableLockExclusive(&pNetRoot->FcbTable, TRUE);
  534. Status = RxAcquireExclusiveFcb(RxContext, pFcb);
  535. }
  536. FinalRefCount = RxDereferenceNetFcb(pFcb);
  537. PrefixTableLockAcquired = TRUE;
  538. }
  539. } else {
  540. pNetRoot = NULL;
  541. }
  542. if (Status == (STATUS_SUCCESS)) {
  543. NodeActuallyFinalized = RxFinalizeNetFcb(pFcb,RecursiveFinalize,ForceFinalize,FinalRefCount);
  544. }
  545. if (PrefixTableLockAcquired) {
  546. RxReleaseFcbTableLock(&pNetRoot->FcbTable);
  547. }
  548. if (pNetRoot != NULL) {
  549. RxDereferenceNetRoot(pNetRoot,LHS_LockNotHeld);
  550. }
  551. }
  552. return NodeActuallyFinalized;
  553. }
  554. VOID
  555. RxWaitForStableCondition(
  556. IN PRX_BLOCK_CONDITION pCondition,
  557. IN OUT PLIST_ENTRY pTransitionWaitList,
  558. IN OUT PRX_CONTEXT pRxContext,
  559. OUT NTSTATUS *AsyncStatus OPTIONAL)
  560. /*++
  561. Routine Description:
  562. The routine checks to see if the condition is stable. If not, it
  563. is suspended till a stable condition is attained. when a stable condition is
  564. obtained, either the rxcontext sync event is set or the context is posted...depending
  565. on the POST_ON_STABLE_CONDITION context flag. the flag is cleared on a post.
  566. Arguments:
  567. Condition - the condition variable we're waiting on
  568. Resource - the resrouce used to control access to the containing block
  569. RxContext - the RX context
  570. Return Value:
  571. RXSTATUS - PENDING if notstable and the context will be posted
  572. SUCCESS otherwise
  573. --*/
  574. {
  575. NTSTATUS DummyStatus;
  576. BOOLEAN Wait = FALSE;
  577. PAGED_CODE();
  578. if (AsyncStatus == NULL) {
  579. AsyncStatus = &DummyStatus;
  580. }
  581. *AsyncStatus = (STATUS_SUCCESS);
  582. if (StableCondition(*pCondition))
  583. return; //early out could macroize
  584. #ifndef WIN9X
  585. RxAcquireSerializationMutex();
  586. #endif
  587. if (!StableCondition(*pCondition)) {
  588. RxInsertContextInSerializationQueue(pTransitionWaitList,pRxContext);
  589. if (!FlagOn(pRxContext->Flags,RX_CONTEXT_FLAG_POST_ON_STABLE_CONDITION)){
  590. Wait = TRUE;
  591. } else {
  592. *AsyncStatus = (STATUS_PENDING);
  593. }
  594. }
  595. #ifndef WIN9X
  596. RxReleaseSerializationMutex();
  597. #endif WIN9X
  598. if (Wait) {
  599. RxWaitSync(pRxContext);
  600. }
  601. return;
  602. }
  603. VOID
  604. RxUpdateCondition (
  605. IN RX_BLOCK_CONDITION NewCondition,
  606. OUT PRX_BLOCK_CONDITION pCondition,
  607. IN OUT PLIST_ENTRY pTransitionWaitList)
  608. /*++
  609. Routine Description:
  610. The routine unwaits the guys waiting on the transition event and the condition is set
  611. according to the parameter passed.
  612. Arguments:
  613. NewConditionValue - the new value of the condition variable
  614. pCondition - variable (i.e. a ptr) to the transitioning condition
  615. pTransitionWaitList - list of contexts waiting for the transition.
  616. Notes:
  617. The resource associated with the data structure instance being modified must have been
  618. acquired exclusively before invoking this routine, i.e., for SRV_CALL,NET_ROOT and V_NET_ROOT
  619. the net name table lock must be acquired and for FCB's the associated resource.
  620. --*/
  621. {
  622. LIST_ENTRY TargetListHead;
  623. PRX_CONTEXT pRxContext;
  624. PAGED_CODE();
  625. #ifndef WIN9X
  626. RxAcquireSerializationMutex();
  627. #endif
  628. ASSERT(NewCondition != Condition_InTransition);
  629. *pCondition = NewCondition;
  630. RxTransferList(&TargetListHead,pTransitionWaitList);
  631. #ifndef WIN9X
  632. RxReleaseSerializationMutex();
  633. #endif
  634. while (pRxContext = RxRemoveFirstContextFromSerializationQueue(&TargetListHead)) {
  635. if (!FlagOn(pRxContext->Flags,RX_CONTEXT_FLAG_POST_ON_STABLE_CONDITION)){
  636. RxSignalSynchronousWaiter(pRxContext);
  637. } else {
  638. ClearFlag(pRxContext->Flags,RX_CONTEXT_FLAG_POST_ON_STABLE_CONDITION);
  639. RxFsdPostRequest(pRxContext);
  640. }
  641. }
  642. }
  643. PVOID
  644. RxAllocateObject(
  645. NODE_TYPE_CODE NodeType,
  646. PMINIRDR_DISPATCH pMRxDispatch,
  647. ULONG NameLength)
  648. /*++
  649. Routine Description:
  650. The routine allocates and constructs the skeleton of a SRV_CALL/NET_ROOT/V_NET_ROOT
  651. instance.
  652. Arguments:
  653. NodeType - the node type
  654. pMRxDispatch - the Mini redirector dispatch vector
  655. NameLength - name size.
  656. Notes:
  657. The reasons as to why the allocation/freeing of these data structures have been
  658. centralized are as follows
  659. 1) The construction of these three data types have a lot in common with the exception
  660. of the initial computation of sizes. Therefore centralization minimizes the footprint.
  661. 2) It allows us to experiment with different clustering/allocation strategies.
  662. 3) It allows the incorporation of debug support in an easy way.
  663. There are two special cases of interest in the allocation strategy ...
  664. 1) The data structures for the wrapper as well as the corresponding mini redirector
  665. are allocated adjacent to each other. This ensures spatial locality.
  666. 2) The one exception to the above rule is the SRV_CALL data structure. This is because
  667. of the bootstrapping problem. A SRV_CALL skeleton needs to be created which is then passed
  668. around to each of the mini redirectors. Therefore adoption of rule (1) is not possible.
  669. Further there can be more than one mini redirector laying claim to a particular server. In
  670. consideration of these things SRV_CALL's need to be treated as an exception to (1). However
  671. once a particular mini redirector has been selected as the winner it would be advantageous
  672. to colocate the data structure to derive the associated performance benefits. This has not
  673. been implemented as yet.
  674. --*/
  675. {
  676. ULONG PoolTag;
  677. ULONG RdbssNodeSize,MRxNodeSize;
  678. BOOLEAN fInitializeContextFields = FALSE;
  679. PNODE_TYPE_CODE_AND_SIZE pNode;
  680. PAGED_CODE();
  681. RdbssNodeSize = MRxNodeSize = 0;
  682. switch (NodeType) {
  683. case RDBSS_NTC_SRVCALL :
  684. {
  685. PoolTag = RX_SRVCALL_POOLTAG;
  686. RdbssNodeSize = QuadAlign(sizeof(SRV_CALL));
  687. if (pMRxDispatch != NULL) {
  688. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_SRV_CALL_EXTENSION) {
  689. MRxNodeSize = QuadAlign(pMRxDispatch->MRxSrvCallSize);
  690. }
  691. }
  692. }
  693. break;
  694. case RDBSS_NTC_NETROOT:
  695. {
  696. PoolTag = RX_NETROOT_POOLTAG;
  697. RdbssNodeSize = QuadAlign(sizeof(NET_ROOT));
  698. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_NET_ROOT_EXTENSION) {
  699. MRxNodeSize = QuadAlign(pMRxDispatch->MRxNetRootSize);
  700. }
  701. }
  702. break;
  703. case RDBSS_NTC_V_NETROOT:
  704. {
  705. PoolTag = RX_V_NETROOT_POOLTAG;
  706. RdbssNodeSize = QuadAlign(sizeof(V_NET_ROOT));
  707. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_V_NET_ROOT_EXTENSION) {
  708. MRxNodeSize = QuadAlign(pMRxDispatch->MRxVNetRootSize);
  709. }
  710. }
  711. break;
  712. default:
  713. ASSERT(!"Invalid Node Type for allocation/Initialization");
  714. return NULL;
  715. }
  716. pNode = RxAllocatePoolWithTag(
  717. NonPagedPool,
  718. (RdbssNodeSize + MRxNodeSize + NameLength),
  719. PoolTag);
  720. if (pNode != NULL) {
  721. ULONG NodeSize;
  722. PVOID *pContextPtr;
  723. PRX_PREFIX_ENTRY pPrefixEntry = NULL;
  724. NodeSize = RdbssNodeSize + MRxNodeSize;
  725. ZeroAndInitializeNodeType(pNode, NodeType, (NodeSize + NameLength));
  726. switch (NodeType) {
  727. case RDBSS_NTC_SRVCALL:
  728. {
  729. PSRV_CALL pSrvCall = (PSRV_CALL)pNode;
  730. pContextPtr = &pSrvCall->Context;
  731. pPrefixEntry = &pSrvCall->PrefixEntry;
  732. // Set up the name pointer in the MRX_SRV_CALL structure ..
  733. pSrvCall->pSrvCallName = &pSrvCall->PrefixEntry.Prefix;
  734. }
  735. break;
  736. case RDBSS_NTC_NETROOT:
  737. {
  738. PNET_ROOT pNetRoot = (PNET_ROOT)pNode;
  739. pContextPtr = &pNetRoot->Context;
  740. pPrefixEntry = &pNetRoot->PrefixEntry;
  741. // Set up the net root name pointer in the MRX_NET_ROOT structure
  742. pNetRoot->pNetRootName = &pNetRoot->PrefixEntry.Prefix;
  743. }
  744. break;
  745. case RDBSS_NTC_V_NETROOT:
  746. {
  747. PV_NET_ROOT pVNetRoot = (PV_NET_ROOT)pNode;
  748. pContextPtr = &pVNetRoot->Context;
  749. pPrefixEntry = &pVNetRoot->PrefixEntry;
  750. }
  751. break;
  752. default:
  753. break;
  754. }
  755. if (pPrefixEntry != NULL) {
  756. ZeroAndInitializeNodeType(
  757. pPrefixEntry,
  758. RDBSS_NTC_PREFIX_ENTRY,
  759. sizeof( RX_PREFIX_ENTRY ));
  760. pPrefixEntry->Prefix.Buffer = (PWCH)((PCHAR)pNode + NodeSize);
  761. pPrefixEntry->Prefix.Length = (USHORT)NameLength;
  762. pPrefixEntry->Prefix.MaximumLength = (USHORT)NameLength;
  763. }
  764. if (MRxNodeSize > 0) {
  765. *pContextPtr = (PBYTE)pNode + RdbssNodeSize;
  766. }
  767. }
  768. return pNode;
  769. }
  770. VOID
  771. RxFreeObject(PVOID pObject)
  772. /*++
  773. Routine Description:
  774. The routine frees a SRV_CALL/V_NET_ROOT/NET_ROOT instance
  775. Arguments:
  776. pObject - the instance to be freed
  777. Notes:
  778. --*/
  779. {
  780. PAGED_CODE();
  781. IF_DEBUG {
  782. switch (NodeType(pObject)) {
  783. case RDBSS_NTC_SRVCALL :
  784. {
  785. PSRV_CALL pSrvCall = (PSRV_CALL)pObject;
  786. if (pSrvCall->RxDeviceObject != NULL) {
  787. if (!(pSrvCall->RxDeviceObject->Dispatch->MRxFlags & RDBSS_MANAGE_SRV_CALL_EXTENSION)) {
  788. ASSERT(pSrvCall->Context == NULL);
  789. }
  790. ASSERT(pSrvCall->Context2 == NULL);
  791. pSrvCall->RxDeviceObject = NULL;
  792. }
  793. }
  794. break;
  795. case RDBSS_NTC_NETROOT :
  796. {
  797. PNET_ROOT pNetRoot = (PNET_ROOT)pObject;
  798. pNetRoot->SrvCall = NULL;
  799. //pNetRoot->Dispatch = NULL;
  800. pNetRoot->NodeTypeCode |= 0xf000;
  801. }
  802. break;
  803. case RDBSS_NTC_V_NETROOT :
  804. {
  805. }
  806. break;
  807. default:
  808. break;
  809. }
  810. }
  811. RxFreePool(pObject);
  812. }
  813. VOID
  814. RxFinalizeNetTable (
  815. PRDBSS_DEVICE_OBJECT RxDeviceObject,
  816. BOOLEAN fForceFinalization
  817. )
  818. /*++
  819. Routine Description:
  820. This routine finalizes the net table.
  821. --*/
  822. {
  823. BOOLEAN fMorePassesRequired = TRUE;
  824. PLIST_ENTRY pListEntry;
  825. NODE_TYPE_CODE DesiredNodeType;
  826. PRX_PREFIX_TABLE pRxNetNameTable = RxDeviceObject->pRxNetNameTable;
  827. PAGED_CODE();
  828. RxDbgTrace(+1, Dbg, ("RxForceNetTableFinalization at the TOP\n"));
  829. RxLog(("FINALNETT\n"));
  830. RxWmiLog(LOG,
  831. RxFinalizeNetTable_1,
  832. LOGPTR(RxDeviceObject));
  833. RxAcquirePrefixTableLockExclusive( pRxNetNameTable, TRUE); //could be hosed if rogue!
  834. DesiredNodeType = RDBSS_NTC_V_NETROOT;
  835. RxAcquireScavengerMutex();
  836. while (fMorePassesRequired) {
  837. for (pListEntry = pRxNetNameTable->MemberQueue.Flink;
  838. pListEntry != &(pRxNetNameTable->MemberQueue); ) {
  839. BOOLEAN NodeFinalized;
  840. PVOID pContainer;
  841. PRX_PREFIX_ENTRY PrefixEntry;
  842. PLIST_ENTRY pPrevEntry;
  843. PrefixEntry = CONTAINING_RECORD( pListEntry, RX_PREFIX_ENTRY, MemberQLinks );
  844. ASSERT (NodeType(PrefixEntry) == RDBSS_NTC_PREFIX_ENTRY);
  845. pContainer = (PrefixEntry->ContainingRecord);
  846. RxDbgTrace(0, Dbg, ("RxForceNetTableFinalization ListEntry PrefixEntry Container"
  847. "=--> %08lx %08lx %08lx\n", pListEntry, PrefixEntry, pContainer));
  848. RxLog(("FINALNETT: %lx %wZ\n", pContainer, &PrefixEntry->Prefix));
  849. RxWmiLog(LOG,
  850. RxFinalizeNetTable_2,
  851. LOGPTR(pContainer)
  852. LOGUSTR(PrefixEntry->Prefix));
  853. pListEntry = pListEntry->Flink;
  854. if (pContainer != NULL) {
  855. RxpUndoScavengerFinalizationMarking(pContainer);
  856. if (NodeType(pContainer) == DesiredNodeType) {
  857. switch (NodeType(pContainer)) {
  858. case RDBSS_NTC_SRVCALL :
  859. NodeFinalized = RxFinalizeSrvCall((PSRV_CALL)pContainer,TRUE,fForceFinalization);
  860. break;
  861. case RDBSS_NTC_NETROOT :
  862. NodeFinalized = RxFinalizeNetRoot((PNET_ROOT)pContainer,TRUE,fForceFinalization);
  863. break;
  864. case RDBSS_NTC_V_NETROOT :
  865. {
  866. PV_NET_ROOT pVNetRoot = (PV_NET_ROOT)pContainer;
  867. ULONG AdditionalReferenceTaken;
  868. AdditionalReferenceTaken = InterlockedCompareExchange(
  869. &pVNetRoot->AdditionalReferenceForDeleteFsctlTaken,
  870. 0,
  871. 1);
  872. if (AdditionalReferenceTaken) {
  873. RxDereferenceVNetRoot(pVNetRoot,LHS_ExclusiveLockHeld);
  874. NodeFinalized = TRUE;
  875. } else {
  876. NodeFinalized = RxFinalizeVNetRoot((PV_NET_ROOT)pContainer,TRUE,fForceFinalization);
  877. }
  878. }
  879. break;
  880. }
  881. }
  882. }
  883. }
  884. switch (DesiredNodeType) {
  885. case RDBSS_NTC_SRVCALL :
  886. fMorePassesRequired = FALSE;
  887. break;
  888. case RDBSS_NTC_NETROOT :
  889. DesiredNodeType = RDBSS_NTC_SRVCALL;
  890. break;
  891. case RDBSS_NTC_V_NETROOT :
  892. DesiredNodeType = RDBSS_NTC_NETROOT;
  893. break;
  894. }
  895. }
  896. RxDbgTrace(-1,Dbg,("RxFinalizeNetTable -- Done\n"));
  897. RxReleaseScavengerMutex();
  898. RxReleasePrefixTableLock( pRxNetNameTable );
  899. }
  900. NTSTATUS
  901. RxFinalizeConnection(
  902. IN OUT PNET_ROOT NetRoot,
  903. IN OUT PV_NET_ROOT VNetRoot,
  904. IN BOOLEAN Level
  905. )
  906. /*++
  907. Routine Description:
  908. The routine deletes a connection FROM THE USER's PERSPECTIVE. It doesn't disconnect
  909. but it does (with force) close open files. disconnecting is handled either by timeout or by
  910. srvcall finalization.
  911. Arguments:
  912. NetRoot - the NetRoot being finalized
  913. VNetRoot - the VNetRoot being finalized
  914. Level - This is a tri-state
  915. FALSE - fail if files or changenotifications are open
  916. TRUE - succeed no matter waht. orphan files and remove change notifies forcefully
  917. 0xff - take away extra reference on the vnetroot due to add_connection
  918. but otherwise act like FALSE
  919. Return Value:
  920. RxStatus(SUCCESS) if successful.
  921. --*/
  922. {
  923. NTSTATUS Status = STATUS_SUCCESS;
  924. ULONG NumberOfOpenDirectories = 0;
  925. ULONG NumberOfOpenNonDirectories = 0;
  926. ULONG NumberOfFobxs = 0;
  927. LONG AdditionalReferenceForDeleteFsctlTaken = 0;
  928. PLIST_ENTRY ListEntry, NextListEntry;
  929. BOOLEAN PrefixTableLockAcquired,FcbTableLockAcquired;
  930. PRX_PREFIX_TABLE pRxNetNameTable;
  931. BOOLEAN ForceFilesClosed = FALSE;
  932. if (Level==TRUE)
  933. {
  934. ForceFilesClosed = TRUE;
  935. }
  936. PAGED_CODE();
  937. ASSERT( NodeType(NetRoot) == RDBSS_NTC_NETROOT );
  938. pRxNetNameTable = NetRoot->SrvCall->RxDeviceObject->pRxNetNameTable;
  939. Status = RxCancelNotifyChangeDirectoryRequestsForVNetRoot(VNetRoot, ForceFilesClosed);
  940. // either changenotifications were cancelled, or they weren't but we still want to
  941. // do go through in order to either forceclose the files or atleast deref the vnetroot
  942. // of the extra ref taken during ADD_CONNECTION
  943. if ((Status == STATUS_SUCCESS) || (Level != FALSE))
  944. {
  945. // reset the status
  946. Status = STATUS_SUCCESS;
  947. PrefixTableLockAcquired = RxAcquirePrefixTableLockExclusive(
  948. pRxNetNameTable,
  949. TRUE);
  950. //don't let the netroot be finalized yet.......
  951. RxReferenceNetRoot(NetRoot);
  952. FcbTableLockAcquired = RxAcquireFcbTableLockExclusive(
  953. &NetRoot->FcbTable,
  954. TRUE);
  955. try {
  956. if ((Status == STATUS_SUCCESS) && (!VNetRoot->ConnectionFinalizationDone)) {
  957. USHORT BucketNumber;
  958. RxDbgTrace(+1, Dbg, ("RxFinalizeConnection<+> NR= %08lx VNR= %08lx %wZ\n",
  959. NetRoot,VNetRoot,&NetRoot->PrefixEntry.Prefix));
  960. RxLog(("FINALCONN: %lx %wZ\n",NetRoot,&NetRoot->PrefixEntry.Prefix));
  961. RxWmiLog(LOG,
  962. RxFinalizeConnection,
  963. LOGPTR(NetRoot)
  964. LOGUSTR(NetRoot->PrefixEntry.Prefix));
  965. for (BucketNumber = 0;
  966. (BucketNumber < NetRoot->FcbTable.NumberOfBuckets);
  967. BucketNumber++) {
  968. PLIST_ENTRY ListHeader;
  969. ListHeader = &NetRoot->FcbTable.HashBuckets[BucketNumber];
  970. for (ListEntry = ListHeader->Flink;
  971. ListEntry != ListHeader;
  972. ListEntry = NextListEntry ) {
  973. PFCB Fcb;
  974. PRX_FCB_TABLE_ENTRY FcbTableEntry;
  975. NextListEntry = ListEntry->Flink;
  976. FcbTableEntry = CONTAINING_RECORD(
  977. ListEntry,
  978. RX_FCB_TABLE_ENTRY,
  979. HashLinks );
  980. Fcb = CONTAINING_RECORD(
  981. FcbTableEntry,
  982. FCB,
  983. FcbTableEntry);
  984. if (Fcb->VNetRoot != VNetRoot) {
  985. continue;
  986. }
  987. if (Fcb->UncleanCount>0 && !ForceFilesClosed) {
  988. Status = STATUS_CONNECTION_IN_USE; //this is changed later
  989. if (NodeType(Fcb)==RDBSS_NTC_STORAGE_TYPE_DIRECTORY) {
  990. NumberOfOpenDirectories++;
  991. } else {
  992. NumberOfOpenNonDirectories++;
  993. }
  994. continue;
  995. }
  996. ASSERT( NodeTypeIsFcb(Fcb));
  997. RxDbgTrace( 0, Dbg, (" AcquiringFcbLock%c!!\n", '!'));
  998. Status = RxAcquireExclusiveFcb(NULL,Fcb);
  999. ASSERT(Status == STATUS_SUCCESS);
  1000. RxDbgTrace( 0, Dbg, (" AcquiredFcbLock%c!!\n", '!'));
  1001. // Ensure that no more file objects will be marked for a delayed close
  1002. // on this FCB.
  1003. ClearFlag(Fcb->FcbState,FCB_STATE_COLLAPSING_ENABLED);
  1004. RxScavengeRelatedFobxs(Fcb);
  1005. // a small complication here is that this fcb MAY have an open
  1006. // section against it caused by our cacheing the file. if so,
  1007. // we need to purge to get to the close
  1008. RxPurgeFcb(Fcb);
  1009. }
  1010. }
  1011. if (VNetRoot->NumberOfFobxs == 0) {
  1012. VNetRoot->ConnectionFinalizationDone = TRUE;
  1013. }
  1014. }
  1015. NumberOfFobxs = VNetRoot->NumberOfFobxs;
  1016. AdditionalReferenceForDeleteFsctlTaken = VNetRoot->AdditionalReferenceForDeleteFsctlTaken;
  1017. if (ForceFilesClosed) {
  1018. RxFinalizeVNetRoot(VNetRoot,FALSE,TRUE);
  1019. }
  1020. } finally {
  1021. if (FcbTableLockAcquired) {
  1022. RxReleaseFcbTableLock( &NetRoot->FcbTable );
  1023. }
  1024. // We should not delete the remote connection with the file opened.
  1025. if (!ForceFilesClosed && (Status == STATUS_SUCCESS) && (NumberOfFobxs > 0)) {
  1026. Status = STATUS_FILES_OPEN;
  1027. }
  1028. if (Status != STATUS_SUCCESS) {
  1029. if (NumberOfOpenNonDirectories) {
  1030. Status = STATUS_FILES_OPEN;
  1031. }
  1032. }
  1033. if ((Status == STATUS_SUCCESS)||(Level==0xff)){
  1034. // the corresponding reference for this is in RxCreateTreeConnect...
  1035. // please see the comment there...
  1036. if (AdditionalReferenceForDeleteFsctlTaken != 0) {
  1037. VNetRoot->AdditionalReferenceForDeleteFsctlTaken = 0;
  1038. RxDereferenceVNetRoot(VNetRoot,LHS_ExclusiveLockHeld);
  1039. }
  1040. }
  1041. if (PrefixTableLockAcquired) {
  1042. RxDereferenceNetRoot(NetRoot,LHS_ExclusiveLockHeld);
  1043. RxReleasePrefixTableLock( pRxNetNameTable );
  1044. }
  1045. }
  1046. RxDbgTrace(-1, Dbg, ("RxFinalizeConnection<-> Status=%08lx\n", Status));
  1047. }
  1048. return(Status);
  1049. }
  1050. NTSTATUS
  1051. RxInitializeSrvCallParameters(
  1052. PRX_CONTEXT RxContext,
  1053. PSRV_CALL SrvCall)
  1054. /*++
  1055. Routine Description:
  1056. This routine initializes the server call parameters passed in through EA's
  1057. Currently this routine initializes the Server principal name which is passed
  1058. in by the DFS driver.
  1059. Arguments:
  1060. RxContext -- the associated context
  1061. SrvCall -- the Srv Call Instance
  1062. Return Value:
  1063. RxStatus(SUCCESS) if successfull
  1064. Notes:
  1065. The current implementation maps out of memory situations into an error and
  1066. passes it back. If the global strategy is to raise an exception this
  1067. redundant step can be avoided.
  1068. --*/
  1069. {
  1070. NTSTATUS Status = (STATUS_SUCCESS);
  1071. RxCaptureRequestPacket;
  1072. RxCaptureParamBlock;
  1073. ULONG EaInformationLength;
  1074. PAGED_CODE();
  1075. SrvCall->pPrincipalName = NULL;
  1076. if (RxContext->MajorFunction != IRP_MJ_CREATE) {
  1077. return STATUS_SUCCESS;
  1078. }
  1079. EaInformationLength = RxContext->Create.EaLength;
  1080. if (EaInformationLength > 0) {
  1081. PFILE_FULL_EA_INFORMATION pEaEntry;
  1082. pEaEntry = (PFILE_FULL_EA_INFORMATION)RxContext->Create.EaBuffer;
  1083. ASSERT(pEaEntry != NULL);
  1084. for(;;) {
  1085. RxDbgTrace(0,Dbg,("RxExtractSrvCallParams: Processing EA name %s\n",
  1086. pEaEntry->EaName));
  1087. if (strcmp(pEaEntry->EaName, EA_NAME_PRINCIPAL) == 0) {
  1088. if (pEaEntry->EaValueLength > 0) {
  1089. SrvCall->pPrincipalName = (PUNICODE_STRING)
  1090. RxAllocatePoolWithTag(
  1091. NonPagedPool,
  1092. (sizeof(UNICODE_STRING) + pEaEntry->EaValueLength),
  1093. RX_SRVCALL_PARAMS_POOLTAG);
  1094. if (SrvCall->pPrincipalName != NULL) {
  1095. SrvCall->pPrincipalName->Length = pEaEntry->EaValueLength;
  1096. SrvCall->pPrincipalName->MaximumLength = pEaEntry->EaValueLength;
  1097. SrvCall->pPrincipalName->Buffer = (PWCHAR)((PCHAR)SrvCall->pPrincipalName + sizeof(UNICODE_STRING));
  1098. RtlCopyMemory(
  1099. SrvCall->pPrincipalName->Buffer,
  1100. pEaEntry->EaName + pEaEntry->EaNameLength + 1,
  1101. SrvCall->pPrincipalName->Length);
  1102. } else {
  1103. Status = (STATUS_INSUFFICIENT_RESOURCES);
  1104. }
  1105. }
  1106. break;
  1107. }
  1108. if (pEaEntry->NextEntryOffset == 0) {
  1109. break;
  1110. } else {
  1111. pEaEntry = (PFILE_FULL_EA_INFORMATION)
  1112. ((PCHAR) pEaEntry + pEaEntry->NextEntryOffset);
  1113. }
  1114. }
  1115. }
  1116. return Status;
  1117. }
  1118. PSRV_CALL
  1119. RxCreateSrvCall (
  1120. IN PRX_CONTEXT RxContext,
  1121. IN PUNICODE_STRING Name,
  1122. IN PUNICODE_STRING InnerNamePrefix OPTIONAL,
  1123. IN PRX_CONNECTION_ID RxConnectionId
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. The routine builds a node representing a server call context and inserts the name into the net
  1128. name table. Optionally, it "co-allocates" a netroot structure as well. Appropriate alignment is
  1129. respected for the enclosed netroot. The name(s) is(are) allocated at the end of the block. The
  1130. reference count on the block is set to 1 (2 if enclosed netroot) on this create to account for
  1131. ptr returned.
  1132. Arguments:
  1133. RxContext - the RDBSS context
  1134. Name - the name to be inserted
  1135. Dispatch - pointer to the minirdr dispatch table
  1136. Return Value:
  1137. Ptr to the created srvcall.
  1138. --*/
  1139. {
  1140. PSRV_CALL ThisSrvCall;
  1141. PRX_PREFIX_ENTRY ThisEntry;
  1142. ULONG NameSize,PrefixNameSize;
  1143. PAGED_CODE();
  1144. RxDbgTrace(+1, Dbg, ("RxSrvCallCreate--> Name = %wZ\n", Name));
  1145. ASSERT ( RxIsPrefixTableLockExclusive ( RxContext->RxDeviceObject->pRxNetNameTable ) );
  1146. NameSize = Name->Length + sizeof(WCHAR) * 2;
  1147. if (InnerNamePrefix) {
  1148. PrefixNameSize = InnerNamePrefix->Length;
  1149. } else {
  1150. PrefixNameSize = 0;
  1151. }
  1152. ThisSrvCall = RxAllocateObject(RDBSS_NTC_SRVCALL,NULL,(NameSize + PrefixNameSize));
  1153. if (ThisSrvCall != NULL) {
  1154. ThisSrvCall->SerialNumberForEnum = SerialNumber++;
  1155. ThisSrvCall->RxDeviceObject = RxContext->RxDeviceObject;
  1156. RxInitializeBufferingManager(ThisSrvCall);
  1157. InitializeListHead(&ThisSrvCall->ScavengerFinalizationList);
  1158. InitializeListHead(&ThisSrvCall->TransitionWaitList);
  1159. RxInitializePurgeSyncronizationContext(
  1160. &ThisSrvCall->PurgeSyncronizationContext);
  1161. #ifndef WIN9X
  1162. RxInitializeSrvCallParameters(RxContext,ThisSrvCall);
  1163. #endif
  1164. RtlMoveMemory(
  1165. ThisSrvCall->PrefixEntry.Prefix.Buffer,
  1166. Name->Buffer,
  1167. Name->Length);
  1168. ThisEntry = &ThisSrvCall->PrefixEntry;
  1169. ThisEntry->Prefix.MaximumLength = (USHORT)NameSize;
  1170. ThisEntry->Prefix.Length = Name->Length;
  1171. RxPrefixTableInsertName (
  1172. RxContext->RxDeviceObject->pRxNetNameTable,
  1173. ThisEntry,
  1174. (PVOID)ThisSrvCall,
  1175. &ThisSrvCall->NodeReferenceCount,
  1176. Name->Length,
  1177. RxConnectionId); //make the whole srvcallname case insensitive
  1178. RxDbgTrace(-1, Dbg, ("RxSrvCallCreate -> RefCount = %08lx\n", ThisSrvCall->NodeReferenceCount));
  1179. }
  1180. return ThisSrvCall;
  1181. }
  1182. NTSTATUS
  1183. RxSetSrvCallDomainName(
  1184. PMRX_SRV_CALL pSrvCall,
  1185. PUNICODE_STRING pDomainName)
  1186. /*++
  1187. Routine Description:
  1188. The routine sets the domain name associated with any given server.
  1189. Arguments:
  1190. pSrvCall - the SrvCall
  1191. pDomainName - the DOMAIN to which the server belongs.
  1192. Return Value:
  1193. RxStatus(SUCCESS) if successful
  1194. Notes:
  1195. This is one of the callback routines provided in the wrapper for the mini redirectors.
  1196. Since the Domain name is not often known at the beginning this mechanism has to be
  1197. adopted once it is found.
  1198. --*/
  1199. {
  1200. NTSTATUS Status = (STATUS_SUCCESS);
  1201. PAGED_CODE();
  1202. if (pSrvCall->pDomainName != NULL) {
  1203. RxFreePool(pSrvCall->pDomainName);
  1204. }
  1205. if (pDomainName != NULL && pDomainName->Length > 0) {
  1206. pSrvCall->pDomainName = (PUNICODE_STRING)
  1207. RxAllocatePoolWithTag(
  1208. NonPagedPool,
  1209. sizeof(UNICODE_STRING) + pDomainName->Length + sizeof(WCHAR),
  1210. RX_SRVCALL_PARAMS_POOLTAG);
  1211. if (pSrvCall->pDomainName != NULL) {
  1212. pSrvCall->pDomainName->Buffer = (PWCHAR)((PCHAR)pSrvCall->pDomainName + sizeof(UNICODE_STRING));
  1213. pSrvCall->pDomainName->Length = pDomainName->Length;
  1214. pSrvCall->pDomainName->MaximumLength = pDomainName->Length;
  1215. *pSrvCall->pDomainName->Buffer = 0;
  1216. if (pSrvCall->pDomainName->Length > 0) {
  1217. RtlCopyMemory(
  1218. pSrvCall->pDomainName->Buffer,
  1219. pDomainName->Buffer,
  1220. pDomainName->Length);
  1221. }
  1222. } else {
  1223. Status = (STATUS_INSUFFICIENT_RESOURCES);
  1224. }
  1225. } else {
  1226. pSrvCall->pDomainName = NULL;
  1227. }
  1228. return Status;
  1229. }
  1230. VOID
  1231. RxpDestroySrvCall(
  1232. PSRV_CALL ThisSrvCall)
  1233. /*++
  1234. Routine Description:
  1235. This routine is used to tear down a SRV_CALL entry. This code is offloaded
  1236. from the RxFinalizeCall routine to avoid having to hold the Name Table Lock
  1237. for extended periods of time while the mini redirector is finalizing its
  1238. data structures.
  1239. Arguments:
  1240. ThisSrvCall - the SrvCall being finalized
  1241. Notes:
  1242. there is no recursive part because i don't have a list of srvcalls and a list
  1243. of netroots i only have a combined list. thus, recursive finalization of
  1244. netroots is directly from the top level. however, all netroots should already
  1245. have been done when i get here..
  1246. --*/
  1247. {
  1248. NTSTATUS Status;
  1249. BOOLEAN ForceFinalize;
  1250. PRDBSS_DEVICE_OBJECT RxDeviceObject = ThisSrvCall->RxDeviceObject;
  1251. PRX_PREFIX_TABLE pRxNetNameTable = RxDeviceObject->pRxNetNameTable;
  1252. ASSERT(ThisSrvCall->UpperFinalizationDone);
  1253. ForceFinalize = BooleanFlagOn(
  1254. ThisSrvCall->Flags,
  1255. SRVCALL_FLAG_FORCE_FINALIZED);
  1256. //we have to protect this call since the srvcall may never have been claimed
  1257. MINIRDR_CALL_THROUGH(
  1258. Status,
  1259. RxDeviceObject->Dispatch,
  1260. MRxFinalizeSrvCall,((PMRX_SRV_CALL)ThisSrvCall,ForceFinalize)
  1261. );
  1262. RxAcquirePrefixTableLockExclusive( pRxNetNameTable, TRUE);
  1263. InterlockedDecrement(&ThisSrvCall->NodeReferenceCount);
  1264. RxFinalizeSrvCall(
  1265. ThisSrvCall,
  1266. FALSE,
  1267. ForceFinalize);
  1268. RxReleasePrefixTableLock(pRxNetNameTable);
  1269. }
  1270. BOOLEAN
  1271. RxFinalizeSrvCall (
  1272. OUT PSRV_CALL ThisSrvCall,
  1273. IN BOOLEAN RecursiveFinalize,
  1274. IN BOOLEAN ForceFinalize
  1275. )
  1276. /*++
  1277. Routine Description:
  1278. The routine finalizes the given netroot. You should have exclusive on
  1279. the netname tablelock.
  1280. Arguments:
  1281. ThisSrvCall - the SrvCall being finalized
  1282. Return Value:
  1283. BOOLEAN - tells whether finalization actually occured
  1284. Notes:
  1285. there is no recursive part because i don't have a list of srvcalls and a list
  1286. of netroots i only have a combined list. thus, recursive finalization of
  1287. netroots is directly from the top level. however, all netroots should already
  1288. have been done when i get here..
  1289. --*/
  1290. {
  1291. BOOLEAN NodeActuallyFinalized = FALSE;
  1292. PRX_PREFIX_TABLE pRxNetNameTable;
  1293. PAGED_CODE();
  1294. ASSERT( NodeType(ThisSrvCall) == RDBSS_NTC_SRVCALL );
  1295. pRxNetNameTable = ThisSrvCall->RxDeviceObject->pRxNetNameTable;
  1296. ASSERT( RxIsPrefixTableLockExclusive( pRxNetNameTable ));
  1297. RxDbgTrace(+1, Dbg, ("RxFinalizeSrvCall<+> %08lx %wZ RefC=%ld\n",
  1298. ThisSrvCall,&ThisSrvCall->PrefixEntry.Prefix,
  1299. ThisSrvCall->NodeReferenceCount));
  1300. if( ThisSrvCall->NodeReferenceCount == 1 || ForceFinalize ) {
  1301. BOOLEAN DeferFinalizationToWorkerThread = FALSE;
  1302. RxLog(("FINALSRVC: %lx %wZ\n",ThisSrvCall,&ThisSrvCall->PrefixEntry.Prefix));
  1303. RxWmiLog(LOG,
  1304. RxFinalizeSrvCall,
  1305. LOGPTR(ThisSrvCall)
  1306. LOGUSTR(ThisSrvCall->PrefixEntry.Prefix));
  1307. if (!ThisSrvCall->UpperFinalizationDone) {
  1308. NTSTATUS Status;
  1309. RxRemovePrefixTableEntry ( pRxNetNameTable, &ThisSrvCall->PrefixEntry);
  1310. if (ForceFinalize) {
  1311. ThisSrvCall->Flags |= SRVCALL_FLAG_FORCE_FINALIZED;
  1312. }
  1313. ThisSrvCall->UpperFinalizationDone = TRUE;
  1314. if (ThisSrvCall->NodeReferenceCount == 1) {
  1315. NodeActuallyFinalized = TRUE;
  1316. }
  1317. if (ThisSrvCall->RxDeviceObject != NULL) {
  1318. if (IoGetCurrentProcess() != RxGetRDBSSProcess()) {
  1319. InterlockedIncrement(&ThisSrvCall->NodeReferenceCount);
  1320. RxDispatchToWorkerThread(
  1321. ThisSrvCall->RxDeviceObject,
  1322. DelayedWorkQueue,
  1323. RxpDestroySrvCall,
  1324. ThisSrvCall);
  1325. DeferFinalizationToWorkerThread = TRUE;
  1326. } else {
  1327. MINIRDR_CALL_THROUGH(
  1328. Status,
  1329. ThisSrvCall->RxDeviceObject->Dispatch,
  1330. MRxFinalizeSrvCall,((PMRX_SRV_CALL)ThisSrvCall,ForceFinalize)
  1331. );
  1332. }
  1333. }
  1334. }
  1335. if (!DeferFinalizationToWorkerThread) {
  1336. if( ThisSrvCall->NodeReferenceCount == 1 ) {
  1337. if (ThisSrvCall->pDomainName != NULL) {
  1338. RxFreePool(ThisSrvCall->pDomainName);
  1339. }
  1340. RxTearDownBufferingManager(ThisSrvCall);
  1341. RxFreeObject(ThisSrvCall);
  1342. NodeActuallyFinalized = TRUE;
  1343. }
  1344. }
  1345. } else {
  1346. RxDbgTrace(0, Dbg, (" NODE NOT ACTUALLY FINALIZED!!!%C\n", '!'));
  1347. }
  1348. RxDbgTrace(-1, Dbg, ("RxFinalizeSrvCall<-> %08lx\n", ThisSrvCall, NodeActuallyFinalized));
  1349. return NodeActuallyFinalized;
  1350. }
  1351. PNET_ROOT
  1352. RxCreateNetRoot (
  1353. IN PSRV_CALL SrvCall,
  1354. IN PUNICODE_STRING Name,
  1355. IN ULONG NetRootFlags,
  1356. IN PRX_CONNECTION_ID RxConnectionId
  1357. )
  1358. /*++
  1359. Routine Description:
  1360. The routine builds a node representing a netroot and inserts the name into the net
  1361. name table. The name is allocated at the end of the block. The reference count on the block
  1362. is set to 1 on this create....
  1363. Arguments:
  1364. SrvCall - the associated server call context; may be NULL!! (but not right now.........)
  1365. Dispatch - the minirdr dispatch table
  1366. Name - the name to be inserted
  1367. Return Value:
  1368. Ptr to the created net root.
  1369. --*/
  1370. {
  1371. PNET_ROOT ThisNetRoot;
  1372. PRX_PREFIX_TABLE pRxNetNameTable;
  1373. ULONG NameSize,SrvCallNameSize;
  1374. PAGED_CODE();
  1375. RxDbgTrace(+1, Dbg, ("RxNetRootCreate--> Name = %wZ\n", Name));
  1376. ASSERT (SrvCall != NULL);
  1377. pRxNetNameTable = SrvCall->RxDeviceObject->pRxNetNameTable;
  1378. ASSERT ( RxIsPrefixTableLockExclusive ( pRxNetNameTable ) );
  1379. SrvCallNameSize = SrvCall->PrefixEntry.Prefix.Length;
  1380. NameSize = Name->Length + SrvCallNameSize;
  1381. ThisNetRoot = RxAllocateObject(
  1382. RDBSS_NTC_NETROOT,
  1383. SrvCall->RxDeviceObject->Dispatch,
  1384. NameSize);
  1385. if (ThisNetRoot != NULL) {
  1386. USHORT CaseInsensitiveLength;
  1387. RtlMoveMemory(
  1388. (PCHAR)(ThisNetRoot->PrefixEntry.Prefix.Buffer) + SrvCallNameSize,
  1389. Name->Buffer,
  1390. Name->Length);
  1391. if (SrvCallNameSize) {
  1392. RtlMoveMemory(
  1393. ThisNetRoot->PrefixEntry.Prefix.Buffer,
  1394. SrvCall->PrefixEntry.Prefix.Buffer,
  1395. SrvCallNameSize);
  1396. }
  1397. if (FlagOn(SrvCall->Flags,SRVCALL_FLAG_CASE_INSENSITIVE_NETROOTS)) {
  1398. CaseInsensitiveLength = (USHORT)NameSize;
  1399. } else {
  1400. CaseInsensitiveLength = SrvCall->PrefixEntry.CaseInsensitiveLength;
  1401. }
  1402. RxPrefixTableInsertName (
  1403. pRxNetNameTable,
  1404. &ThisNetRoot->PrefixEntry,
  1405. (PVOID)ThisNetRoot,
  1406. &ThisNetRoot->NodeReferenceCount,
  1407. CaseInsensitiveLength,
  1408. RxConnectionId);
  1409. RxInitializeFcbTable(&ThisNetRoot->FcbTable, TRUE);
  1410. InitializeListHead(&ThisNetRoot->VirtualNetRoots);
  1411. InitializeListHead(&ThisNetRoot->TransitionWaitList);
  1412. InitializeListHead(&ThisNetRoot->ScavengerFinalizationList);
  1413. RxInitializePurgeSyncronizationContext(
  1414. &ThisNetRoot->PurgeSyncronizationContext);
  1415. ThisNetRoot->SerialNumberForEnum = SerialNumber++;
  1416. ThisNetRoot->Flags |= NetRootFlags;
  1417. ThisNetRoot->DiskParameters.ClusterSize = 1;
  1418. ThisNetRoot->DiskParameters.ReadAheadGranularity = DEFAULT_READ_AHEAD_GRANULARITY;
  1419. ThisNetRoot->SrvCall = SrvCall;
  1420. //already have the lock
  1421. RxReferenceSrvCall((PSRV_CALL)ThisNetRoot->SrvCall);
  1422. }
  1423. return ThisNetRoot;
  1424. }
  1425. BOOLEAN
  1426. RxFinalizeNetRoot (
  1427. OUT PNET_ROOT ThisNetRoot,
  1428. IN BOOLEAN RecursiveFinalize,
  1429. IN BOOLEAN ForceFinalize
  1430. )
  1431. /*++
  1432. Routine Description:
  1433. The routine finalizes the given netroot. You must be exclusive on
  1434. the NetName tablelock.
  1435. Arguments:
  1436. ThisNetRoot - the NetRoot being dereferenced
  1437. Return Value:
  1438. BOOLEAN - tells whether finalization actually occured
  1439. --*/
  1440. {
  1441. NTSTATUS Status;
  1442. BOOLEAN NodeActuallyFinalized = FALSE;
  1443. PRX_PREFIX_TABLE pRxNetNameTable;
  1444. PAGED_CODE();
  1445. ASSERT( NodeType(ThisNetRoot) == RDBSS_NTC_NETROOT );
  1446. pRxNetNameTable = ThisNetRoot->SrvCall->RxDeviceObject->pRxNetNameTable;
  1447. ASSERT ( RxIsPrefixTableLockExclusive ( pRxNetNameTable ) );
  1448. if (ThisNetRoot->Flags & NETROOT_FLAG_FINALIZATION_IN_PROGRESS) {
  1449. return FALSE;
  1450. }
  1451. // Since the table lock has been acquired exclusive the flags can be modified
  1452. // without any further synchronization since the protection is against recursive
  1453. // invocations.
  1454. ThisNetRoot->Flags |= NETROOT_FLAG_FINALIZATION_IN_PROGRESS;
  1455. RxDbgTrace(+1, Dbg, ("RxFinalizeNetRoot<+> %08lx %wZ RefC=%ld\n",
  1456. ThisNetRoot,&ThisNetRoot->PrefixEntry.Prefix,
  1457. ThisNetRoot->NodeReferenceCount));
  1458. if (RecursiveFinalize) {
  1459. PLIST_ENTRY ListEntry;
  1460. USHORT BucketNumber;
  1461. RxAcquireFcbTableLockExclusive(&ThisNetRoot->FcbTable,TRUE);
  1462. IF_DEBUG{
  1463. if ( FALSE && ThisNetRoot->NodeReferenceCount){
  1464. RxDbgTrace(0, Dbg, (" BAD!!!!!ReferenceCount = %08lx\n", ThisNetRoot->NodeReferenceCount));
  1465. }
  1466. }
  1467. for (BucketNumber = 0;
  1468. (BucketNumber < ThisNetRoot->FcbTable.NumberOfBuckets);
  1469. BucketNumber++) {
  1470. PLIST_ENTRY ListHeader;
  1471. ListHeader = &ThisNetRoot->FcbTable.HashBuckets[BucketNumber];
  1472. for (ListEntry = ListHeader->Flink;
  1473. ListEntry != ListHeader;
  1474. ) {
  1475. PFCB Fcb;
  1476. PRX_FCB_TABLE_ENTRY pFcbTableEntry;
  1477. pFcbTableEntry = CONTAINING_RECORD(
  1478. ListEntry,
  1479. RX_FCB_TABLE_ENTRY,
  1480. HashLinks);
  1481. Fcb = CONTAINING_RECORD(
  1482. pFcbTableEntry,
  1483. FCB,
  1484. FcbTableEntry);
  1485. ListEntry = ListEntry->Flink;
  1486. ASSERT( NodeTypeIsFcb(Fcb));
  1487. if (!FlagOn(Fcb->FcbState,FCB_STATE_ORPHANED)) {
  1488. Status = RxAcquireExclusiveFcb(NULL,Fcb);
  1489. ASSERT(Status == (STATUS_SUCCESS));
  1490. // a small complication here is that this fcb MAY have an open section against it caused
  1491. // by our cacheing the file. if so, we need to purge to get to the close
  1492. // wrong//if so, we have to get rid of it and then standoff to let
  1493. // the close go thru. sigh.............
  1494. RxPurgeFcb(Fcb);
  1495. }
  1496. }
  1497. }
  1498. RxReleaseFcbTableLock( &ThisNetRoot->FcbTable );
  1499. }
  1500. if ( ThisNetRoot->NodeReferenceCount == 1 || ForceFinalize ){
  1501. RxLog(("FINALNETROOT: %lx %wZ\n",ThisNetRoot,&ThisNetRoot->PrefixEntry.Prefix));
  1502. RxWmiLog(LOG,
  1503. RxFinalizeNetRoot,
  1504. LOGPTR(ThisNetRoot)
  1505. LOGUSTR(ThisNetRoot->PrefixEntry.Prefix));
  1506. //if (!ThisNetRoot->UpperFinalizationDone) {
  1507. // NOTHING;
  1508. // ThisNetRoot->UpperFinalizationDone = TRUE;
  1509. //}
  1510. if ( ThisNetRoot->NodeReferenceCount == 1 ){
  1511. PSRV_CALL SrvCall = (PSRV_CALL)ThisNetRoot->SrvCall;
  1512. RxFinalizeFcbTable(&ThisNetRoot->FcbTable);
  1513. if (!FlagOn(ThisNetRoot->Flags,NETROOT_FLAG_NAME_ALREADY_REMOVED)) {
  1514. RxRemovePrefixTableEntry ( pRxNetNameTable, &ThisNetRoot->PrefixEntry);
  1515. }
  1516. RxFreeObject(ThisNetRoot);
  1517. if (SrvCall != NULL) {
  1518. RxDereferenceSrvCall(SrvCall,LHS_ExclusiveLockHeld); //already have the lock
  1519. }
  1520. NodeActuallyFinalized = TRUE;
  1521. }
  1522. } else {
  1523. RxDbgTrace(0, Dbg, (" NODE NOT ACTUALLY FINALIZED!!!%C\n", '!'));
  1524. }
  1525. RxDbgTrace(-1, Dbg, ("RxFinalizeNetRoot<-> %08lx\n", ThisNetRoot, NodeActuallyFinalized));
  1526. return NodeActuallyFinalized;
  1527. }
  1528. VOID
  1529. RxAddVirtualNetRootToNetRoot(
  1530. PNET_ROOT pNetRoot,
  1531. PV_NET_ROOT pVNetRoot)
  1532. /*++
  1533. Routine Description:
  1534. The routine adds a VNetRoot to the list of VNetRoot's associated with a NetRoot
  1535. Arguments:
  1536. pNetRoot - the NetRoot
  1537. pVNetRoot - the new VNetRoot to be added to the list.
  1538. Notes:
  1539. The reference count associated with a NetRoot will be equal to the number of VNetRoot's
  1540. associated with it plus 1. the last one being for the prefix name table. This ensures
  1541. that a NetRoot cannot be finalized till all the VNetRoots associated with it have been
  1542. finalized.
  1543. --*/
  1544. {
  1545. PAGED_CODE();
  1546. ASSERT(RxIsPrefixTableLockExclusive( pNetRoot->SrvCall->RxDeviceObject->pRxNetNameTable ));
  1547. pVNetRoot->NetRoot = pNetRoot;
  1548. pNetRoot->NumberOfVirtualNetRoots++;
  1549. if (pNetRoot->DefaultVNetRoot == NULL) {
  1550. //pNetRoot->DefaultVNetRoot = pVNetRoot;
  1551. }
  1552. InsertTailList(&pNetRoot->VirtualNetRoots,&pVNetRoot->NetRootListEntry);
  1553. }
  1554. VOID
  1555. RxRemoveVirtualNetRootFromNetRoot(
  1556. PNET_ROOT pNetRoot,
  1557. PV_NET_ROOT pVNetRoot)
  1558. /*++
  1559. Routine Description:
  1560. The routine removes a VNetRoot to the list of VNetRoot's associated with a NetRoot
  1561. Arguments:
  1562. pNetRoot - the NetRoot
  1563. pVNetRoot - the VNetRoot to be removed from the list.
  1564. Notes:
  1565. The reference count associated with a NetRoot will be equal to the number of VNetRoot's
  1566. associated with it plus 1. the last one being for the prefix name table. This ensures
  1567. that a NetRoot cannot be finalized till all the VNetRoots associated with it have been
  1568. finalized.
  1569. --*/
  1570. {
  1571. PRX_PREFIX_TABLE pRxNetNameTable = pNetRoot->SrvCall->RxDeviceObject->pRxNetNameTable;
  1572. PAGED_CODE();
  1573. ASSERT(RxIsPrefixTableLockExclusive( pRxNetNameTable ));
  1574. pNetRoot->NumberOfVirtualNetRoots--;
  1575. RemoveEntryList(&pVNetRoot->NetRootListEntry);
  1576. if (pNetRoot->DefaultVNetRoot == pVNetRoot) {
  1577. if (!IsListEmpty(&pNetRoot->VirtualNetRoots)) {
  1578. // Traverse the list and pick another default net root.
  1579. PV_NET_ROOT pTempVNetRoot;
  1580. pTempVNetRoot = (PV_NET_ROOT)
  1581. CONTAINING_RECORD(
  1582. pNetRoot->VirtualNetRoots.Flink,
  1583. V_NET_ROOT,
  1584. NetRootListEntry);
  1585. pNetRoot->DefaultVNetRoot = pTempVNetRoot;
  1586. } else {
  1587. pNetRoot->DefaultVNetRoot = NULL;
  1588. }
  1589. }
  1590. if (IsListEmpty(&pNetRoot->VirtualNetRoots)) {
  1591. NTSTATUS Status;
  1592. if (!FlagOn(pNetRoot->Flags,NETROOT_FLAG_NAME_ALREADY_REMOVED)) {
  1593. RxRemovePrefixTableEntry(pRxNetNameTable, &pNetRoot->PrefixEntry);
  1594. SetFlag(pNetRoot->Flags,NETROOT_FLAG_NAME_ALREADY_REMOVED);
  1595. }
  1596. //ASSERT(pNetRoot->Dispatch != NULL);
  1597. if ((pNetRoot->SrvCall != NULL)
  1598. && (pNetRoot->SrvCall->RxDeviceObject!=NULL)) {
  1599. MINIRDR_CALL_THROUGH(
  1600. Status,
  1601. pNetRoot->SrvCall->RxDeviceObject->Dispatch,
  1602. MRxFinalizeNetRoot,((PMRX_NET_ROOT)pNetRoot,NULL)
  1603. );
  1604. }
  1605. }
  1606. }
  1607. NTSTATUS
  1608. RxInitializeVNetRootParameters(
  1609. PRX_CONTEXT RxContext,
  1610. LUID *pLogonId,
  1611. ULONG *pSessionId,
  1612. PUNICODE_STRING *pUserNamePtr,
  1613. PUNICODE_STRING *pUserDomainNamePtr,
  1614. PUNICODE_STRING *pPasswordPtr,
  1615. ULONG *pFlags
  1616. )
  1617. /*++
  1618. Routine Description:
  1619. This routine extracts the ea parameters specified
  1620. Arguments:
  1621. RxContext -- the RxContext
  1622. pLogonId -- the logon Id.
  1623. pUserNamePtr -- pointer to the User Name
  1624. pUserDomainNamePtr -- pointer to the user domain name
  1625. pPasswordPtr -- the password.
  1626. Return Value:
  1627. STATUS_SUCCESS -- successful,
  1628. appropriate NTSTATUS code otherwise
  1629. Notes:
  1630. --*/
  1631. {
  1632. NTSTATUS Status = STATUS_SUCCESS;
  1633. RxCaptureRequestPacket;
  1634. RxCaptureParamBlock;
  1635. PIO_SECURITY_CONTEXT pSecurityContext;
  1636. PACCESS_TOKEN pAccessToken;
  1637. PAGED_CODE();
  1638. pSecurityContext = RxContext->Create.NtCreateParameters.SecurityContext;
  1639. pAccessToken = SeQuerySubjectContextToken(
  1640. &pSecurityContext->AccessState->SubjectSecurityContext);
  1641. *pPasswordPtr = NULL;
  1642. *pUserDomainNamePtr = NULL;
  1643. *pUserNamePtr = NULL;
  1644. *pFlags &= ~VNETROOT_FLAG_CSCAGENT_INSTANCE;
  1645. if (!SeTokenIsRestricted(pAccessToken)) {
  1646. Status = SeQueryAuthenticationIdToken(
  1647. pAccessToken,
  1648. pLogonId);
  1649. if (Status == STATUS_SUCCESS) {
  1650. Status = SeQuerySessionIdToken(
  1651. pAccessToken,
  1652. pSessionId);
  1653. }
  1654. if ((Status == STATUS_SUCCESS) &&
  1655. (RxContext->Create.UserName.Buffer != NULL)) {
  1656. PUNICODE_STRING pTargetString;
  1657. pTargetString = RxAllocatePoolWithTag(
  1658. NonPagedPool,
  1659. (sizeof(UNICODE_STRING) + RxContext->Create.UserName.Length),
  1660. RX_SRVCALL_PARAMS_POOLTAG);
  1661. if (pTargetString != NULL) {
  1662. pTargetString->Length = RxContext->Create.UserName.Length;
  1663. pTargetString->MaximumLength = RxContext->Create.UserName.MaximumLength;
  1664. if (pTargetString->Length > 0) {
  1665. pTargetString->Buffer = (PWCHAR)((PCHAR)pTargetString + sizeof(UNICODE_STRING));
  1666. RtlCopyMemory(
  1667. pTargetString->Buffer,
  1668. RxContext->Create.UserName.Buffer,
  1669. pTargetString->Length);
  1670. } else {
  1671. pTargetString->Buffer = NULL;
  1672. }
  1673. *pUserNamePtr = pTargetString;
  1674. } else {
  1675. Status = STATUS_INSUFFICIENT_RESOURCES;
  1676. }
  1677. }
  1678. if ((RxContext->Create.UserDomainName.Buffer != NULL) && (Status == STATUS_SUCCESS)) {
  1679. PUNICODE_STRING pTargetString;
  1680. pTargetString = RxAllocatePoolWithTag(
  1681. NonPagedPool,
  1682. (sizeof(UNICODE_STRING) + RxContext->Create.UserDomainName.Length + sizeof(WCHAR)),
  1683. RX_SRVCALL_PARAMS_POOLTAG);
  1684. if (pTargetString != NULL) {
  1685. pTargetString->Length = RxContext->Create.UserDomainName.Length;
  1686. pTargetString->MaximumLength = RxContext->Create.UserDomainName.MaximumLength;
  1687. pTargetString->Buffer = (PWCHAR)((PCHAR)pTargetString + sizeof(UNICODE_STRING));
  1688. // in case of UPN name, domain name will be a NULL string
  1689. *pTargetString->Buffer = 0;
  1690. if (pTargetString->Length > 0) {
  1691. RtlCopyMemory(
  1692. pTargetString->Buffer,
  1693. RxContext->Create.UserDomainName.Buffer,
  1694. pTargetString->Length);
  1695. }
  1696. *pUserDomainNamePtr = pTargetString;
  1697. } else {
  1698. Status = STATUS_INSUFFICIENT_RESOURCES;
  1699. }
  1700. }
  1701. if ((RxContext->Create.Password.Buffer != NULL) && (Status == STATUS_SUCCESS)) {
  1702. PUNICODE_STRING pTargetString;
  1703. pTargetString = RxAllocatePoolWithTag(
  1704. NonPagedPool,
  1705. (sizeof(UNICODE_STRING) + RxContext->Create.Password.Length),
  1706. RX_SRVCALL_PARAMS_POOLTAG);
  1707. if (pTargetString != NULL) {
  1708. pTargetString->Length = RxContext->Create.Password.Length;
  1709. pTargetString->MaximumLength = RxContext->Create.Password.MaximumLength;
  1710. if (pTargetString->Length > 0) {
  1711. pTargetString->Buffer = (PWCHAR)((PCHAR)pTargetString + sizeof(UNICODE_STRING));
  1712. RtlCopyMemory(
  1713. pTargetString->Buffer,
  1714. RxContext->Create.Password.Buffer,
  1715. pTargetString->Length);
  1716. } else {
  1717. pTargetString->Buffer = NULL;
  1718. }
  1719. *pPasswordPtr = pTargetString;
  1720. } else {
  1721. Status = STATUS_INSUFFICIENT_RESOURCES;
  1722. }
  1723. }
  1724. if (Status == STATUS_SUCCESS)
  1725. {
  1726. if(RxIsThisACscAgentOpen(RxContext))
  1727. {
  1728. *pFlags |= VNETROOT_FLAG_CSCAGENT_INSTANCE;
  1729. }
  1730. }
  1731. if (Status != STATUS_SUCCESS) {
  1732. if (*pUserNamePtr != NULL) {
  1733. RxFreePool(*pUserNamePtr);
  1734. *pUserNamePtr = NULL;
  1735. }
  1736. if (*pUserDomainNamePtr != NULL) {
  1737. RxFreePool(*pUserDomainNamePtr);
  1738. *pUserDomainNamePtr = NULL;
  1739. }
  1740. if (*pPasswordPtr != NULL) {
  1741. RxFreePool(*pPasswordPtr);
  1742. *pPasswordPtr = NULL;
  1743. }
  1744. }
  1745. } else {
  1746. Status = STATUS_ACCESS_DENIED;
  1747. }
  1748. return Status;
  1749. }
  1750. VOID
  1751. RxUninitializeVNetRootParameters(
  1752. PUNICODE_STRING pUserName,
  1753. PUNICODE_STRING pUserDomainName,
  1754. PUNICODE_STRING pPassword,
  1755. ULONG *lpFlags
  1756. )
  1757. /*++
  1758. Routine Description:
  1759. This routine unintializes the parameters ( logon ) associated with a VNetRoot
  1760. Arguments:
  1761. pVNetRoot -- the VNetRoot
  1762. --*/
  1763. {
  1764. PAGED_CODE();
  1765. if (pUserName != NULL) {
  1766. RxFreePool(pUserName);
  1767. }
  1768. if (pUserDomainName != NULL) {
  1769. RxFreePool(pUserDomainName);
  1770. }
  1771. if (pPassword != NULL) {
  1772. RxFreePool(pPassword);
  1773. }
  1774. if (lpFlags)
  1775. {
  1776. *lpFlags &= ~VNETROOT_FLAG_CSCAGENT_INSTANCE;
  1777. }
  1778. }
  1779. PV_NET_ROOT
  1780. RxCreateVNetRoot (
  1781. IN PRX_CONTEXT RxContext,
  1782. IN PNET_ROOT NetRoot,
  1783. IN PUNICODE_STRING CanonicalName,
  1784. IN PUNICODE_STRING LocalNetRootName,
  1785. IN PUNICODE_STRING FilePath,
  1786. IN PRX_CONNECTION_ID RxConnectionId
  1787. )
  1788. /*++
  1789. Routine Description:
  1790. The routine builds a node representing a virtual netroot and inserts the name into
  1791. the net name table. The name is allocated at the end of the block. The reference
  1792. count on the block is set to 1 on this create....
  1793. Virtual netroots provide a mechanism for mapping "into" a share....i.e. having a
  1794. user drive that points not at the root of the associated share point. The format
  1795. of a name is either
  1796. \server\share\d1\d2.....
  1797. or
  1798. \;m:\server\share\d1\d2.....
  1799. depending on whether there is a local device ("m:") associated with this vnetroot.
  1800. In the latter case is that \d1\d2.. gets prefixed onto each createfile that is
  1801. opened on this vnetroot.
  1802. vnetroot's are also used to supply alternate credentials. the point of the former
  1803. kind of vnetroot is to propagate the credentials into the netroot as the default.
  1804. for this to work, there must be no other references.
  1805. You need to have the lock exclusive to call....see RxCreateSrvCall.......
  1806. Arguments:
  1807. RxContext - the RDBSS context
  1808. NetRoot - the associated net root context
  1809. Name - the name to be inserted
  1810. NamePrefixOffsetInBytes - offset into the name where the prefix starts
  1811. Return Value:
  1812. Ptr to the created v net root.
  1813. --*/
  1814. {
  1815. NTSTATUS Status = STATUS_SUCCESS;
  1816. PV_NET_ROOT ThisVNetRoot;
  1817. UNICODE_STRING VNetRootName;
  1818. PUNICODE_STRING ThisNamePrefix;
  1819. ULONG NameSize;
  1820. BOOLEAN fCscAgent = FALSE;
  1821. PRX_PREFIX_ENTRY ThisEntry;
  1822. PAGED_CODE();
  1823. ASSERT (RxIsPrefixTableLockExclusive( RxContext->RxDeviceObject->pRxNetNameTable ));
  1824. NameSize = NetRoot->PrefixEntry.Prefix.Length + LocalNetRootName->Length;
  1825. ThisVNetRoot = RxAllocateObject(RDBSS_NTC_V_NETROOT,NetRoot->SrvCall->RxDeviceObject->Dispatch,NameSize);
  1826. if (ThisVNetRoot != NULL) {
  1827. USHORT CaseInsensitiveLength;
  1828. PMRX_SRV_CALL SrvCall;
  1829. if (Status == STATUS_SUCCESS) {
  1830. // Initialize the Create Parameters
  1831. Status = RxInitializeVNetRootParameters(
  1832. RxContext,
  1833. &ThisVNetRoot->LogonId,
  1834. &ThisVNetRoot->SessionId,
  1835. &ThisVNetRoot->pUserName,
  1836. &ThisVNetRoot->pUserDomainName,
  1837. &ThisVNetRoot->pPassword,
  1838. &ThisVNetRoot->Flags
  1839. );
  1840. }
  1841. if (Status == STATUS_SUCCESS) {
  1842. VNetRootName = ThisVNetRoot->PrefixEntry.Prefix;
  1843. RtlMoveMemory(
  1844. VNetRootName.Buffer,
  1845. CanonicalName->Buffer,
  1846. VNetRootName.Length);
  1847. ThisVNetRoot->PrefixOffsetInBytes = LocalNetRootName->Length +
  1848. NetRoot->PrefixEntry.Prefix.Length;
  1849. RxDbgTrace(+1, Dbg, ("RxVNetRootCreate--> Name = <%wZ>, offs=%08lx\n",
  1850. CanonicalName, ThisVNetRoot->PrefixOffsetInBytes));
  1851. ThisNamePrefix = &ThisVNetRoot->NamePrefix;
  1852. ThisNamePrefix->Buffer = (PWCH)((PCHAR)VNetRootName.Buffer + ThisVNetRoot->PrefixOffsetInBytes);
  1853. ThisNamePrefix->Length =
  1854. ThisNamePrefix->MaximumLength =
  1855. VNetRootName.Length - (USHORT)ThisVNetRoot->PrefixOffsetInBytes;
  1856. InitializeListHead(&ThisVNetRoot->TransitionWaitList);
  1857. InitializeListHead(&ThisVNetRoot->ScavengerFinalizationList);
  1858. // Now, insert into the netrootQ and the net name table
  1859. ThisEntry = &ThisVNetRoot->PrefixEntry;
  1860. SrvCall = NetRoot->pSrvCall;
  1861. if (FlagOn(SrvCall->Flags,SRVCALL_FLAG_CASE_INSENSITIVE_FILENAMES)) {
  1862. //here is insensitive length is the whole thing
  1863. CaseInsensitiveLength = (USHORT)NameSize;
  1864. } else {
  1865. //here is insensitive length is determined by the netroot or srvcall
  1866. //plus we have to account for the device, if present
  1867. ULONG ComponentsToUpcase,wcLength,i;
  1868. if (FlagOn(SrvCall->Flags,SRVCALL_FLAG_CASE_INSENSITIVE_NETROOTS)) {
  1869. CaseInsensitiveLength = NetRoot->PrefixEntry.CaseInsensitiveLength;
  1870. } else {
  1871. CaseInsensitiveLength = ((PSRV_CALL)SrvCall)->PrefixEntry.CaseInsensitiveLength;
  1872. }
  1873. wcLength = CanonicalName->Length/sizeof(WCHAR);
  1874. for (i=1;;i++) { //note: don't start at zero
  1875. if (i>=wcLength)
  1876. break;
  1877. if (CanonicalName->Buffer[i]!=OBJ_NAME_PATH_SEPARATOR)
  1878. break;
  1879. }
  1880. CaseInsensitiveLength += (USHORT)(i*sizeof(WCHAR));
  1881. }
  1882. RxPrefixTableInsertName(
  1883. RxContext->RxDeviceObject->pRxNetNameTable,
  1884. ThisEntry,
  1885. (PVOID)ThisVNetRoot,
  1886. &ThisVNetRoot->NodeReferenceCount,
  1887. CaseInsensitiveLength,
  1888. RxConnectionId);
  1889. RxReferenceNetRoot(NetRoot);
  1890. RxAddVirtualNetRootToNetRoot(NetRoot,ThisVNetRoot);
  1891. ThisVNetRoot->SerialNumberForEnum = SerialNumber++;
  1892. ThisVNetRoot->UpperFinalizationDone = FALSE;
  1893. ThisVNetRoot->ConnectionFinalizationDone = FALSE;
  1894. ThisVNetRoot->AdditionalReferenceForDeleteFsctlTaken = 0;
  1895. RxDbgTrace(-1, Dbg, ("RxVNetRootCreate -> RefCount = %08lx\n", ThisVNetRoot->NodeReferenceCount));
  1896. }
  1897. if (Status != STATUS_SUCCESS) {
  1898. RxUninitializeVNetRootParameters(
  1899. ThisVNetRoot->pUserName,
  1900. ThisVNetRoot->pUserDomainName,
  1901. ThisVNetRoot->pPassword,
  1902. &ThisVNetRoot->Flags
  1903. );
  1904. RxFreeObject(ThisVNetRoot);
  1905. ThisVNetRoot = NULL;
  1906. }
  1907. }
  1908. return ThisVNetRoot;
  1909. }
  1910. VOID
  1911. RxOrphanSrvOpens(
  1912. IN PV_NET_ROOT ThisVNetRoot
  1913. )
  1914. /*++
  1915. Routine Description:
  1916. The routine iterates through all the FCBs that belong to the netroot to which this VNetRoot
  1917. belongs and orphans all SrvOpens that belong to the VNetRoot. The caller must have acquired
  1918. the NetName tablelock.
  1919. Arguments:
  1920. ThisVNetRoot - the VNetRoot
  1921. Return Value:
  1922. None
  1923. Notes:
  1924. On Entry -- RxNetNameTable lock must be acquired exclusive.
  1925. On Exit -- no change in lock ownership.
  1926. --*/
  1927. {
  1928. PLIST_ENTRY pListEntry;
  1929. USHORT BucketNumber;
  1930. PNET_ROOT NetRoot = (PNET_ROOT)(ThisVNetRoot->NetRoot);
  1931. PRX_PREFIX_TABLE pRxNetNameTable = NetRoot->SrvCall->RxDeviceObject->pRxNetNameTable;
  1932. PAGED_CODE();
  1933. //
  1934. // MAILSLOT FCBs don't have SrvOpens
  1935. //
  1936. if(NetRoot->Type == NET_ROOT_MAILSLOT) return;
  1937. ASSERT(RxIsPrefixTableLockExclusive(pRxNetNameTable));
  1938. RxAcquireFcbTableLockExclusive( &NetRoot->FcbTable, TRUE);
  1939. try {
  1940. for (BucketNumber = 0;
  1941. (BucketNumber < NetRoot->FcbTable.NumberOfBuckets);
  1942. BucketNumber++) {
  1943. PLIST_ENTRY pListHeader;
  1944. pListHeader = &NetRoot->FcbTable.HashBuckets[BucketNumber];
  1945. pListEntry = pListHeader->Flink;
  1946. while (pListEntry != pListHeader) {
  1947. PFCB pFcb;
  1948. PRX_FCB_TABLE_ENTRY pFcbTableEntry;
  1949. pFcbTableEntry = CONTAINING_RECORD(
  1950. pListEntry,
  1951. RX_FCB_TABLE_ENTRY,
  1952. HashLinks );
  1953. pListEntry = pListEntry->Flink;
  1954. pFcb = CONTAINING_RECORD(
  1955. pFcbTableEntry,
  1956. FCB,
  1957. FcbTableEntry);
  1958. ASSERT(NodeTypeIsFcb(pFcb));
  1959. RxOrphanSrvOpensForThisFcb(pFcb, ThisVNetRoot, FALSE); // don't force orphan the FCB
  1960. // orphan only those srvopens
  1961. // that belong to this VNetRoot
  1962. }
  1963. }
  1964. if (NetRoot->FcbTable.pTableEntryForNull)
  1965. {
  1966. PFCB pFcb;
  1967. pFcb = CONTAINING_RECORD(
  1968. NetRoot->FcbTable.pTableEntryForNull,
  1969. FCB,
  1970. FcbTableEntry);
  1971. ASSERT(NodeTypeIsFcb(pFcb));
  1972. RxOrphanSrvOpensForThisFcb(pFcb, ThisVNetRoot, FALSE);
  1973. }
  1974. } finally {
  1975. RxReleaseFcbTableLock( &NetRoot->FcbTable );
  1976. }
  1977. }
  1978. BOOLEAN
  1979. RxFinalizeVNetRoot(
  1980. OUT PV_NET_ROOT ThisVNetRoot,
  1981. IN BOOLEAN RecursiveFinalize,
  1982. IN BOOLEAN ForceFinalize
  1983. )
  1984. /*++
  1985. Routine Description:
  1986. The routine finalizes the given netroot. You must be exclusive on
  1987. the NetName tablelock.
  1988. Arguments:
  1989. ThisVNetRoot - the VNetRoot being dereferenced
  1990. Return Value:
  1991. BOOLEAN - tells whether finalization actually occured
  1992. --*/
  1993. {
  1994. NTSTATUS Status = STATUS_SUCCESS;
  1995. BOOLEAN NodeActuallyFinalized = FALSE;
  1996. PRX_PREFIX_TABLE pRxNetNameTable;
  1997. PAGED_CODE();
  1998. ASSERT( NodeType(ThisVNetRoot) == RDBSS_NTC_V_NETROOT );
  1999. pRxNetNameTable = ThisVNetRoot->NetRoot->SrvCall->RxDeviceObject->pRxNetNameTable;
  2000. ASSERT ( RxIsPrefixTableLockExclusive ( pRxNetNameTable ) );
  2001. RxDbgTrace(+1, Dbg, ("RxFinalizeVNetRoot<+> %08lx %wZ RefC=%ld\n",
  2002. ThisVNetRoot,&ThisVNetRoot->PrefixEntry.Prefix,
  2003. ThisVNetRoot->NodeReferenceCount));
  2004. //The actual finalization is divided into two parts:
  2005. // 1) if we're at the end (refcount==1) or being forced, we do the one-time only stuff
  2006. // 2) if the refcount goes to zero, we actually do the free
  2007. if( ThisVNetRoot->NodeReferenceCount == 1 || ForceFinalize ){
  2008. PNET_ROOT NetRoot = (PNET_ROOT)ThisVNetRoot->NetRoot;
  2009. RxLog(("FINALVNETROOT: %lx %wZ\n",ThisVNetRoot,&ThisVNetRoot->PrefixEntry.Prefix));
  2010. RxWmiLog(LOG,
  2011. RxFinalizeVNetRoot,
  2012. LOGPTR(ThisVNetRoot)
  2013. LOGUSTR(ThisVNetRoot->PrefixEntry.Prefix));
  2014. if (!ThisVNetRoot->UpperFinalizationDone) {
  2015. ASSERT( NodeType(NetRoot) == RDBSS_NTC_NETROOT );
  2016. RxReferenceNetRoot(NetRoot);
  2017. RxOrphanSrvOpens(ThisVNetRoot);
  2018. RxRemoveVirtualNetRootFromNetRoot(NetRoot,ThisVNetRoot);
  2019. RxDereferenceNetRoot(NetRoot,LHS_ExclusiveLockHeld);
  2020. RxDbgTrace(0, Dbg, ("Mini Rdr VNetRoot finalization returned %lx\n", Status));
  2021. RxRemovePrefixTableEntry ( pRxNetNameTable, &ThisVNetRoot->PrefixEntry);
  2022. ThisVNetRoot->UpperFinalizationDone = TRUE;
  2023. }
  2024. if (ThisVNetRoot->NodeReferenceCount == 1) {
  2025. if (NetRoot->SrvCall->RxDeviceObject != NULL) {
  2026. MINIRDR_CALL_THROUGH(
  2027. Status,
  2028. NetRoot->SrvCall->RxDeviceObject->Dispatch,
  2029. MRxFinalizeVNetRoot,((PMRX_V_NET_ROOT)ThisVNetRoot,NULL)
  2030. );
  2031. }
  2032. RxUninitializeVNetRootParameters(
  2033. ThisVNetRoot->pUserName,
  2034. ThisVNetRoot->pUserDomainName,
  2035. ThisVNetRoot->pPassword,
  2036. &ThisVNetRoot->Flags
  2037. );
  2038. RxDereferenceNetRoot(NetRoot,LHS_ExclusiveLockHeld);
  2039. RxFreePool(ThisVNetRoot);
  2040. NodeActuallyFinalized = TRUE;
  2041. }
  2042. } else {
  2043. RxDbgTrace(0, Dbg, (" NODE NOT ACTUALLY FINALIZED!!!%C\n", '!'));
  2044. }
  2045. RxDbgTrace(-1, Dbg, ("RxFinalizeVNetRoot<-> %08lx\n", ThisVNetRoot, NodeActuallyFinalized));
  2046. return NodeActuallyFinalized;
  2047. }
  2048. PVOID
  2049. RxAllocateFcbObject(
  2050. PRDBSS_DEVICE_OBJECT RxDeviceObject,
  2051. NODE_TYPE_CODE NodeType,
  2052. POOL_TYPE PoolType,
  2053. ULONG NameSize,
  2054. PVOID pAlreadyAllocatedObject)
  2055. /*++
  2056. Routine Description:
  2057. The routine allocates and constructs the skeleton of a FCB/SRV_OPEN and FOBX instance
  2058. Arguments:
  2059. pMRxDispatch - the Mini redirector dispatch vector
  2060. NodeType - the node type
  2061. PoolType - the pool type to be used ( for paging file data structures NonPagedPool is
  2062. used.
  2063. NameLength - name size.
  2064. Notes:
  2065. The reasons as to why the allocation/freeing of these data structures have been
  2066. centralized are as follows
  2067. 1) The construction of these three data types have a lot in common with the exception
  2068. of the initial computation of sizes. Therefore centralization minimizes the footprint.
  2069. 2) It allows us to experiment with different clustering/allocation strategies.
  2070. 3) It allows the incorporation of debug support in an easy way.
  2071. --*/
  2072. {
  2073. ULONG FcbSize,NonPagedFcbSize,SrvOpenSize,FobxSize;
  2074. PMINIRDR_DISPATCH pMRxDispatch = RxDeviceObject->Dispatch;
  2075. PVOID pObject;
  2076. PNON_PAGED_FCB pNonPagedFcb = NULL;
  2077. PFCB pFcb = NULL;
  2078. PSRV_OPEN pSrvOpen = NULL;
  2079. PFOBX pFobx = NULL;
  2080. PWCH pName = NULL;
  2081. PAGED_CODE();
  2082. FcbSize = SrvOpenSize = FobxSize = NonPagedFcbSize = 0;
  2083. switch (NodeType) {
  2084. default:
  2085. {
  2086. FcbSize = QuadAlign(sizeof(FCB));
  2087. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_FCB_EXTENSION) {
  2088. FcbSize += QuadAlign(pMRxDispatch->MRxFcbSize);
  2089. }
  2090. if (PoolType == NonPagedPool) {
  2091. NonPagedFcbSize = QuadAlign(sizeof(NON_PAGED_FCB));
  2092. }
  2093. if (NodeType == RDBSS_NTC_OPENTARGETDIR_FCB) {
  2094. break;
  2095. }
  2096. }
  2097. // lack of break intentional
  2098. case RDBSS_NTC_SRVOPEN :
  2099. case RDBSS_NTC_INTERNAL_SRVOPEN:
  2100. {
  2101. SrvOpenSize = QuadAlign(sizeof(SRV_OPEN));
  2102. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_SRV_OPEN_EXTENSION) {
  2103. SrvOpenSize += QuadAlign(pMRxDispatch->MRxSrvOpenSize);
  2104. }
  2105. }
  2106. // lack of break intentional
  2107. case RDBSS_NTC_FOBX :
  2108. {
  2109. FobxSize = QuadAlign(sizeof(FOBX));
  2110. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_FOBX_EXTENSION) {
  2111. FobxSize += QuadAlign(pMRxDispatch->MRxFobxSize);
  2112. }
  2113. }
  2114. }
  2115. if (pAlreadyAllocatedObject == NULL) {
  2116. pObject = RxAllocatePoolWithTag(
  2117. PoolType,
  2118. (FcbSize + SrvOpenSize + FobxSize + NonPagedFcbSize + NameSize),
  2119. RX_FCB_POOLTAG);
  2120. //ASSERT(pObject != NULL);
  2121. if (pObject==NULL) {
  2122. return(NULL);
  2123. }
  2124. } else {
  2125. pObject = pAlreadyAllocatedObject;
  2126. }
  2127. switch (NodeType) {
  2128. case RDBSS_NTC_FOBX:
  2129. {
  2130. pFobx = (PFOBX)pObject;
  2131. }
  2132. break;
  2133. case RDBSS_NTC_SRVOPEN:
  2134. {
  2135. pSrvOpen = (PSRV_OPEN)pObject;
  2136. pFobx = (PFOBX)((PBYTE)pSrvOpen + SrvOpenSize);
  2137. }
  2138. break;
  2139. case RDBSS_NTC_INTERNAL_SRVOPEN:
  2140. {
  2141. pSrvOpen = (PSRV_OPEN)pObject;
  2142. }
  2143. break;
  2144. default :
  2145. {
  2146. pFcb = (PFCB)pObject;
  2147. if (NodeType != RDBSS_NTC_OPENTARGETDIR_FCB) {
  2148. pSrvOpen = (PSRV_OPEN)((PBYTE)pFcb + FcbSize);
  2149. pFobx = (PFOBX)((PBYTE)pSrvOpen + SrvOpenSize);
  2150. }
  2151. if (PoolType == NonPagedPool) {
  2152. pNonPagedFcb = (PNON_PAGED_FCB)((PBYTE)pFobx + FobxSize);
  2153. pName = (PWCH)((PBYTE)pNonPagedFcb + NonPagedFcbSize);
  2154. } else {
  2155. pName = (PWCH)((PBYTE)pFcb + FcbSize + SrvOpenSize + FobxSize);
  2156. pNonPagedFcb = RxAllocatePoolWithTag(
  2157. NonPagedPool,
  2158. sizeof(NON_PAGED_FCB),
  2159. RX_NONPAGEDFCB_POOLTAG);
  2160. if (pNonPagedFcb == NULL) {
  2161. RxFreePool(pFcb);
  2162. return NULL;
  2163. }
  2164. }
  2165. }
  2166. break;
  2167. }
  2168. if (pFcb != NULL) {
  2169. ZeroAndInitializeNodeType(pFcb, RDBSS_NTC_STORAGE_TYPE_UNKNOWN, (NODE_BYTE_SIZE) FcbSize);
  2170. pFcb->NonPaged = pNonPagedFcb;
  2171. ZeroAndInitializeNodeType(pFcb->NonPaged, RDBSS_NTC_NONPAGED_FCB, ((NODE_BYTE_SIZE) sizeof( NON_PAGED_FCB )));
  2172. IF_DEBUG {
  2173. //make a copy of NonPaged so we can zap the real pointer and still find it
  2174. DbgDoit(pFcb->CopyOfNonPaged = pNonPagedFcb);
  2175. DbgDoit(pNonPagedFcb->FcbBackPointer = pFcb);
  2176. }
  2177. // Set up the pointers to the preallocated SRV_OPEN and FOBX if required
  2178. pFcb->InternalSrvOpen = pSrvOpen;
  2179. pFcb->InternalFobx = pFobx;
  2180. pFcb->PrivateAlreadyPrefixedName.Buffer = pName;
  2181. pFcb->PrivateAlreadyPrefixedName.Length = (USHORT)NameSize;
  2182. pFcb->PrivateAlreadyPrefixedName.MaximumLength = pFcb->PrivateAlreadyPrefixedName.Length;
  2183. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_FCB_EXTENSION) {
  2184. pFcb->Context = ((PBYTE)pFcb + QuadAlign(sizeof(FCB)));
  2185. }
  2186. ZeroAndInitializeNodeType(
  2187. &pFcb->FcbTableEntry,
  2188. RDBSS_NTC_FCB_TABLE_ENTRY,
  2189. sizeof(RX_FCB_TABLE_ENTRY));
  2190. InterlockedIncrement(&RxNumberOfActiveFcbs);
  2191. InterlockedIncrement(&RxDeviceObject->NumberOfActiveFcbs);
  2192. // Initialize the Advanced FCB header
  2193. ExInitializeFastMutex(&pNonPagedFcb->AdvancedFcbHeaderMutex);
  2194. FsRtlSetupAdvancedHeader(&pFcb->Header,&pNonPagedFcb->AdvancedFcbHeaderMutex);
  2195. }
  2196. if (pSrvOpen != NULL) {
  2197. ZeroAndInitializeNodeType(
  2198. pSrvOpen,
  2199. RDBSS_NTC_SRVOPEN,
  2200. (NODE_BYTE_SIZE)SrvOpenSize);
  2201. if ((NodeType != RDBSS_NTC_SRVOPEN) ) {
  2202. //here the srvopen has no internal fobx....set the "used" flag
  2203. SetFlag(pSrvOpen->Flags,SRVOPEN_FLAG_FOBX_USED);
  2204. pSrvOpen->InternalFobx = NULL;
  2205. } else {
  2206. pSrvOpen->InternalFobx = pFobx;
  2207. }
  2208. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_SRV_OPEN_EXTENSION) {
  2209. pSrvOpen->Context = ((PBYTE)pSrvOpen + QuadAlign(sizeof(SRV_OPEN)));
  2210. }
  2211. InitializeListHead( &pSrvOpen->SrvOpenQLinks);
  2212. }
  2213. if (pFobx != NULL) {
  2214. ZeroAndInitializeNodeType(
  2215. pFobx,
  2216. RDBSS_NTC_FOBX,
  2217. (NODE_BYTE_SIZE)FobxSize);
  2218. if (pMRxDispatch->MRxFlags & RDBSS_MANAGE_FOBX_EXTENSION) {
  2219. pFobx->Context = ((PBYTE)pFobx + QuadAlign(sizeof(FOBX)));
  2220. }
  2221. }
  2222. return pObject;
  2223. }
  2224. VOID
  2225. RxFreeFcbObject(PVOID pObject)
  2226. /*++
  2227. Routine Description:
  2228. The routine frees a FCB/SRV_OPEN and FOBX instance
  2229. Arguments:
  2230. pObject - the instance to be freed
  2231. Notes:
  2232. --*/
  2233. {
  2234. PAGED_CODE();
  2235. switch (NodeType(pObject)) {
  2236. case RDBSS_NTC_FOBX:
  2237. case RDBSS_NTC_SRVOPEN:
  2238. {
  2239. RxFreePool(pObject);
  2240. }
  2241. break;
  2242. default:
  2243. if (NodeTypeIsFcb(pObject)) {
  2244. PFCB pFcb = (PFCB)pObject;
  2245. PRDBSS_DEVICE_OBJECT RxDeviceObject = pFcb->RxDeviceObject;
  2246. // Release any Filter Context structures associated with this structure
  2247. FsRtlTeardownPerStreamContexts( &pFcb->Header );
  2248. DbgDoit((pFcb->Header.NodeTypeCode |= 0x1000));
  2249. if (pFcb->FcbState & FCB_STATE_PAGING_FILE) {
  2250. RxFreePool(pFcb);
  2251. } else {
  2252. RxFreePool(pFcb->NonPaged);
  2253. RxFreePool(pFcb);
  2254. }
  2255. InterlockedDecrement(&RxNumberOfActiveFcbs);
  2256. InterlockedDecrement(&RxDeviceObject->NumberOfActiveFcbs);
  2257. } else {
  2258. //ASSERT(!"Valid Object Type for RxFreeFcbObject");
  2259. }
  2260. }
  2261. }
  2262. PFCB
  2263. RxCreateNetFcb (
  2264. OUT PRX_CONTEXT RxContext,
  2265. IN PV_NET_ROOT VNetRoot,
  2266. IN PUNICODE_STRING Name
  2267. )
  2268. /*++
  2269. Routine Description:
  2270. This routine allocates, initializes, and inserts a new Fcb record into
  2271. the in memory data structures. The structure allocated has space for a srvopen
  2272. and a fobx. The size for all these things comes from the net root; they have
  2273. already been aligned.
  2274. An additional complication is that i use the same routine to initialize a
  2275. fake fcb for renames. in this case, i don't want it inserted into the tree.
  2276. You get a fake FCB with IrpSp->Flags|SL_OPEN_TAGET_DIRECTORY.
  2277. Arguments:
  2278. RxContext - an RxContext describing a create............
  2279. NetRoot - the net root that this FCB is being opened on
  2280. Name - The name of the FCB. the netroot MAY contain a nameprefix that is to be prepended here.
  2281. Return Value:
  2282. PFCB - Returns a pointer to the newly allocated FCB
  2283. --*/
  2284. {
  2285. PFCB Fcb;
  2286. POOL_TYPE PoolType;
  2287. NODE_TYPE_CODE NodeType;
  2288. RxCaptureRequestPacket;
  2289. RxCaptureParamBlock;
  2290. BOOLEAN IsPagingFile;
  2291. BOOLEAN FakeFcb;
  2292. PNET_ROOT NetRoot;
  2293. PRDBSS_DEVICE_OBJECT RxDeviceObject;
  2294. PRX_FCB_TABLE_ENTRY ThisEntry;
  2295. ULONG NameSize;
  2296. PAGED_CODE();
  2297. RxDbgTrace(+1, Dbg, ("RxCreateNetFcb\n", 0));
  2298. ASSERT( VNetRoot && (NodeType(VNetRoot) == RDBSS_NTC_V_NETROOT) );
  2299. NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
  2300. ASSERT( NodeType(NetRoot) == RDBSS_NTC_NETROOT );
  2301. ASSERT( ((PMRX_NET_ROOT)NetRoot) == RxContext->Create.pNetRoot );
  2302. RxDeviceObject = NetRoot->SrvCall->RxDeviceObject;
  2303. ASSERT( RxDeviceObject == RxContext->RxDeviceObject);
  2304. IsPagingFile = BooleanFlagOn( capPARAMS->Flags, SL_OPEN_PAGING_FILE );
  2305. FakeFcb = (BooleanFlagOn(capPARAMS->Flags,SL_OPEN_TARGET_DIRECTORY) &&
  2306. !BooleanFlagOn(NetRoot->Flags,NETROOT_FLAG_SUPPORTS_SYMBOLIC_LINKS));
  2307. ASSERT( FakeFcb || RxIsFcbTableLockExclusive ( &NetRoot->FcbTable ) );
  2308. NodeType = (FakeFcb) ? RDBSS_NTC_OPENTARGETDIR_FCB : RDBSS_NTC_STORAGE_TYPE_UNKNOWN;
  2309. PoolType = (IsPagingFile) ? NonPagedPool : PagedPool;
  2310. NameSize = Name->Length + NetRoot->InnerNamePrefix.Length;
  2311. Fcb = RxAllocateFcbObject(RxDeviceObject, NodeType, PoolType, NameSize, NULL);
  2312. if (Fcb != NULL) {
  2313. Fcb->CachedNetRootType = NetRoot->Type;
  2314. //Fcb->MRxDispatch = NetRoot->Dispatch;
  2315. Fcb->RxDeviceObject = RxDeviceObject;
  2316. Fcb->MRxDispatch = RxDeviceObject->Dispatch;
  2317. Fcb->VNetRoot = VNetRoot;
  2318. Fcb->pNetRoot = (PMRX_NET_ROOT)VNetRoot->pNetRoot;
  2319. InitializeListHead(&Fcb->SrvOpenList);
  2320. Fcb->SrvOpenListVersion = 0;
  2321. Fcb->FcbTableEntry.Path.Buffer = (PWCH)((PCHAR)Fcb->PrivateAlreadyPrefixedName.Buffer
  2322. + NetRoot->InnerNamePrefix.Length);
  2323. Fcb->FcbTableEntry.Path.Length = Name->Length;
  2324. Fcb->FcbTableEntry.Path.MaximumLength = Name->Length;
  2325. // finally, copy in the name, including the netroot prefix
  2326. ThisEntry = &Fcb->FcbTableEntry;
  2327. RxDbgTrace(0, Dbg, ("RxCreateNetFcb name buffer/length %08lx/%08lx\n",
  2328. ThisEntry->Path.Buffer, ThisEntry->Path.Length));
  2329. RxDbgTrace(0, Dbg, ("RxCreateNetFcb prefix/name %wZ/%wZ\n",
  2330. &NetRoot->InnerNamePrefix, Name));
  2331. RtlMoveMemory(
  2332. Fcb->PrivateAlreadyPrefixedName.Buffer,
  2333. NetRoot->InnerNamePrefix.Buffer,
  2334. NetRoot->InnerNamePrefix.Length);
  2335. RtlMoveMemory(
  2336. ThisEntry->Path.Buffer,
  2337. Name->Buffer,
  2338. Name->Length);
  2339. RxDbgTrace(0, Dbg, ("RxCreateNetFcb apname %wZ\n", &Fcb->PrivateAlreadyPrefixedName));
  2340. RxDbgTrace(0, Dbg, ("RxCreateNetFcb finalname %wZ\n", &Fcb->FcbTableEntry.Path));
  2341. if (FlagOn(RxContext->Create.Flags,RX_CONTEXT_CREATE_FLAG_ADDEDBACKSLASH)) {
  2342. SetFlag(Fcb->FcbState,FCB_STATE_ADDEDBACKSLASH);
  2343. }
  2344. InitializeListHead(&Fcb->NonPaged->TransitionWaitList);
  2345. // Check to see if we need to set the Fcb state to indicate that this
  2346. // is a paging file
  2347. if (IsPagingFile) {
  2348. Fcb->FcbState |= FCB_STATE_PAGING_FILE;
  2349. }
  2350. // Check to see whether this was marked for reparse
  2351. if( (RxContext->MajorFunction == IRP_MJ_CREATE) &&
  2352. (RxContext->Create.Flags & RX_CONTEXT_CREATE_FLAG_SPECIAL_PATH) )
  2353. {
  2354. Fcb->FcbState |= FCB_STATE_SPECIAL_PATH;
  2355. }
  2356. // The initial state, open count, and segment objects fields are already
  2357. // zero so we can skip setting them
  2358. //
  2359. //Initialize the resources
  2360. Fcb->Header.Resource = &Fcb->NonPaged->HeaderResource;
  2361. ExInitializeResourceLite(Fcb->Header.Resource);
  2362. Fcb->Header.PagingIoResource = &Fcb->NonPaged->PagingIoResource;
  2363. ExInitializeResourceLite(Fcb->Header.PagingIoResource);
  2364. //Initialize the filesize lock
  2365. FILESIZE_LOCK_DISABLED(
  2366. Fcb->Specific.Fcb.FileSizeLock = &Fcb->NonPaged->FileSizeLock;
  2367. ExInitializeFastMutex(Fcb->Specific.Fcb.FileSizeLock);
  2368. )
  2369. if (!FakeFcb) {
  2370. // everything worked.... insert into netroot table
  2371. RxFcbTableInsertFcb(
  2372. &NetRoot->FcbTable,
  2373. Fcb);
  2374. } else {
  2375. Fcb->FcbState |= FCB_STATE_FAKEFCB|FCB_STATE_NAME_ALREADY_REMOVED;
  2376. InitializeListHead(&Fcb->FcbTableEntry.HashLinks);
  2377. RxLog(("FakeFinally %lx\n",RxContext));
  2378. RxWmiLog(LOG,
  2379. RxCreateNetFcb_1,
  2380. LOGPTR(RxContext));
  2381. RxDbgTrace(0, Dbg, ("FakeFcb !!!!!!! Irpc=%08lx\n", RxContext));
  2382. }
  2383. RxReferenceVNetRoot(VNetRoot);
  2384. InterlockedIncrement(&Fcb->pNetRoot->NumberOfFcbs);
  2385. Fcb->ulFileSizeVersion=0;
  2386. #ifdef RDBSSLOG
  2387. RxLog(("Fcb nm %lx %wZ",Fcb,&(Fcb->FcbTableEntry.Path)));
  2388. RxWmiLog(LOG,
  2389. RxCreateNetFcb_2,
  2390. LOGPTR(Fcb)
  2391. LOGUSTR(Fcb->FcbTableEntry.Path));
  2392. {
  2393. char buffer[20];
  2394. ULONG len,remaining;
  2395. UNICODE_STRING jPrefix,jSuffix;
  2396. sprintf(buffer,"Fxx nm %p ",Fcb);
  2397. len = strlen(buffer);
  2398. remaining = MAX_RX_LOG_ENTRY_SIZE -1 - len;
  2399. if (remaining<Fcb->FcbTableEntry.Path.Length) {
  2400. jPrefix.Buffer = Fcb->FcbTableEntry.Path.Buffer;
  2401. jPrefix.Length = (USHORT)(sizeof(WCHAR)*(remaining-17));
  2402. jSuffix.Buffer = Fcb->FcbTableEntry.Path.Buffer-15+(Fcb->FcbTableEntry.Path.Length/sizeof(WCHAR));
  2403. jSuffix.Length = sizeof(WCHAR)*15;
  2404. RxLog(("%s%wZ..%wZ",buffer,&jPrefix,&jSuffix));
  2405. RxWmiLog(LOG,
  2406. RxCreateNetFcb_3,
  2407. LOGARSTR(buffer)
  2408. LOGUSTR(jPrefix)
  2409. LOGUSTR(jSuffix));
  2410. }
  2411. }
  2412. #endif
  2413. RxLoudFcbMsg("Create: ",&(Fcb->FcbTableEntry.Path));
  2414. RxDbgTrace(0, Dbg, ("RxCreateNetFcb nm.iso.ifox %08lx %08lx %08lx\n",
  2415. Fcb->FcbTableEntry.Path.Buffer, Fcb->InternalSrvOpen, Fcb->InternalFobx));
  2416. RxDbgTrace(-1, Dbg, ("RxCreateNetFcb %08lx %wZ\n", Fcb, &(Fcb->FcbTableEntry.Path)));
  2417. }
  2418. if (Fcb != NULL) {
  2419. RxReferenceNetFcb(Fcb);
  2420. #ifdef RX_WJ_DBG_SUPPORT
  2421. RxdInitializeFcbWriteJournalDebugSupport(Fcb);
  2422. #endif
  2423. }
  2424. return Fcb;
  2425. }
  2426. RX_FILE_TYPE
  2427. RxInferFileType(
  2428. IN PRX_CONTEXT RxContext
  2429. )
  2430. /*++
  2431. Routine Description:
  2432. This routine tries to infer the filetype from the createoptions.
  2433. Arguments:
  2434. RxContext - the context of the Open
  2435. Return Value:
  2436. the storagetype implied by the open.
  2437. --*/
  2438. {
  2439. ULONG CreateOptions = RxContext->Create.NtCreateParameters.CreateOptions;
  2440. PAGED_CODE();
  2441. switch (CreateOptions & (FILE_DIRECTORY_FILE|FILE_NON_DIRECTORY_FILE)) {
  2442. case FILE_DIRECTORY_FILE:
  2443. return(FileTypeDirectory);
  2444. case FILE_NON_DIRECTORY_FILE:
  2445. return(FileTypeFile);
  2446. default:
  2447. case 0:
  2448. return(FileTypeNotYetKnown); //0 => i don't know the storage type
  2449. }
  2450. }
  2451. VOID
  2452. RxFinishFcbInitialization(
  2453. IN OUT PMRX_FCB MrxFcb,
  2454. IN RDBSS_STORAGE_TYPE_CODES RdbssStorageType,
  2455. IN PFCB_INIT_PACKET InitPacket OPTIONAL
  2456. )
  2457. /*++
  2458. Routine Description:
  2459. This routine is used to finish initializing an FCB after
  2460. we find out what kind it is.
  2461. Arguments:
  2462. Fcb - the Fcb being initialzed
  2463. StorageType - the type of entity that the FCB refers to
  2464. InitPacket - extra data that is required depending on the type of entity
  2465. Return Value:
  2466. none.
  2467. --*/
  2468. {
  2469. PFCB Fcb = (PFCB)MrxFcb;
  2470. USHORT OldStorageType;
  2471. PAGED_CODE();
  2472. RxDbgTrace( 0, Dbg, ("RxFcbInit %x %08lx %wZ\n",
  2473. RdbssStorageType, Fcb, &(Fcb->FcbTableEntry.Path)));
  2474. OldStorageType = Fcb->Header.NodeTypeCode;
  2475. Fcb->Header.NodeTypeCode = (CSHORT)RdbssStorageType;
  2476. // only update the information in the Fcb if it's not already set
  2477. if ( !FlagOn(Fcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET) ) {
  2478. if (InitPacket != NULL) {
  2479. Fcb->Attributes = *(InitPacket->pAttributes);
  2480. Fcb->NumberOfLinks = *(InitPacket->pNumLinks);
  2481. Fcb->CreationTime = *(InitPacket-> pCreationTime);
  2482. Fcb->LastAccessTime = *(InitPacket->pLastAccessTime);
  2483. Fcb->LastWriteTime = *(InitPacket->pLastWriteTime);
  2484. Fcb->LastChangeTime = *(InitPacket->pLastChangeTime);
  2485. Fcb->ActualAllocationLength = InitPacket->pAllocationSize->QuadPart;
  2486. Fcb->Header.AllocationSize = *(InitPacket->pAllocationSize);
  2487. Fcb->Header.FileSize = *(InitPacket->pFileSize);
  2488. Fcb->Header.ValidDataLength = *(InitPacket->pValidDataLength);
  2489. //don't do this yet RxAdjustAllocationSizeforCC(Fcb);
  2490. SetFlag(Fcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET);
  2491. }
  2492. } else {
  2493. if (RdbssStorageType == RDBSS_NTC_MAILSLOT){
  2494. Fcb->Attributes = 0;
  2495. Fcb->NumberOfLinks = 0;
  2496. Fcb->CreationTime.QuadPart = 0;
  2497. Fcb->LastAccessTime.QuadPart = 0;
  2498. Fcb->LastWriteTime.QuadPart = 0;
  2499. Fcb->LastChangeTime.QuadPart = 0;
  2500. Fcb->ActualAllocationLength = 0;
  2501. Fcb->Header.AllocationSize.QuadPart = 0;
  2502. Fcb->Header.FileSize.QuadPart = 0;
  2503. Fcb->Header.ValidDataLength.QuadPart = 0;
  2504. SetFlag(Fcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET);
  2505. }
  2506. }
  2507. switch (RdbssStorageType) {
  2508. case RDBSS_NTC_MAILSLOT:
  2509. case RDBSS_NTC_SPOOLFILE:
  2510. break;
  2511. case RDBSS_STORAGE_NTC(FileTypeDirectory):
  2512. case RDBSS_STORAGE_NTC(FileTypeNotYetKnown):
  2513. break;
  2514. case RDBSS_STORAGE_NTC(FileTypeFile):
  2515. if (OldStorageType == RDBSS_STORAGE_NTC(FileTypeFile)) break;
  2516. RxInitializeLowIoPerFcbInfo(&Fcb->Specific.Fcb.LowIoPerFcbInfo);
  2517. FsRtlInitializeFileLock(
  2518. &Fcb->Specific.Fcb.FileLock,
  2519. RxLockOperationCompletion,
  2520. RxUnlockOperation );
  2521. //
  2522. // Initialize the oplock structure. NOT YET IMPLEMENTED!!!
  2523. //FsRtlInitializeOplock( &Fcb->Specific.Fcb.Oplock );
  2524. //
  2525. // Indicate that we want to be consulted on whether Fast I/O is possible
  2526. Fcb->Header.IsFastIoPossible = FastIoIsQuestionable;
  2527. break;
  2528. default:
  2529. ASSERT(FALSE);
  2530. break;
  2531. }
  2532. return;
  2533. }
  2534. VOID
  2535. RxRemoveNameNetFcb (
  2536. OUT PFCB ThisFcb
  2537. )
  2538. /*++
  2539. Routine Description:
  2540. The routine removes the name from the table and sets a flag indicateing
  2541. that it has done so. You must have already acquired the netroot
  2542. tablelock and have the fcblock as well.
  2543. Arguments:
  2544. ThisFcb - the Fcb being dereferenced
  2545. Return Value:
  2546. none.
  2547. --*/
  2548. {
  2549. PNET_ROOT NetRoot;
  2550. PAGED_CODE();
  2551. RxDbgTrace(+1, Dbg, ("RxRemoveNameNetFcb<+> %08lx %wZ RefC=%ld\n",
  2552. ThisFcb,&ThisFcb->FcbTableEntry.Path,
  2553. ThisFcb->NodeReferenceCount));
  2554. ASSERT( NodeTypeIsFcb(ThisFcb));
  2555. NetRoot = (PNET_ROOT)ThisFcb->VNetRoot->NetRoot;
  2556. ASSERT( RxIsFcbTableLockExclusive( &NetRoot->FcbTable ));
  2557. ASSERT( RxIsFcbAcquiredExclusive( ThisFcb ));
  2558. RxFcbTableRemoveFcb(
  2559. &NetRoot->FcbTable,
  2560. ThisFcb);
  2561. RxLoudFcbMsg("RemoveName: ",&(ThisFcb->FcbTableEntry.Path));
  2562. SetFlag(ThisFcb->FcbState, FCB_STATE_NAME_ALREADY_REMOVED);
  2563. RxDbgTrace(-1, Dbg, ("RxRemoveNameNetFcb<-> %08lx\n", ThisFcb));
  2564. }
  2565. VOID
  2566. RxPurgeFcb(
  2567. PFCB pFcb)
  2568. /*++
  2569. Routine Description:
  2570. The routine purges a given FCB instance. If the FCB has an open section
  2571. against it caused by cacheing the file then we need to purge to get
  2572. the close
  2573. Arguments:
  2574. pFcb - the Fcb being dereferenced
  2575. Notes:
  2576. On Entry to this routine the FCB must be accquired exclusive.
  2577. On Exit the FCB resource will be released and the FCB finalized if possible
  2578. --*/
  2579. {
  2580. PAGED_CODE();
  2581. ASSERT(RxIsFcbAcquiredExclusive(pFcb));
  2582. //make sure that it doesn't disappear
  2583. RxReferenceNetFcb(pFcb);
  2584. if (pFcb->OpenCount) {
  2585. RxPurgeFcbInSystemCache(
  2586. pFcb,
  2587. NULL,
  2588. 0,
  2589. TRUE,
  2590. TRUE);
  2591. }
  2592. if (!RxDereferenceAndFinalizeNetFcb(pFcb,NULL,FALSE,FALSE)) {
  2593. //if it remains, then release else, you can't!!
  2594. RxReleaseFcb(NULL,pFcb);
  2595. }
  2596. }
  2597. BOOLEAN
  2598. RxFinalizeNetFcb (
  2599. OUT PFCB ThisFcb,
  2600. IN BOOLEAN RecursiveFinalize,
  2601. IN BOOLEAN ForceFinalize,
  2602. IN LONG ReferenceCount
  2603. )
  2604. /*++
  2605. Routine Description:
  2606. The routine finalizes the given Fcb. This routine needs
  2607. the netroot tablelock; get it beforehand.
  2608. Arguments:
  2609. ThisFcb - the Fcb being dereferenced
  2610. Return Value:
  2611. BOOLEAN - tells whether finalization actually occured
  2612. --*/
  2613. {
  2614. BOOLEAN NodeActuallyFinalized = FALSE;
  2615. PAGED_CODE();
  2616. RxDbgTrace(+1, Dbg, ("RxFinalizeNetFcb<+> %08lx %wZ RefC=%ld\n",
  2617. ThisFcb,&ThisFcb->FcbTableEntry.Path,
  2618. ReferenceCount));
  2619. RxLoudFcbMsg("Finalize: ",&(ThisFcb->FcbTableEntry.Path));
  2620. ASSERT_CORRECT_FCB_STRUCTURE(ThisFcb);
  2621. ASSERT(RxIsFcbAcquiredExclusive( ThisFcb ));
  2622. ASSERT(!ForceFinalize);
  2623. if (!RecursiveFinalize) {
  2624. if ((ThisFcb->OpenCount != 0) || (ThisFcb->UncleanCount != 0)) {
  2625. // The FCB cannot be finalized because there are outstanding refrences to it.
  2626. ASSERT(ReferenceCount > 0);
  2627. return NodeActuallyFinalized;
  2628. }
  2629. } else {
  2630. PSRV_OPEN SrvOpen;
  2631. PLIST_ENTRY ListEntry;
  2632. IF_DEBUG{
  2633. if ( FALSE && ReferenceCount){
  2634. RxDbgTrace(0, Dbg, (" BAD!!!!!ReferenceCount = %08lx\n", ReferenceCount));
  2635. }
  2636. }
  2637. ListEntry = ThisFcb->SrvOpenList.Flink;
  2638. while (ListEntry != &ThisFcb->SrvOpenList) {
  2639. SrvOpen = CONTAINING_RECORD( ListEntry, SRV_OPEN, SrvOpenQLinks );
  2640. ListEntry = ListEntry->Flink;
  2641. RxFinalizeSrvOpen(SrvOpen,TRUE,ForceFinalize);
  2642. }
  2643. }
  2644. RxDbgTrace(0, Dbg, (" After Recursive Part, REfC=%lx\n", ReferenceCount));
  2645. // After the recursive finalization the reference count associated with the FCB
  2646. // could be atmost 1 for further finalization to occur. This final reference count
  2647. // belongs to the prefix name table of the NetRoot.
  2648. //The actual finalization is divided into two parts:
  2649. // 1) if we're at the end (refcount==1) or being forced, we do the one-time only stuff
  2650. // 2) if the refcount goes to zero, we actually do the free
  2651. ASSERT(ReferenceCount >= 1);
  2652. if (ReferenceCount == 1 || ForceFinalize ) {
  2653. PV_NET_ROOT VNetRoot = ThisFcb->VNetRoot;
  2654. ASSERT(ForceFinalize ||
  2655. (ThisFcb->OpenCount == 0) && (ThisFcb->UncleanCount == 0));
  2656. RxLog(("FinalFcb %lx %lx %lx %lx",
  2657. ThisFcb,ForceFinalize,ReferenceCount,ThisFcb->OpenCount));
  2658. RxWmiLog(LOG,
  2659. RxFinalizeNetFcb,
  2660. LOGPTR(ThisFcb)
  2661. LOGUCHAR(ForceFinalize)
  2662. LOGULONG(ReferenceCount)
  2663. LOGULONG(ThisFcb->OpenCount));
  2664. RxDbgTrace(0, Dbg, (" Before Phase 1, REfC=%lx\n", ReferenceCount));
  2665. if (!ThisFcb->UpperFinalizationDone) {
  2666. switch (NodeType(ThisFcb)) {
  2667. case RDBSS_STORAGE_NTC(FileTypeFile):
  2668. //FsRtlUninitializeOplock( &ThisFcb->Specific.Fcb.Oplock ); //NOT YET IMPLEMENTED
  2669. FsRtlUninitializeFileLock( &ThisFcb->Specific.Fcb.FileLock );
  2670. break;
  2671. default:
  2672. break;
  2673. }
  2674. if (!FlagOn(ThisFcb->FcbState,FCB_STATE_ORPHANED)) {
  2675. PNET_ROOT NetRoot = VNetRoot->NetRoot;
  2676. ASSERT(RxIsFcbTableLockExclusive ( &NetRoot->FcbTable ));
  2677. if (!FlagOn(ThisFcb->FcbState, FCB_STATE_NAME_ALREADY_REMOVED)){
  2678. RxFcbTableRemoveFcb(
  2679. &NetRoot->FcbTable,
  2680. ThisFcb);
  2681. }
  2682. }
  2683. RxDbgTrace(0, Dbg, (" EndOf Phase 1, REfC=%lx\n", ReferenceCount));
  2684. ThisFcb->UpperFinalizationDone = TRUE;
  2685. }
  2686. RxDbgTrace(0, Dbg, (" After Phase 1, REfC=%lx\n", ReferenceCount));
  2687. ASSERT(ReferenceCount >= 1);
  2688. if (ReferenceCount==1) {
  2689. if (ThisFcb->pBufferingStateChangeCompletedEvent != NULL) {
  2690. RxFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
  2691. }
  2692. if (ThisFcb->MRxDispatch != NULL) {
  2693. ThisFcb->MRxDispatch->MRxDeallocateForFcb((PMRX_FCB)ThisFcb);
  2694. }
  2695. DbgDoit(ThisFcb->NonPaged->NodeTypeCode &= ~0x4000);
  2696. ExDeleteResourceLite(ThisFcb->Header.Resource);
  2697. ExDeleteResourceLite(ThisFcb->Header.PagingIoResource);
  2698. InterlockedDecrement(&ThisFcb->pNetRoot->NumberOfFcbs);
  2699. RxDereferenceVNetRoot(VNetRoot,LHS_LockNotHeld);
  2700. ASSERT(IsListEmpty(&ThisFcb->FcbTableEntry.HashLinks));
  2701. #ifdef RX_WJ_DBG_SUPPORT
  2702. RxdTearDownFcbWriteJournalDebugSupport(ThisFcb);
  2703. #endif
  2704. NodeActuallyFinalized = TRUE;
  2705. ASSERT(!(ThisFcb->fMiniInited));
  2706. RxFreeFcbObject(ThisFcb);
  2707. }
  2708. } else {
  2709. RxDbgTrace(0, Dbg, (" NODE NOT ACTUALLY FINALIZED!!!%C\n", '!'));
  2710. }
  2711. RxDbgTrace(-1, Dbg, ("RxFinalizeNetFcb<-> %08lx\n", ThisFcb, NodeActuallyFinalized));
  2712. return NodeActuallyFinalized;
  2713. }
  2714. VOID
  2715. RxSetFileSizeWithLock (
  2716. IN OUT PFCB Fcb,
  2717. IN PLONGLONG FileSize
  2718. )
  2719. /*++
  2720. Routine Description:
  2721. This routine sets the filesize in the fcb header, taking a lock to ensure
  2722. that the 64-bit value is set and read consistently.
  2723. Arguments:
  2724. Fcb - the associated fcb
  2725. FileSize - ptr to the new filesize
  2726. Return Value:
  2727. none
  2728. Notes:
  2729. --*/
  2730. {
  2731. PAGED_CODE();
  2732. FILESIZE_LOCK_DISABLED(RxAcquireFileSizeLock(Fcb);)
  2733. Fcb->Header.FileSize.QuadPart = *FileSize;
  2734. Fcb->ulFileSizeVersion++;
  2735. FILESIZE_LOCK_DISABLED(RxReleaseFileSizeLock(Fcb);)
  2736. }
  2737. VOID
  2738. RxGetFileSizeWithLock (
  2739. IN PFCB Fcb,
  2740. OUT PLONGLONG FileSize
  2741. )
  2742. /*++
  2743. Routine Description:
  2744. This routine gets the filesize in the fcb header, taking a lock to ensure
  2745. that the 64-bit value is set and read consistently.
  2746. Arguments:
  2747. Fcb - the associated fcb
  2748. FileSize - ptr to the new filesize
  2749. Return Value:
  2750. none
  2751. Notes:
  2752. --*/
  2753. {
  2754. PAGED_CODE();
  2755. FILESIZE_LOCK_DISABLED(RxAcquireFileSizeLock(Fcb);)
  2756. *FileSize = Fcb->Header.FileSize.QuadPart;
  2757. FILESIZE_LOCK_DISABLED(RxReleaseFileSizeLock(Fcb);)
  2758. }
  2759. PSRV_OPEN
  2760. RxCreateSrvOpen (
  2761. IN PV_NET_ROOT pVNetRoot,
  2762. IN OUT PFCB Fcb)
  2763. /*++
  2764. Routine Description:
  2765. This routine allocates, initializes, and inserts a new srv_open record into
  2766. the in memory data structures. If a new structure has to be allocated, it
  2767. has space for a fobx. This routine sets the refcount to 1 and leaves the
  2768. srv_open in Condition_InTransition.
  2769. Arguments:
  2770. pVNetRoot - the V_NET_ROOT instance
  2771. Fcb - the associated fcb
  2772. Return Value:
  2773. the new SRV_OPEN instance
  2774. Notes:
  2775. On Entry : The FCB associated with the SRV_OPEN must have been acquired exclusive
  2776. On Exit : No change in resource ownership
  2777. --*/
  2778. {
  2779. PSRV_OPEN SrvOpen = NULL;
  2780. PNET_ROOT NetRoot;
  2781. POOL_TYPE PoolType;
  2782. ULONG SrvOpenFlags;
  2783. PAGED_CODE();
  2784. RxDbgTrace(+1, Dbg, ("RxCreateNetSrvOpen\n", 0));
  2785. ASSERT ( NodeTypeIsFcb(Fcb) );
  2786. ASSERT ( RxIsFcbAcquiredExclusive ( Fcb ) );
  2787. NetRoot = (PNET_ROOT)Fcb->VNetRoot->NetRoot;
  2788. try {
  2789. PoolType = (Fcb->FcbState & FCB_STATE_PAGING_FILE) ? NonPagedPool : PagedPool;
  2790. SrvOpen = Fcb->InternalSrvOpen;
  2791. if ((SrvOpen != NULL) &&
  2792. !(FlagOn(Fcb->FcbState,FCB_STATE_SRVOPEN_USED)) &&
  2793. !(FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_ENCLOSED_ALLOCATED)) &&
  2794. IsListEmpty(&SrvOpen->SrvOpenQLinks)) {
  2795. RxAllocateFcbObject(
  2796. NetRoot->SrvCall->RxDeviceObject,
  2797. RDBSS_NTC_INTERNAL_SRVOPEN,
  2798. PoolType,
  2799. 0,
  2800. SrvOpen); //this just initializes
  2801. SetFlag(Fcb->FcbState,FCB_STATE_SRVOPEN_USED);
  2802. SrvOpenFlags = SRVOPEN_FLAG_FOBX_USED | SRVOPEN_FLAG_ENCLOSED_ALLOCATED;
  2803. } else {
  2804. SrvOpen = RxAllocateFcbObject(NetRoot->SrvCall->RxDeviceObject,RDBSS_NTC_SRVOPEN,PoolType,0, NULL);
  2805. SrvOpenFlags = 0;
  2806. }
  2807. if (SrvOpen != NULL) {
  2808. SrvOpen->Flags = SrvOpenFlags;
  2809. SrvOpen->Fcb = Fcb;
  2810. SrvOpen->pAlreadyPrefixedName = &Fcb->PrivateAlreadyPrefixedName;
  2811. SrvOpen->pVNetRoot = (PMRX_V_NET_ROOT)pVNetRoot;
  2812. RxReferenceVNetRoot(pVNetRoot);
  2813. InterlockedIncrement(&pVNetRoot->pNetRoot->NumberOfSrvOpens);
  2814. SrvOpen->NodeReferenceCount = 1;
  2815. RxReferenceNetFcb(Fcb); //already have the lock
  2816. InsertTailList(&Fcb->SrvOpenList,&SrvOpen->SrvOpenQLinks);
  2817. Fcb->SrvOpenListVersion++;
  2818. InitializeListHead(&SrvOpen->FobxList);
  2819. InitializeListHead(&SrvOpen->TransitionWaitList);
  2820. InitializeListHead(&SrvOpen->ScavengerFinalizationList);
  2821. InitializeListHead(&SrvOpen->SrvOpenKeyList);
  2822. }
  2823. } finally {
  2824. DebugUnwind( RxCreateFcb );
  2825. if (AbnormalTermination()) {
  2826. // If this is an abnormal termination then undo our work; this is
  2827. // one of those happy times when the existing code will work
  2828. if (SrvOpen != NULL) {
  2829. RxFinalizeSrvOpen( SrvOpen,TRUE,TRUE );
  2830. }
  2831. } else {
  2832. if (SrvOpen != NULL) {
  2833. RxLog(("SrvOp %lx %lx\n",SrvOpen,SrvOpen->Fcb));
  2834. RxWmiLog(LOG,
  2835. RxCreateSrvOpen,
  2836. LOGPTR(SrvOpen)
  2837. LOGPTR(SrvOpen->Fcb));
  2838. }
  2839. }
  2840. }
  2841. RxDbgTrace(-1, Dbg, ("RxCreateNetSrvOpen -> %08lx\n", SrvOpen));
  2842. return SrvOpen;
  2843. }
  2844. BOOLEAN
  2845. RxFinalizeSrvOpen (
  2846. OUT PSRV_OPEN ThisSrvOpen,
  2847. IN BOOLEAN RecursiveFinalize,
  2848. IN BOOLEAN ForceFinalize
  2849. )
  2850. /*++
  2851. Routine Description:
  2852. The routine finalizes the given SrvOpen.
  2853. Arguments:
  2854. ThisSrvOpen - the SrvOpen being dereferenced
  2855. Return Value:
  2856. BOOLEAN - tells whether finalization actually occured
  2857. Notes:
  2858. On Entry : 1) The FCB associated with the SRV_OPEN must have been acquired exclusive
  2859. 2) The tablelock associated with FCB's NET_ROOT instance must have been
  2860. acquired shared(atleast)
  2861. On Exit : No change in resource ownership
  2862. --*/
  2863. {
  2864. NTSTATUS Status;
  2865. BOOLEAN NodeActuallyFinalized = FALSE;
  2866. PAGED_CODE();
  2867. RxDbgTrace(+1, Dbg, ("RxFinalizeSrvOpen<+> %08lx %wZ RefC=%ld\n",
  2868. ThisSrvOpen,&ThisSrvOpen->Fcb->FcbTableEntry.Path,
  2869. ThisSrvOpen->NodeReferenceCount));
  2870. ASSERT(NodeType(ThisSrvOpen) == RDBSS_NTC_SRVOPEN );
  2871. if (RecursiveFinalize) {
  2872. PFOBX Fobx;
  2873. PLIST_ENTRY ListEntry;
  2874. IF_DEBUG{
  2875. if ( FALSE && ThisSrvOpen->NodeReferenceCount){
  2876. RxDbgTrace(0, Dbg, (" BAD!!!!!ReferenceCount = %08lx\n", ThisSrvOpen->NodeReferenceCount));
  2877. }
  2878. }
  2879. ListEntry = ThisSrvOpen->FobxList.Flink;
  2880. while (ListEntry != &ThisSrvOpen->FobxList) {
  2881. Fobx = CONTAINING_RECORD( ListEntry, FOBX, FobxQLinks );
  2882. ListEntry = ListEntry->Flink;
  2883. RxFinalizeNetFobx(Fobx,TRUE,ForceFinalize);
  2884. }
  2885. }
  2886. if( ThisSrvOpen->NodeReferenceCount == 0 || ForceFinalize ){
  2887. BOOLEAN FreeSrvOpen;
  2888. PFCB Fcb;
  2889. Fcb = ThisSrvOpen->Fcb;
  2890. RxLog(("FinalSrvOp %lx %lx %lx",
  2891. ThisSrvOpen,ForceFinalize,ThisSrvOpen->NodeReferenceCount
  2892. ));
  2893. RxWmiLog(LOG,
  2894. RxFinalizeSrvOpen,
  2895. LOGPTR(ThisSrvOpen)
  2896. LOGUCHAR(ForceFinalize)
  2897. LOGULONG(ThisSrvOpen->NodeReferenceCount));
  2898. FreeSrvOpen = !FlagOn(ThisSrvOpen->Flags,SRVOPEN_FLAG_ENCLOSED_ALLOCATED);
  2899. if ((!ThisSrvOpen->UpperFinalizationDone) &&
  2900. ((ThisSrvOpen->Condition != Condition_Good) ||
  2901. (ThisSrvOpen->Flags & SRVOPEN_FLAG_CLOSED))) {
  2902. ASSERT(NodeType(Fcb) != RDBSS_NTC_OPENTARGETDIR_FCB );
  2903. ASSERT(RxIsFcbAcquiredExclusive ( Fcb ) );
  2904. RxPurgeChangeBufferingStateRequestsForSrvOpen(ThisSrvOpen);
  2905. if (!FlagOn(Fcb->FcbState,FCB_STATE_ORPHANED)) {
  2906. // close the file.
  2907. MINIRDR_CALL_THROUGH(Status,Fcb->MRxDispatch,MRxForceClosed,((PMRX_SRV_OPEN)ThisSrvOpen));
  2908. }
  2909. RemoveEntryList ( &ThisSrvOpen->SrvOpenQLinks);
  2910. InitializeListHead( &ThisSrvOpen->SrvOpenQLinks);
  2911. Fcb->SrvOpenListVersion++;
  2912. if (ThisSrvOpen->pVNetRoot != NULL) {
  2913. InterlockedDecrement(&ThisSrvOpen->pVNetRoot->pNetRoot->NumberOfSrvOpens);
  2914. RxDereferenceVNetRoot(
  2915. (PV_NET_ROOT)ThisSrvOpen->pVNetRoot,
  2916. LHS_LockNotHeld);
  2917. ThisSrvOpen->pVNetRoot = NULL;
  2918. }
  2919. ThisSrvOpen->UpperFinalizationDone = TRUE;
  2920. }
  2921. if (ThisSrvOpen->NodeReferenceCount == 0) {
  2922. ASSERT(IsListEmpty(&ThisSrvOpen->SrvOpenKeyList));
  2923. if (!IsListEmpty(&ThisSrvOpen->SrvOpenQLinks)) {
  2924. RemoveEntryList(&ThisSrvOpen->SrvOpenQLinks);
  2925. InitializeListHead(&ThisSrvOpen->SrvOpenQLinks);
  2926. }
  2927. if (FreeSrvOpen ) {
  2928. RxFreeFcbObject(ThisSrvOpen);
  2929. }
  2930. if (!FreeSrvOpen){
  2931. ClearFlag(Fcb->FcbState,FCB_STATE_SRVOPEN_USED);
  2932. }
  2933. RxDereferenceNetFcb(Fcb);
  2934. }
  2935. NodeActuallyFinalized = TRUE;
  2936. } else {
  2937. RxDbgTrace(0, Dbg, (" NODE NOT ACTUALLY FINALIZED!!!%C\n", '!'));
  2938. }
  2939. RxDbgTrace(-1, Dbg, ("RxFinalizeSrvOpen<-> %08lx\n", ThisSrvOpen, NodeActuallyFinalized));
  2940. return NodeActuallyFinalized;
  2941. }
  2942. ULONG RxPreviousFobxSerialNumber = 0;
  2943. PMRX_FOBX
  2944. RxCreateNetFobx (
  2945. OUT PRX_CONTEXT RxContext,
  2946. IN PMRX_SRV_OPEN mrxSrvOpen
  2947. )
  2948. /*++
  2949. Routine Description:
  2950. This routine allocates, initializes, and inserts a new file object extension instance.
  2951. Arguments:
  2952. RxContext - an RxContext describing a create............
  2953. pSrvOpen - the associated SrvOpen
  2954. Return Value:
  2955. none
  2956. Notes:
  2957. On Entry : FCB associated with the FOBX instance have been acquired exclusive.
  2958. On Exit : No change in resource ownership
  2959. --*/
  2960. {
  2961. PFCB pFcb;
  2962. PFOBX pFobx;
  2963. PSRV_OPEN pSrvOpen = (PSRV_OPEN)mrxSrvOpen;
  2964. RxCaptureRequestPacket;
  2965. RxCaptureParamBlock;
  2966. ULONG FobxFlags;
  2967. POOL_TYPE PoolType;
  2968. PAGED_CODE();
  2969. RxDbgTrace(+1, Dbg, ("RxCreateFobx<+>\n", 0));
  2970. ASSERT(NodeType(pSrvOpen) == RDBSS_NTC_SRVOPEN);
  2971. ASSERT( NodeTypeIsFcb(pSrvOpen->Fcb) );
  2972. ASSERT(RxIsFcbAcquiredExclusive(pSrvOpen->Fcb));
  2973. pFcb = pSrvOpen->Fcb;
  2974. PoolType = (pFcb->FcbState & FCB_STATE_PAGING_FILE) ? NonPagedPool : PagedPool;
  2975. if (!(FlagOn(pFcb->FcbState,FCB_STATE_FOBX_USED)) &&
  2976. (pSrvOpen == pFcb->InternalSrvOpen)){
  2977. // Try and use the FOBX allocated as part of the FCB if it is available
  2978. pFobx = pFcb->InternalFobx;
  2979. RxAllocateFcbObject(
  2980. pFcb->RxDeviceObject,
  2981. RDBSS_NTC_FOBX,PoolType,
  2982. 0,
  2983. pFobx);//just initialize
  2984. SetFlag(pFcb->FcbState,FCB_STATE_FOBX_USED);
  2985. FobxFlags = FOBX_FLAG_ENCLOSED_ALLOCATED;
  2986. } else if (!(FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_FOBX_USED))){
  2987. // Try and use the FOBX allocated as part of the SRV_OPEN if it is available
  2988. pFobx = pSrvOpen->InternalFobx;
  2989. RxAllocateFcbObject(
  2990. pFcb->RxDeviceObject,
  2991. RDBSS_NTC_FOBX,
  2992. PoolType,
  2993. 0,
  2994. pFobx);//just initialize
  2995. SetFlag(pSrvOpen->Flags,SRVOPEN_FLAG_FOBX_USED);
  2996. FobxFlags = FOBX_FLAG_ENCLOSED_ALLOCATED;
  2997. } else {
  2998. pFobx = RxAllocateFcbObject(
  2999. pFcb->RxDeviceObject,
  3000. RDBSS_NTC_FOBX,
  3001. PoolType,
  3002. 0,
  3003. NULL);
  3004. FobxFlags = 0;
  3005. }
  3006. if (pFobx != NULL) {
  3007. PMRX_NET_ROOT pNetRoot;
  3008. pFobx->Flags = FobxFlags;
  3009. if ((pNetRoot = RxContext->Create.pNetRoot) != NULL) {
  3010. switch (pNetRoot->DeviceType) {
  3011. case RxDeviceType(NAMED_PIPE):
  3012. RxInitializeThrottlingState(
  3013. &pFobx->Specific.NamedPipe.ThrottlingState,
  3014. pNetRoot->NamedPipeParameters.PipeReadThrottlingParameters.Increment,
  3015. pNetRoot->NamedPipeParameters.PipeReadThrottlingParameters.MaximumDelay
  3016. );
  3017. break;
  3018. case RxDeviceType(DISK):
  3019. RxInitializeThrottlingState(
  3020. &pFobx->Specific.DiskFile.LockThrottlingState,
  3021. pNetRoot->DiskParameters.LockThrottlingParameters.Increment,
  3022. pNetRoot->DiskParameters.LockThrottlingParameters.MaximumDelay
  3023. );
  3024. break;
  3025. }
  3026. }
  3027. if (FlagOn(RxContext->Create.Flags,RX_CONTEXT_CREATE_FLAG_UNC_NAME)){
  3028. SetFlag(pFobx->Flags,FOBX_FLAG_UNC_NAME);
  3029. //DbgPrint("setting UNC flag in fobx\n");
  3030. }
  3031. if (FlagOn(RxContext->Create.NtCreateParameters.CreateOptions,FILE_OPEN_FOR_BACKUP_INTENT)) {
  3032. SetFlag(pFobx->Flags,FOBX_FLAG_BACKUP_INTENT);
  3033. }
  3034. pFobx->FobxSerialNumber = 0;
  3035. pFobx->SrvOpen = pSrvOpen;
  3036. pFobx->NodeReferenceCount = 1;
  3037. pFobx->fOpenCountDecremented = FALSE;
  3038. RxReferenceSrvOpen(pSrvOpen);
  3039. InterlockedIncrement(&pSrvOpen->pVNetRoot->NumberOfFobxs);
  3040. InsertTailList(&pSrvOpen->FobxList,&pFobx->FobxQLinks);
  3041. InitializeListHead(&pFobx->ClosePendingList);
  3042. InitializeListHead(&pFobx->ScavengerFinalizationList);
  3043. RxLog(("Fobx %lx %lx %lx\n",pFobx,pFobx->SrvOpen,pFobx->SrvOpen->Fcb));
  3044. RxWmiLog(LOG,
  3045. RxCreateNetFobx,
  3046. LOGPTR(pFobx)
  3047. LOGPTR(pFobx->SrvOpen)
  3048. LOGPTR(pFobx->SrvOpen->Fcb));
  3049. }
  3050. RxDbgTrace(-1, Dbg, ("RxCreateNetFobx<-> %08lx\n", pFobx));
  3051. return (PMRX_FOBX)pFobx;
  3052. }
  3053. BOOLEAN
  3054. RxFinalizeNetFobx (
  3055. OUT PFOBX ThisFobx,
  3056. IN BOOLEAN RecursiveFinalize,
  3057. IN BOOLEAN ForceFinalize
  3058. )
  3059. /*++
  3060. Routine Description:
  3061. The routine finalizes the given Fobx. you need exclusive fcblock.
  3062. Arguments:
  3063. ThisFobx - the Fobx being dereferenced
  3064. Return Value:
  3065. BOOLEAN - tells whether finalization actually occured
  3066. Notes:
  3067. On Entry : FCB associated with the FOBX instance must have been acquired exclusive.
  3068. On Exit : No change in resource ownership
  3069. --*/
  3070. {
  3071. BOOLEAN NodeActuallyFinalized = FALSE;
  3072. PAGED_CODE();
  3073. RxDbgTrace(+1, Dbg, ("RxFinalizeFobx<+> %08lx %wZ RefC=%ld\n",
  3074. ThisFobx,&ThisFobx->SrvOpen->Fcb->FcbTableEntry.Path,
  3075. ThisFobx->NodeReferenceCount));
  3076. ASSERT( NodeType(ThisFobx) == RDBSS_NTC_FOBX );
  3077. if( ThisFobx->NodeReferenceCount == 0 || ForceFinalize ){
  3078. NTSTATUS Status;
  3079. PSRV_OPEN SrvOpen = ThisFobx->SrvOpen;
  3080. PFCB Fcb = SrvOpen->Fcb;
  3081. BOOLEAN FreeFobx = !FlagOn(ThisFobx->Flags,FOBX_FLAG_ENCLOSED_ALLOCATED);
  3082. RxLog(("FinalFobx %lx %lx %lx",
  3083. ThisFobx,ForceFinalize,ThisFobx->NodeReferenceCount
  3084. ));
  3085. RxWmiLog(LOG,
  3086. RxFinalizeNetFobx_1,
  3087. LOGPTR(ThisFobx)
  3088. LOGUCHAR(ForceFinalize)
  3089. LOGULONG(ThisFobx->NodeReferenceCount));
  3090. if (!ThisFobx->UpperFinalizationDone) {
  3091. ASSERT(NodeType(ThisFobx->SrvOpen->Fcb) != RDBSS_NTC_OPENTARGETDIR_FCB );
  3092. ASSERT( RxIsFcbAcquiredExclusive ( ThisFobx->SrvOpen->Fcb ) );
  3093. RemoveEntryList ( &ThisFobx->FobxQLinks);
  3094. if (FlagOn(ThisFobx->Flags,FOBX_FLAG_FREE_UNICODE)){
  3095. RxFreePool(ThisFobx->UnicodeQueryTemplate.Buffer);
  3096. }
  3097. if ((Fcb->MRxDispatch != NULL) && (Fcb->MRxDispatch->MRxDeallocateForFobx != NULL)) {
  3098. Fcb->MRxDispatch->MRxDeallocateForFobx((PMRX_FOBX)ThisFobx);
  3099. }
  3100. if (!FlagOn(ThisFobx->Flags,FOBX_FLAG_SRVOPEN_CLOSED)) {
  3101. // DbgPrint("@@@@ CloseAssociatedSrvOpen FOBX(%lx) SrvOpen(%lx) %wZ\n",ThisFobx,SrvOpen,&SrvOpen->Fcb->FcbTableEntry.Path);
  3102. Status = RxCloseAssociatedSrvOpen(ThisFobx,NULL);
  3103. RxLog(("$$ScCl FOBX %lx SrvOp %lx %lx\n",ThisFobx,ThisFobx->SrvOpen,Status));
  3104. RxWmiLog(LOG,
  3105. RxFinalizeNetFobx_2,
  3106. LOGPTR(ThisFobx)
  3107. LOGPTR(ThisFobx->SrvOpen)
  3108. LOGULONG(Status));
  3109. }
  3110. ThisFobx->UpperFinalizationDone = TRUE;
  3111. }
  3112. if (ThisFobx->NodeReferenceCount == 0){
  3113. ASSERT(IsListEmpty(&ThisFobx->ClosePendingList));
  3114. if (ThisFobx == Fcb->InternalFobx) {
  3115. ClearFlag(Fcb->FcbState,FCB_STATE_FOBX_USED);
  3116. } else if (ThisFobx == SrvOpen->InternalFobx) {
  3117. ClearFlag(SrvOpen->Flags,SRVOPEN_FLAG_FOBX_USED);
  3118. }
  3119. if (SrvOpen != NULL) {
  3120. ThisFobx->SrvOpen = NULL;
  3121. InterlockedDecrement(&SrvOpen->pVNetRoot->NumberOfFobxs);
  3122. RxDereferenceSrvOpen(SrvOpen,LHS_ExclusiveLockHeld);
  3123. }
  3124. if (FreeFobx){
  3125. RxFreeFcbObject(ThisFobx);
  3126. }
  3127. NodeActuallyFinalized = TRUE;
  3128. }
  3129. } else {
  3130. RxDbgTrace(0, Dbg, (" NODE NOT ACTUALLY FINALIZED!!!%C\n", '!'));
  3131. }
  3132. RxDbgTrace(-1, Dbg, ("RxFinalizeFobx<-> %08lx\n", ThisFobx, NodeActuallyFinalized));
  3133. return NodeActuallyFinalized;
  3134. }
  3135. //#define RDBSS_ENABLELOUDFCBOPSBYDEFAULT
  3136. #if DBG
  3137. #ifdef RDBSS_ENABLELOUDFCBOPSBYDEFAULT
  3138. BOOLEAN RxLoudFcbOpsOnExes = TRUE;
  3139. #else
  3140. BOOLEAN RxLoudFcbOpsOnExes = FALSE;
  3141. #endif // RDBSS_ENABLELOUDFCBOPSBYDEFAULT
  3142. BOOLEAN
  3143. RxLoudFcbMsg(
  3144. PUCHAR msg,
  3145. PUNICODE_STRING Name
  3146. )
  3147. {
  3148. PWCHAR Buffer;
  3149. ULONG Length;
  3150. if (!RxLoudFcbOpsOnExes) {
  3151. return FALSE;
  3152. }
  3153. Length = (Name->Length)/sizeof(WCHAR);
  3154. Buffer = Name->Buffer + Length;
  3155. if (
  3156. ( Length < 4 )
  3157. || ( (Buffer[-1]&'E') != 'E' )
  3158. || ( (Buffer[-2]&'X') != 'X' )
  3159. || ( (Buffer[-3]&'E') != 'E' )
  3160. || ( (Buffer[-4]&'.') != '.' )
  3161. ) { return FALSE; }
  3162. DbgPrint("--->%s %wZ\n",msg,Name);
  3163. return(TRUE);
  3164. }
  3165. #endif
  3166. VOID
  3167. RxCheckFcbStructuresForAlignment(void)
  3168. {
  3169. ULONG StructureId;
  3170. PAGED_CODE();
  3171. if (FIELD_OFFSET(NET_ROOT,SrvCall) != FIELD_OFFSET(NET_ROOT,pSrvCall)) {
  3172. StructureId = 'RN'; goto DO_A_BUGCHECK;
  3173. }
  3174. if (FIELD_OFFSET(V_NET_ROOT,NetRoot) != FIELD_OFFSET(V_NET_ROOT,pNetRoot)) {
  3175. StructureId = 'RNV'; goto DO_A_BUGCHECK;
  3176. }
  3177. if (FIELD_OFFSET(FCB,VNetRoot) != FIELD_OFFSET(FCB,VNetRoot)) {
  3178. StructureId = 'BCF'; goto DO_A_BUGCHECK;
  3179. }
  3180. if (FIELD_OFFSET(SRV_OPEN,Fcb) != FIELD_OFFSET(SRV_OPEN,pFcb)) {
  3181. StructureId = 'NPOS'; goto DO_A_BUGCHECK;
  3182. }
  3183. if (FIELD_OFFSET(FOBX,SrvOpen) != FIELD_OFFSET(FOBX,pSrvOpen)) {
  3184. StructureId = 'XBOF'; goto DO_A_BUGCHECK;
  3185. }
  3186. return;
  3187. DO_A_BUGCHECK:
  3188. RxBugCheck( StructureId, 0, 0 );
  3189. }
  3190. BOOLEAN
  3191. RxIsThisACscAgentOpen(
  3192. IN PRX_CONTEXT RxContext
  3193. )
  3194. /*++
  3195. Routine Description:
  3196. This routine determines if the open was made by the user mode CSC agent.
  3197. Arguments:
  3198. RxContext - the RDBSS context
  3199. Return Value:
  3200. TRUE - if it is an agent open, FALSE otherwise
  3201. Notes:
  3202. The agent opens are always satisfied by going to the server. They are never
  3203. satisfied from the cached copies. This enables reintegration using snapshots
  3204. even when the files are being currently used.
  3205. --*/
  3206. {
  3207. BOOLEAN AgentOpen = FALSE;
  3208. ULONG EaInformationLength;
  3209. PDFS_NAME_CONTEXT pDfsNameContext;
  3210. if (RxContext->Create.EaLength > 0) {
  3211. PFILE_FULL_EA_INFORMATION pEaEntry;
  3212. pEaEntry = (PFILE_FULL_EA_INFORMATION)RxContext->Create.EaBuffer;
  3213. ASSERT(pEaEntry != NULL);
  3214. for(;;) {
  3215. if (strcmp(pEaEntry->EaName, EA_NAME_CSCAGENT) == 0) {
  3216. AgentOpen = TRUE;
  3217. break;
  3218. }
  3219. if (pEaEntry->NextEntryOffset == 0) {
  3220. break;
  3221. } else {
  3222. pEaEntry = (PFILE_FULL_EA_INFORMATION)
  3223. ((PCHAR) pEaEntry + pEaEntry->NextEntryOffset);
  3224. }
  3225. }
  3226. }
  3227. pDfsNameContext = RxContext->Create.NtCreateParameters.DfsNameContext;
  3228. if ((pDfsNameContext != NULL) &&
  3229. (pDfsNameContext->NameContextType == DFS_CSCAGENT_NAME_CONTEXT)) {
  3230. AgentOpen = TRUE;
  3231. }
  3232. return AgentOpen;
  3233. }
  3234. VOID
  3235. RxOrphanThisFcb(
  3236. PFCB pFcb
  3237. )
  3238. /*++
  3239. Routine Description:
  3240. This routine orphans an FCB
  3241. Arguments:
  3242. pFcb - the fcb to be orphaned
  3243. Return Value:
  3244. None
  3245. Notes:
  3246. --*/
  3247. {
  3248. // force orphan all SrvOpens for this FCB and orphan the FCB itself
  3249. RxOrphanSrvOpensForThisFcb(pFcb, NULL, TRUE);
  3250. }
  3251. VOID
  3252. RxOrphanSrvOpensForThisFcb(
  3253. PFCB pFcb,
  3254. IN PV_NET_ROOT ThisVNetRoot,
  3255. BOOLEAN fOrphanAll
  3256. )
  3257. /*++
  3258. Routine Description:
  3259. This routine orphans all srvopens for a file belonging to a particular VNetRoot. The
  3260. SrvOpen collapsing routine elsewhere makes sure that srvopens for different vnetroots
  3261. are not collapsed.
  3262. Arguments:
  3263. pFcb - the fcb whose srvopens need to be orphaned
  3264. ThisVNetRoot - the VNetRoot for which the SrvOpens have to be orphaned
  3265. fOrphanAll - Orphan all SrvOpens, ie ignore the ThisVNetRoot parameter
  3266. Return Value:
  3267. None
  3268. Notes:
  3269. --*/
  3270. {
  3271. NTSTATUS Status;
  3272. PLIST_ENTRY pListEntry;
  3273. BOOLEAN fAllSrvOpensOrphaned = TRUE;
  3274. // fOrphanAll = TRUE; // temporarily force the old behaviour
  3275. Status = RxAcquireExclusiveFcb(NULL,pFcb);
  3276. ASSERT(Status == STATUS_SUCCESS);
  3277. RxReferenceNetFcb(pFcb);
  3278. pListEntry = pFcb->SrvOpenList.Flink;
  3279. while (pListEntry != &pFcb->SrvOpenList) {
  3280. PSRV_OPEN pSrvOpen;
  3281. pSrvOpen = (PSRV_OPEN)
  3282. (CONTAINING_RECORD(
  3283. pListEntry,
  3284. SRV_OPEN,
  3285. SrvOpenQLinks));
  3286. pListEntry = pSrvOpen->SrvOpenQLinks.Flink;
  3287. if (!FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_ORPHANED))
  3288. {
  3289. // NB check fOrphanAll first as if it is TRUE, the ThisVNetRoot
  3290. // parameter maybe NULL
  3291. if (fOrphanAll || ((PV_NET_ROOT)(pSrvOpen->pVNetRoot) == ThisVNetRoot))
  3292. {
  3293. PLIST_ENTRY pEntry;
  3294. PFOBX pFobx;
  3295. SetFlag(pSrvOpen->Flags, SRVOPEN_FLAG_ORPHANED);
  3296. RxAcquireScavengerMutex();
  3297. pEntry = pSrvOpen->FobxList.Flink;
  3298. while (pEntry != &pSrvOpen->FobxList) {
  3299. pFobx = (PFOBX)CONTAINING_RECORD(
  3300. pEntry,
  3301. FOBX,
  3302. FobxQLinks);
  3303. if (!pFobx->fOpenCountDecremented) {
  3304. InterlockedDecrement(&pFcb->OpenCount);
  3305. pFobx->fOpenCountDecremented = TRUE;
  3306. }
  3307. pEntry = pEntry->Flink;
  3308. }
  3309. RxReleaseScavengerMutex();
  3310. if (!FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_CLOSED) &&
  3311. !IsListEmpty(&pSrvOpen->FobxList)) {
  3312. PLIST_ENTRY pEntry;
  3313. NTSTATUS Status;
  3314. PFOBX pFobx;
  3315. pEntry = pSrvOpen->FobxList.Flink;
  3316. pFobx = (PFOBX)CONTAINING_RECORD(
  3317. pEntry,
  3318. FOBX,
  3319. FobxQLinks);
  3320. RxReferenceNetFobx(pFobx);
  3321. RxPurgeChangeBufferingStateRequestsForSrvOpen(pSrvOpen);
  3322. Status = RxCloseAssociatedSrvOpen(pFobx,NULL);
  3323. RxDereferenceNetFobx(pFobx,LHS_ExclusiveLockHeld);
  3324. pListEntry = pFcb->SrvOpenList.Flink;
  3325. }
  3326. }
  3327. else
  3328. {
  3329. // we found atleast one SrvOpen which is a) Not Orphaned and
  3330. // b) doesn't belong to this VNetRoot
  3331. // hence we cannot orphan this FCB
  3332. fAllSrvOpensOrphaned = FALSE;
  3333. }
  3334. }
  3335. }
  3336. // if all srvopens for this FCB are in orphaned state, orphan the FCB as well.
  3337. if (fAllSrvOpensOrphaned)
  3338. {
  3339. // remove the FCB from the netname table
  3340. // so that any new opens/creates for this file will create a new FCB.
  3341. RxRemoveNameNetFcb(pFcb);
  3342. SetFlag(pFcb->FcbState,FCB_STATE_ORPHANED);
  3343. ClearFlag(pFcb->FcbState,FCB_STATE_WRITECACHEING_ENABLED);
  3344. if (!RxDereferenceAndFinalizeNetFcb(pFcb,NULL,FALSE,FALSE)) {
  3345. RxReleaseFcb(NULL,pFcb);
  3346. }
  3347. }
  3348. else
  3349. {
  3350. // some srvopens are still active, just remove the refcount and release the FCB
  3351. RxDereferenceNetFcb(pFcb);
  3352. RxReleaseFcb(NULL,pFcb);
  3353. }
  3354. }
  3355. VOID
  3356. RxForceFinalizeAllVNetRoots(
  3357. PNET_ROOT pNetRoot
  3358. )
  3359. /*++
  3360. Routine Description:
  3361. The routine foce finalizes all the vnetroots from the given netroot. You must be exclusive on
  3362. the NetName tablelock.
  3363. Arguments:
  3364. pNetRoot - the NetRoot
  3365. Return Value:
  3366. VOID
  3367. --*/
  3368. {
  3369. PLIST_ENTRY pListEntry;
  3370. pListEntry = pNetRoot->VirtualNetRoots.Flink;
  3371. while (pListEntry != &pNetRoot->VirtualNetRoots)
  3372. {
  3373. PV_NET_ROOT pTempVNetRoot;
  3374. pTempVNetRoot = (PV_NET_ROOT)
  3375. CONTAINING_RECORD(
  3376. pListEntry,
  3377. V_NET_ROOT,
  3378. NetRootListEntry);
  3379. if (NodeType(pTempVNetRoot) == RDBSS_NTC_V_NETROOT)
  3380. {
  3381. RxFinalizeVNetRoot(pTempVNetRoot, TRUE, TRUE);
  3382. }
  3383. pListEntry = pListEntry->Flink;
  3384. }
  3385. }