Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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