mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 22:28:36 +00:00
[RXCE]
- Implement RxFinalizeConnection(), RxOrphanSrvOpens() - Stub RxOrphanSrvOpensForThisFcb() [RDBSS] - Fix a bug in RxCommonDevFCBClose() where prefix table wasn't acquire exclusively; this was problematic due to potential prefix table removal on dereference - Stub RxCancelNotifyChangeDirectoryRequestsForVNetRoot() This commit basically allows you to delete a NFS share you would have made use of in ReactOS. Like net use z: \\share\path can be deleted through net use /delete z: Note that if you access the share using cmd tools (dir, copy, more, and so on), dismount will work. If you attempt to access with Explorer, then, handles will be kept open and dismount will fail. CORE-8204 CORE-11327 svn path=/trunk/; revision=75286
This commit is contained in:
parent
d135302c2f
commit
f93ac7e964
|
@ -630,7 +630,7 @@ RxFinalizeNetFobx(
|
||||||
(Fcb)->Header.AllocationSize.QuadPart = as; \
|
(Fcb)->Header.AllocationSize.QuadPart = as; \
|
||||||
(Fcb)->Header.FileSize.QuadPart = fs; \
|
(Fcb)->Header.FileSize.QuadPart = fs; \
|
||||||
(Fcb)->Header.ValidDataLength.QuadPart = vdl; \
|
(Fcb)->Header.ValidDataLength.QuadPart = vdl; \
|
||||||
(Fcb)->FcbState |= FCB_STATE_TIME_AND_SIZE_ALREADY_SET
|
SetFlag((Fcb)->FcbState, FCB_STATE_TIME_AND_SIZE_ALREADY_SET)
|
||||||
|
|
||||||
#define TRACKER_ACQUIRE_FCB 0x61616161
|
#define TRACKER_ACQUIRE_FCB 0x61616161
|
||||||
#define TRACKER_RELEASE_FCB_NO_BUFF_PENDING 0x72727272
|
#define TRACKER_RELEASE_FCB_NO_BUFF_PENDING 0x72727272
|
||||||
|
|
|
@ -31,6 +31,7 @@ typedef struct _MRX_SRV_CALL_
|
||||||
#define NET_ROOT_PIPE ((UCHAR)1)
|
#define NET_ROOT_PIPE ((UCHAR)1)
|
||||||
#define NET_ROOT_PRINT ((UCHAR)3)
|
#define NET_ROOT_PRINT ((UCHAR)3)
|
||||||
#define NET_ROOT_WILD ((UCHAR)4)
|
#define NET_ROOT_WILD ((UCHAR)4)
|
||||||
|
#define NET_ROOT_MAILSLOT ((UCHAR)5)
|
||||||
|
|
||||||
typedef UCHAR NET_ROOT_TYPE, *PNET_ROOT_TYPE;
|
typedef UCHAR NET_ROOT_TYPE, *PNET_ROOT_TYPE;
|
||||||
|
|
||||||
|
|
|
@ -435,6 +435,11 @@ RxRemoveFirstContextFromSerializationQueue(
|
||||||
ExReleaseFastMutex(Mutex); \
|
ExReleaseFastMutex(Mutex); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
|
||||||
|
PV_NET_ROOT VNetRoot,
|
||||||
|
BOOLEAN ForceFilesClosed);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
RxCancelNotifyChangeDirectoryRequestsForFobx(
|
RxCancelNotifyChangeDirectoryRequestsForFobx(
|
||||||
PFOBX Fobx
|
PFOBX Fobx
|
||||||
|
|
|
@ -693,6 +693,12 @@ VOID
|
||||||
RxOrphanThisFcb(
|
RxOrphanThisFcb(
|
||||||
_In_ PFCB Fcb);
|
_In_ PFCB Fcb);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
RxOrphanSrvOpensForThisFcb(
|
||||||
|
_In_ PFCB Fcb,
|
||||||
|
_In_ PV_NET_ROOT ThisVNetRoot,
|
||||||
|
_In_ BOOLEAN OrphanAll);
|
||||||
|
|
||||||
#define RxEqualConnectionId(C1, C2) RtlEqualMemory(C1, C2, sizeof(RX_CONNECTION_ID))
|
#define RxEqualConnectionId(C1, C2) RtlEqualMemory(C1, C2, sizeof(RX_CONNECTION_ID))
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -792,6 +792,15 @@ RxCancelNotifyChangeDirectoryRequestsForFobx(
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
|
||||||
|
PV_NET_ROOT VNetRoot,
|
||||||
|
BOOLEAN ForceFilesClosed)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
RxCancelRoutine(
|
RxCancelRoutine(
|
||||||
|
@ -2066,7 +2075,7 @@ RxCommonDevFCBClose(
|
||||||
/* Our FOBX if set, has to be a VNetRoot */
|
/* Our FOBX if set, has to be a VNetRoot */
|
||||||
if (NetRoot != NULL)
|
if (NetRoot != NULL)
|
||||||
{
|
{
|
||||||
RxAcquirePrefixTableLockShared(Context->RxDeviceObject->pRxNetNameTable, TRUE);
|
RxAcquirePrefixTableLockExclusive(Context->RxDeviceObject->pRxNetNameTable, TRUE);
|
||||||
if (NetRoot->NodeTypeCode == RDBSS_NTC_V_NETROOT)
|
if (NetRoot->NodeTypeCode == RDBSS_NTC_V_NETROOT)
|
||||||
{
|
{
|
||||||
--NetRoot->NumberOfOpens;
|
--NetRoot->NumberOfOpens;
|
||||||
|
@ -3786,17 +3795,6 @@ RxFastIoWrite(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
RxFinalizeConnection(
|
|
||||||
IN OUT PNET_ROOT NetRoot,
|
|
||||||
IN OUT PV_NET_ROOT VNetRoot OPTIONAL,
|
|
||||||
IN LOGICAL ForceFilesClosed)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
RxFindOrCreateFcb(
|
RxFindOrCreateFcb(
|
||||||
PRX_CONTEXT RxContext,
|
PRX_CONTEXT RxContext,
|
||||||
|
|
|
@ -2435,6 +2435,182 @@ RxFcbTableRemoveFcb(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
RxFinalizeConnection(
|
||||||
|
IN OUT PNET_ROOT NetRoot,
|
||||||
|
IN OUT PV_NET_ROOT VNetRoot OPTIONAL,
|
||||||
|
IN LOGICAL ForceFilesClosed)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PRX_PREFIX_TABLE PrefixTable;
|
||||||
|
ULONG UncleanAny, UncleanDir;
|
||||||
|
LONG FilesOpen, AdditionalRef;
|
||||||
|
BOOLEAN PrefixLocked, FcbTableLocked, ForceClose;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(NodeType(NetRoot) == RDBSS_NTC_NETROOT);
|
||||||
|
|
||||||
|
/* Get a BOOLEAN out of LOGICAL
|
||||||
|
* -1 is like FALSE but also drops extra V_NET_ROOT reference in case of failure
|
||||||
|
*/
|
||||||
|
ForceClose = (ForceFilesClosed == TRUE ? TRUE : FALSE);
|
||||||
|
|
||||||
|
/* First, delete any notification change */
|
||||||
|
Status = RxCancelNotifyChangeDirectoryRequestsForVNetRoot(VNetRoot, ForceClose);
|
||||||
|
/* If it failed, continue if forced */
|
||||||
|
if (Status != STATUS_SUCCESS && !ForceFilesClosed)
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
/* Reset status, in case notification deletion failed */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
PrefixTable = NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
|
||||||
|
|
||||||
|
PrefixLocked = FALSE;
|
||||||
|
FcbTableLocked = FALSE;
|
||||||
|
FilesOpen = 0;
|
||||||
|
AdditionalRef = 0;
|
||||||
|
UncleanAny = 0;
|
||||||
|
UncleanDir = 0;
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
|
||||||
|
PrefixLocked = TRUE;
|
||||||
|
|
||||||
|
RxReferenceNetRoot(NetRoot);
|
||||||
|
|
||||||
|
RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
|
||||||
|
FcbTableLocked = TRUE;
|
||||||
|
|
||||||
|
/* If our V_NET_ROOT wasn't finalized yet, proceed! */
|
||||||
|
if (!VNetRoot->ConnectionFinalizationDone)
|
||||||
|
{
|
||||||
|
USHORT Bucket;
|
||||||
|
PRX_FCB_TABLE FcbTable;
|
||||||
|
|
||||||
|
DPRINT("Finalizing connection %p: %wZ\n", NetRoot, &NetRoot->PrefixEntry.Prefix);
|
||||||
|
|
||||||
|
/* We'll browse all its associated FCB to check whether they're open/orphaned */
|
||||||
|
FcbTable = &NetRoot->FcbTable;
|
||||||
|
for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY BucketList, Entry;
|
||||||
|
|
||||||
|
BucketList = &FcbTable->HashBuckets[Bucket];
|
||||||
|
Entry = BucketList->Flink;
|
||||||
|
while (Entry != BucketList)
|
||||||
|
{
|
||||||
|
PFCB Fcb;
|
||||||
|
|
||||||
|
Fcb = CONTAINING_RECORD(Entry, FCB, FcbTableEntry.HashLinks);
|
||||||
|
Entry = Entry->Flink;
|
||||||
|
|
||||||
|
/* FCB for this connection, go ahead */
|
||||||
|
if (Fcb->VNetRoot == VNetRoot)
|
||||||
|
{
|
||||||
|
/* It's still open, and no force? Fail and keep track */
|
||||||
|
if (Fcb->UncleanCount > 0 && !ForceClose)
|
||||||
|
{
|
||||||
|
Status = STATUS_CONNECTION_IN_USE;
|
||||||
|
if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
|
||||||
|
{
|
||||||
|
++UncleanDir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++UncleanAny;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Else, force purge */
|
||||||
|
ASSERT(NodeTypeIsFcb(Fcb));
|
||||||
|
|
||||||
|
Status = RxAcquireExclusiveFcb(NULL, Fcb);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
ClearFlag(Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED);
|
||||||
|
|
||||||
|
RxScavengeRelatedFobxs(Fcb);
|
||||||
|
RxPurgeFcb(Fcb);
|
||||||
|
|
||||||
|
/* We don't need to release FCB lock, FCB finalize will take care of it */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No files left, our V_NET_ROOT is finalized */
|
||||||
|
if (VNetRoot->NumberOfFobxs == 0)
|
||||||
|
{
|
||||||
|
VNetRoot->ConnectionFinalizationDone = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep Number of open files and track of the extra reference */
|
||||||
|
FilesOpen = VNetRoot->NumberOfFobxs;
|
||||||
|
AdditionalRef = VNetRoot->AdditionalReferenceForDeleteFsctlTaken;
|
||||||
|
/* If force close, caller doesn't want to keep connection alive
|
||||||
|
* and wants it totally close, so drop the V_NET_ROOT too
|
||||||
|
*/
|
||||||
|
if (ForceClose)
|
||||||
|
{
|
||||||
|
RxFinalizeVNetRoot(VNetRoot, FALSE, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_FINALLY
|
||||||
|
{
|
||||||
|
/* Release what was acquired */
|
||||||
|
if (FcbTableLocked)
|
||||||
|
{
|
||||||
|
RxReleaseFcbTableLock(&NetRoot->FcbTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If close is forced, only fix status if there are open files */
|
||||||
|
if (ForceClose)
|
||||||
|
{
|
||||||
|
if (Status != STATUS_SUCCESS && UncleanAny != 0)
|
||||||
|
{
|
||||||
|
Status = STATUS_FILES_OPEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Else, fix status and fail closing if there are open files */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((Status != STATUS_SUCCESS && UncleanAny != 0) || FilesOpen > 0)
|
||||||
|
{
|
||||||
|
Status = STATUS_FILES_OPEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("UncleanAny: %ld, UncleanDir: %ld, FilesOpen: %ld\n", UncleanAny, UncleanDir, FilesOpen);
|
||||||
|
|
||||||
|
/* If we're are asked to remove the extra ref, or if closing was a success, do it;
|
||||||
|
* only if it was still referenced!
|
||||||
|
*/
|
||||||
|
if ((ForceFilesClosed == 0xFF || Status == STATUS_SUCCESS) && AdditionalRef != 0)
|
||||||
|
{
|
||||||
|
VNetRoot->AdditionalReferenceForDeleteFsctlTaken = 0;
|
||||||
|
RxDereferenceVNetRoot(VNetRoot, LHS_ExclusiveLockHeld);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PrefixLocked)
|
||||||
|
{
|
||||||
|
RxDereferenceNetRoot(NetRoot, LHS_ExclusiveLockHeld);
|
||||||
|
RxReleasePrefixTableLock(PrefixTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -5433,6 +5609,67 @@ RxOrphanThisFcb(
|
||||||
VOID
|
VOID
|
||||||
RxOrphanSrvOpens(
|
RxOrphanSrvOpens(
|
||||||
IN PV_NET_ROOT ThisVNetRoot)
|
IN PV_NET_ROOT ThisVNetRoot)
|
||||||
|
{
|
||||||
|
PFCB Fcb;
|
||||||
|
USHORT Bucket;
|
||||||
|
PNET_ROOT NetRoot;
|
||||||
|
PRX_FCB_TABLE FcbTable;
|
||||||
|
PRX_PREFIX_TABLE PrefixTable;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Mailslot won't have any SRV_OPEN (to orphan) */
|
||||||
|
NetRoot = (PNET_ROOT)ThisVNetRoot->pNetRoot;
|
||||||
|
if (NetRoot->Type == NET_ROOT_MAILSLOT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefixTable = NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
|
||||||
|
ASSERT(RxIsPrefixTableLockExclusive(PrefixTable));
|
||||||
|
|
||||||
|
FcbTable = &NetRoot->FcbTable;
|
||||||
|
RxAcquireFcbTableLockExclusive(FcbTable, TRUE);
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
/* Now, we'll browse all the FCBs attached, and orphan related SRV_OPENs */
|
||||||
|
for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY BucketList, Entry;
|
||||||
|
|
||||||
|
BucketList = &FcbTable->HashBuckets[Bucket];
|
||||||
|
Entry = BucketList->Flink;
|
||||||
|
while (Entry != BucketList)
|
||||||
|
{
|
||||||
|
Fcb = CONTAINING_RECORD(Entry, FCB, FcbTableEntry.HashLinks);
|
||||||
|
Entry = Entry->Flink;
|
||||||
|
|
||||||
|
ASSERT(NodeTypeIsFcb(Fcb));
|
||||||
|
RxOrphanSrvOpensForThisFcb(Fcb, ThisVNetRoot, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Of course, don't forget about NULL-entry */
|
||||||
|
if (FcbTable->TableEntryForNull != NULL)
|
||||||
|
{
|
||||||
|
Fcb = CONTAINING_RECORD(FcbTable->TableEntryForNull, FCB, FcbTableEntry.HashLinks);
|
||||||
|
ASSERT(NodeTypeIsFcb(Fcb));
|
||||||
|
RxOrphanSrvOpensForThisFcb(Fcb, ThisVNetRoot, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_FINALLY
|
||||||
|
{
|
||||||
|
RxReleaseFcbTableLock(FcbTable);
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
RxOrphanSrvOpensForThisFcb(
|
||||||
|
IN PFCB Fcb,
|
||||||
|
IN PV_NET_ROOT ThisVNetRoot,
|
||||||
|
IN BOOLEAN OrphanAll)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue