- Implement RxCloseAssociatedSrvOpen(), RxFastIoRead(), RxPurgeNetFcb(), RxRemoveShareAccess(), RxRemoveShareAccessPerSrvOpens()
- Continue implementation of RxCommonCleanup() to handle allocated SRV_OPEN
- Halfplement RxFastIoCheckIfPossible() so that it handles read operations
- Stub RxCancelNotifyChangeDirectoryRequestsForFobx()

[RXCE]
- Implement RxChangeBufferingState(), RxFinalizeSrvOpen(), RxFreeFcbObject(), RxGatherRequestsForSrvOpen(), RxGetDeviceObjectOfInstance(), RxInitializeRxTimer(), RxMarkFobxOnCleanup(), RxMarkFobxOnClose(), RxpDiscardChangeBufferingStateRequests(), RxpDispatchChangeBufferingStateRequests(), RxpLookupSrvOpenForRequestLite(), RxpMarkInstanceForScavengedFinalization(), RxPostOneShotTimerRequest(), RxPrepareRequestForReuse(), RxProcessChangeBufferingStateRequestsForSrvOpen(), RxpUndoScavengerFinalizationMarking(), RxPurgeChangeBufferingStateRequestsForSrvOpen(), RxPurgeFobxFromCache(), RxRemoveNameNetFcb(), RxScavengerTimerRoutine(), RxTimerDispatch()
- Finish implementation of RxDereference() to handle scavenger
- Finish implementation of RxLowIoCompletionTail() to handle blocked operations resume
- Fix a bug in RxFinalizeNetFcb() where it was dereferencing its NET_ROOT instead of its V_NET_ROOT
- Fix bugs in __RxAcquireFcb() where it improperly handled the lack of RX_CONTEXT
- Halfplement RxResumeBlockedOperations_ALL() to extract blocked operations from RX_CONTEXT (and drop them...)
- Stub RxDispatchChangeBufferingStateRequests(), RxScavengerFinalizeEntries()

[COPYSUP]
- Implement FsRtlCopyRead2()
This library is basically what you can find in FsRtl with an extended support of Top Level IRP. It is used by RDBSS for FastIO. Next to come in it will be FsRtlCopyWrite2().

This commit brings several improvements to current work on RBDSS/RXCE. First of all, both libraries will leak less (again!).
It also brings the scavenger infrastructure (not fully fonctionnal though). Our NFS driver doesn't make use of it though.
Finally, this brings support of FastIO (for read operations ;-)) to our NFS driver!

Regarding CORE-13484, with copy + FastIO I could copy a file without troubles. But that seems to be still problematic with xcopy without FastIO...

CORE-13484
CORE-11327

svn path=/trunk/; revision=75265
This commit is contained in:
Pierre Schweitzer 2017-07-02 17:00:11 +00:00
parent 92ea310563
commit 0584d49170
14 changed files with 2282 additions and 93 deletions

View File

@ -11,7 +11,7 @@ add_definitions(-DRDBSS_TRACKER)
add_library(nfs41_driver SHARED ${SOURCE} nfs.rc)
set_module_type(nfs41_driver kernelmodedriver)
target_link_libraries(nfs41_driver ntoskrnl_vista rdbsslib rxce memcmp ${PSEH_LIB})
target_link_libraries(nfs41_driver ntoskrnl_vista rdbsslib rxce copysup memcmp ${PSEH_LIB})
add_importlibs(nfs41_driver ntoskrnl hal)
if((NOT MSVC) AND (NOT CMAKE_C_COMPILER_ID STREQUAL "Clang"))

View File

@ -1,6 +1,20 @@
#ifndef __BUFFRING_H__
#define __BUFFRING_H__
#define RX_REQUEST_PREPARED_FOR_HANDLING 0x10000000
typedef struct _CHANGE_BUFFERING_STATE_REQUEST_
{
LIST_ENTRY ListEntry;
ULONG Flags;
#if (_WIN32_WINNT < 0x0600)
PSRV_CALL pSrvCall;
#endif
PSRV_OPEN SrvOpen;
PVOID SrvOpenKey;
PVOID MRxContext;
} CHANGE_BUFFERING_STATE_REQUEST, *PCHANGE_BUFFERING_STATE_REQUEST;
typedef struct _RX_BUFFERING_MANAGER_
{
BOOLEAN DispatcherActive;
@ -49,6 +63,10 @@ VOID
RxProcessFcbChangeBufferingStateRequest(
_In_ PFCB Fcb);
VOID
RxPurgeChangeBufferingStateRequestsForSrvOpen(
_In_ PSRV_OPEN SrvOpen);
VOID
RxCompleteSrvOpenKeyAssociation(
_Inout_ PSRV_OPEN SrvOpen);

View File

@ -211,10 +211,14 @@ typedef struct _FCB
#define FCB_STATE_FILE_IS_BUF_COMPRESSED 0x00004000
#define FCB_STATE_FILE_IS_DISK_COMPRESSED 0x00008000
#define FCB_STATE_FILE_IS_SHADOWED 0x00010000
#define FCB_STATE_BUFFERSTATE_CHANGING 0x00002000
#define FCB_STATE_SPECIAL_PATH 0x00020000
#define FCB_STATE_TIME_AND_SIZE_ALREADY_SET 0x00040000
#define FCB_STATE_FILETIMECACHEING_ENABLED 0x00080000
#define FCB_STATE_FILESIZECACHEING_ENABLED 0x00100000
#define FCB_STATE_LOCK_BUFFERING_ENABLED 0x00200000
#define FCB_STATE_COLLAPSING_ENABLED 0x00400000
#define FCB_STATE_OPENSHARING_ENABLED 0x00800000
#define FCB_STATE_READBUFFERING_ENABLED 0x01000000
#define FCB_STATE_READCACHING_ENABLED 0x02000000
#define FCB_STATE_WRITEBUFFERING_ENABLED 0x04000000
@ -224,6 +228,17 @@ typedef struct _FCB
#define FCB_STATE_FOBX_USED 0x40000000
#define FCB_STATE_SRVOPEN_USED 0x80000000
#define FCB_STATE_BUFFERING_STATE_MASK \
((FCB_STATE_WRITECACHING_ENABLED \
| FCB_STATE_WRITEBUFFERING_ENABLED \
| FCB_STATE_READCACHING_ENABLED \
| FCB_STATE_READBUFFERING_ENABLED \
| FCB_STATE_OPENSHARING_ENABLED \
| FCB_STATE_COLLAPSING_ENABLED \
| FCB_STATE_LOCK_BUFFERING_ENABLED \
| FCB_STATE_FILESIZECACHEING_ENABLED \
| FCB_STATE_FILETIMECACHEING_ENABLED))
typedef struct _FCB_INIT_PACKET
{
PULONG pAttributes;
@ -276,6 +291,7 @@ typedef struct _SRV_OPEN
#define FOBX_FLAG_SRVOPEN_CLOSED 0x1000000
#define FOBX_FLAG_UNC_NAME 0x2000000
#define FOBX_FLAG_ENCLOSED_ALLOCATED 0x4000000
#define FOBX_FLAG_MARKED_AS_DORMANT 0x8000000
typedef struct _FOBX
{
@ -354,53 +370,57 @@ RxpTrackDereference(
DbgPrint("%ld\n", Count); \
}
#define RxReferenceSrvCall(SrvCall) \
RxpTrackReference(RDBSS_REF_TRACK_SRVCALL, __FILE__, __LINE__, SrvCall); \
RxReference(SrvCall)
#define RxReferenceSrvCall(SrvCall) \
RxpTrackReference(RDBSS_REF_TRACK_SRVCALL, __FILE__, __LINE__, SrvCall); \
RxReference(SrvCall)
#define RxDereferenceSrvCall(SrvCall, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_SRVCALL, __FILE__, __LINE__, SrvCall); \
RxDereference(SrvCall, LockHoldingState)
#define RxDereferenceSrvCall(SrvCall, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_SRVCALL, __FILE__, __LINE__, SrvCall); \
RxDereference(SrvCall, LockHoldingState)
#define RxReferenceNetRoot(NetRoot) \
RxpTrackReference(RDBSS_REF_TRACK_NETROOT, __FILE__, __LINE__, NetRoot); \
RxReference(NetRoot)
#define RxReferenceNetRoot(NetRoot) \
RxpTrackReference(RDBSS_REF_TRACK_NETROOT, __FILE__, __LINE__, NetRoot); \
RxReference(NetRoot)
#define RxDereferenceNetRoot(NetRoot, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_NETROOT, __FILE__, __LINE__, NetRoot); \
RxDereference(NetRoot, LockHoldingState)
#define RxDereferenceNetRoot(NetRoot, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_NETROOT, __FILE__, __LINE__, NetRoot); \
RxDereference(NetRoot, LockHoldingState)
#define RxReferenceVNetRoot(VNetRoot) \
RxpTrackReference(RDBSS_REF_TRACK_VNETROOT, __FILE__, __LINE__, VNetRoot); \
RxReference(VNetRoot)
#define RxReferenceVNetRoot(VNetRoot) \
RxpTrackReference(RDBSS_REF_TRACK_VNETROOT, __FILE__, __LINE__, VNetRoot); \
RxReference(VNetRoot)
#define RxDereferenceVNetRoot(VNetRoot, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_VNETROOT, __FILE__, __LINE__, VNetRoot); \
RxDereference(VNetRoot, LockHoldingState)
#define RxDereferenceVNetRoot(VNetRoot, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_VNETROOT, __FILE__, __LINE__, VNetRoot); \
RxDereference(VNetRoot, LockHoldingState)
#define RxDereferenceNetFobx(Fobx, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_NETFOBX, __FILE__, __LINE__, Fobx); \
RxDereference(Fobx, LockHoldingState)
#define RxReferenceNetFobx(Fobx) \
RxpTrackReference(RDBSS_REF_TRACK_NETFOBX, __FILE__, __LINE__, Fobx); \
RxReference(Fobx)
#define RxReferenceSrvOpen(SrvOpen) \
RxpTrackReference(RDBSS_REF_TRACK_SRVOPEN, __FILE__, __LINE__, SrvOpen); \
RxReference(SrvOpen)
#define RxDereferenceNetFobx(Fobx, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_NETFOBX, __FILE__, __LINE__, Fobx); \
RxDereference(Fobx, LockHoldingState)
#define RxDereferenceSrvOpen(SrvOpen, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_SRVOPEN, __FILE__, __LINE__, SrvOpen); \
RxDereference(SrvOpen, LockHoldingState)
#define RxReferenceSrvOpen(SrvOpen) \
RxpTrackReference(RDBSS_REF_TRACK_SRVOPEN, __FILE__, __LINE__, SrvOpen); \
RxReference(SrvOpen)
#define RxReferenceNetFcb(Fcb) \
(RxpTrackReference(RDBSS_REF_TRACK_NETFCB, __FILE__, __LINE__, Fcb), \
RxpReferenceNetFcb(Fcb))
#define RxDereferenceSrvOpen(SrvOpen, LockHoldingState) \
RxpTrackDereference(RDBSS_REF_TRACK_SRVOPEN, __FILE__, __LINE__, SrvOpen); \
RxDereference(SrvOpen, LockHoldingState)
#define RxDereferenceNetFcb(Fcb) \
((LONG)RxpTrackDereference(RDBSS_REF_TRACK_NETFCB, __FILE__, __LINE__, Fcb), \
RxpDereferenceNetFcb(Fcb))
#define RxReferenceNetFcb(Fcb) \
(RxpTrackReference(RDBSS_REF_TRACK_NETFCB, __FILE__, __LINE__, Fcb), \
RxpReferenceNetFcb(Fcb))
#define RxDereferenceAndFinalizeNetFcb(Fcb, RxContext, RecursiveFinalize, ForceFinalize) \
(RxpTrackDereference(RDBSS_REF_TRACK_NETFCB, __FILE__, __LINE__, Fcb), \
RxpDereferenceAndFinalizeNetFcb(Fcb, RxContext, RecursiveFinalize, ForceFinalize))
#define RxDereferenceNetFcb(Fcb) \
((LONG)RxpTrackDereference(RDBSS_REF_TRACK_NETFCB, __FILE__, __LINE__, Fcb), \
RxpDereferenceNetFcb(Fcb))
#define RxDereferenceAndFinalizeNetFcb(Fcb, RxContext, RecursiveFinalize, ForceFinalize) \
(RxpTrackDereference(RDBSS_REF_TRACK_NETFCB, __FILE__, __LINE__, Fcb), \
RxpDereferenceAndFinalizeNetFcb(Fcb, RxContext, RecursiveFinalize, ForceFinalize))
PSRV_CALL
RxCreateSrvCall(
@ -533,6 +553,10 @@ RxFinishFcbInitialization(
#define RxWaitForStableSrvOpen(S, R) RxWaitForStableCondition(&(S)->Condition, &(S)->TransitionWaitList, (R), NULL)
#define RxTransitionSrvOpen(S, C) RxUpdateCondition((C), &(S)->Condition, &(S)->TransitionWaitList)
VOID
RxRemoveNameNetFcb(
_Out_ PFCB ThisFcb);
LONG
RxpReferenceNetFcb(
_In_ PFCB Fcb);
@ -616,6 +640,16 @@ RxFinalizeNetFobx(
#define TRACKER_RELEASE_NON_EXCL_FCB_FOR_THRD_BUFF_PENDING 0x72727430
#define TRACKER_RELEASE_EXCL_FCB_FOR_THRD_BUFF_PENDING 0x72727431
#define TRACKER_FCB_FREE 0x72724372
#define FCB_STATE_BUFFERING_STATE_WITH_NO_SHARES \
(( FCB_STATE_WRITECACHING_ENABLED \
| FCB_STATE_WRITEBUFFERING_ENABLED \
| FCB_STATE_READCACHING_ENABLED \
| FCB_STATE_READBUFFERING_ENABLED \
| FCB_STATE_LOCK_BUFFERING_ENABLED \
| FCB_STATE_FILESIZECACHEING_ENABLED \
| FCB_STATE_FILETIMECACHEING_ENABLED))
#endif
#endif

View File

@ -132,7 +132,9 @@ typedef struct _MRX_FCB_
#define SRVOPEN_FLAG_CLOSE_DELAYED 0x8
#define SRVOPEN_FLAG_FILE_RENAMED 0x10
#define SRVOPEN_FLAG_FILE_DELETED 0x20
#define SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING 0x40
#define SRVOPEN_FLAG_COLLAPSING_DISABLED 0x80
#define SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_REQUESTS_PURGED 0x100
#define SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE 0x200
#define SRVOPEN_FLAG_ORPHANED 0x400

View File

@ -42,6 +42,7 @@ typedef enum _RX_FILE_TYPE
#define RDBSS_NTC_STORAGE_TYPE_DIRECTORY ((NODE_TYPE_CODE)0xec02)
#define RDBSS_NTC_STORAGE_TYPE_FILE ((NODE_TYPE_CODE)0xec03)
#define RDBSS_NTC_OPENTARGETDIR_FCB ((NODE_TYPE_CODE)0xecff)
#define RDBSS_NTC_IPC_SHARE ((NODE_TYPE_CODE)0xecfe)
#define RDBSS_NTC_MAILSLOT ((NODE_TYPE_CODE)0xecfd)
#define RDBSS_NTC_SPOOLFILE ((NODE_TYPE_CODE)0xecfc)
#define RDBSS_NTC_SRVCALL ((NODE_TYPE_CODE)0xeb10)

View File

@ -428,6 +428,18 @@ RxRemoveFirstContextFromSerializationQueue(
InitializeListHead((Source)); \
}
#define RxTransferListWithMutex(Destination, Source, Mutex) \
{ \
ExAcquireFastMutex(Mutex); \
RxTransferList(Destination, Source); \
ExReleaseFastMutex(Mutex); \
}
VOID
RxCancelNotifyChangeDirectoryRequestsForFobx(
PFOBX Fobx
);
VOID
NTAPI
RxInitializeContext(
@ -472,4 +484,8 @@ RxResumeBlockedOperations_Serially(
_Inout_ PRX_CONTEXT RxContext,
_Inout_ PLIST_ENTRY BlockingIoQ);
VOID
RxResumeBlockedOperations_ALL(
_Inout_ PRX_CONTEXT RxContext);
#endif

View File

@ -469,6 +469,10 @@ VOID
RxUpdateShareAccessPerSrvOpens(
_In_ PSRV_OPEN SrvOpen);
VOID
RxRemoveShareAccessPerSrvOpens(
_Inout_ PSRV_OPEN SrvOpen);
#if DBG
NTSTATUS
RxCheckShareAccess(
@ -528,10 +532,33 @@ ULONG
RxGetNetworkProviderPriority(
_In_ PUNICODE_STRING DeviceName);
VOID
RxPrepareRequestForReuse(
PCHANGE_BUFFERING_STATE_REQUEST Request);
VOID
RxpDiscardChangeBufferingStateRequests(
_Inout_ PLIST_ENTRY DiscardedRequests);
VOID
RxGatherRequestsForSrvOpen(
_Inout_ PSRV_CALL SrvCall,
_In_ PSRV_OPEN SrvOpen,
_Inout_ PLIST_ENTRY RequestsListHead);
NTSTATUS
RxpLookupSrvOpenForRequestLite(
_In_ PSRV_CALL SrvCall,
_Inout_ PCHANGE_BUFFERING_STATE_REQUEST Request);
VOID
RxProcessChangeBufferingStateRequestsForSrvOpen(
PSRV_OPEN SrvOpen);
NTSTATUS
RxPurgeFobxFromCache(
PFOBX FobxToBePurged);
VOID
RxUndoScavengerFinalizationMarking(
PVOID Instance);

View File

@ -8,6 +8,15 @@ typedef struct _RX_WORK_ITEM_
ULONG Options;
} RX_WORK_ITEM, *PRX_WORK_ITEM;
NTSTATUS
NTAPI
RxPostOneShotTimerRequest(
_In_ PRDBSS_DEVICE_OBJECT pDeviceObject,
_In_ PRX_WORK_ITEM pWorkItem,
_In_ PRX_WORKERTHREAD_ROUTINE Routine,
_In_ PVOID pContext,
_In_ LARGE_INTEGER TimeInterval);
NTSTATUS
NTAPI
RxInitializeRxTimer(

View File

@ -116,6 +116,10 @@ BOOLEAN
RxScavengeRelatedFobxs(
_In_ PFCB Fcb);
VOID
RxpMarkInstanceForScavengedFinalization(
PVOID Instance);
VOID
RxpUndoScavengerFinalizationMarking(
_In_ PVOID Instance);

View File

@ -0,0 +1,7 @@
add_definitions(-DUNICODE -D_UNICODE)
list(APPEND SOURCE
copysup.c)
add_library(copysup ${SOURCE})
add_dependencies(copysup bugcodes xdk)

View File

@ -0,0 +1,182 @@
/*
* ReactOS kernel
* Copyright (C) 2017 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: sdk/lib/drivers/copysup/copysup.c
* PURPOSE: CopySup library
* PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
*/
/* INCLUDES *****************************************************************/
#include "copysup.h"
#include <pseh/pseh2.h>
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
BOOLEAN
FsRtlCopyRead2(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject,
IN PVOID TopLevelContext)
{
BOOLEAN Ret;
ULONG PageCount;
LARGE_INTEGER FinalOffset;
PFSRTL_COMMON_FCB_HEADER Fcb;
PFAST_IO_DISPATCH FastIoDispatch;
PDEVICE_OBJECT RelatedDeviceObject;
PAGED_CODE();
Ret = TRUE;
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset, Length);
/* Null-length read is always OK */
if (Length == 0)
{
IoStatus->Information = 0;
IoStatus->Status = STATUS_SUCCESS;
return TRUE;
}
/* Check we don't overflow */
FinalOffset.QuadPart = FileOffset->QuadPart + Length;
if (FinalOffset.QuadPart <= 0)
{
return FALSE;
}
/* Get the FCB (at least, its header) */
Fcb = FileObject->FsContext;
FsRtlEnterFileSystem();
/* Acquire its resource (shared) */
if (Wait)
{
ExAcquireResourceSharedLite(Fcb->Resource, TRUE);
}
else
{
if (!ExAcquireResourceSharedLite(Fcb->Resource, FALSE))
{
Ret = FALSE;
goto CriticalSection;
}
}
/* If cache wasn't initialized, or FastIO isn't possible, fail */
if (FileObject->PrivateCacheMap == NULL || Fcb->IsFastIoPossible == FastIoIsNotPossible)
{
Ret = FALSE;
goto Resource;
}
/* If FastIO is questionable, then, question! */
if (Fcb->IsFastIoPossible == FastIoIsQuestionable)
{
RelatedDeviceObject = IoGetRelatedDeviceObject(FileObject);
FastIoDispatch = RelatedDeviceObject->DriverObject->FastIoDispatch;
ASSERT(FastIoDispatch != NULL);
ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
/* If it's not possible, then fail */
if (!FastIoDispatch->FastIoCheckIfPossible(FileObject, FileOffset, Length,
Wait, LockKey, TRUE, IoStatus, RelatedDeviceObject))
{
Ret = FALSE;
goto Resource;
}
}
/* If we get beyond file end... */
if (FinalOffset.QuadPart > Fcb->FileSize.QuadPart)
{
/* Fail if the offset was already beyond file end */
if (FileOffset->QuadPart >= Fcb->FileSize.QuadPart)
{
IoStatus->Information = 0;
IoStatus->Status = STATUS_END_OF_FILE;
goto Resource;
}
/* Otherwise, just fix read length */
Length = (ULONG)(Fcb->FileSize.QuadPart - FileOffset->QuadPart);
}
/* Set caller provided context as TLI */
IoSetTopLevelIrp(TopLevelContext);
_SEH2_TRY
{
/* If we cannot wait, or if file is bigger than 4GB */
if (!Wait || (FinalOffset.HighPart | Fcb->FileSize.HighPart) != 0)
{
/* Forward to Cc */
Ret = CcCopyRead(FileObject, FileOffset, Length, Wait, Buffer, IoStatus);
SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ);
/* Validate output */
ASSERT(!Ret || (IoStatus->Status == STATUS_END_OF_FILE) || (((ULONGLONG)FileOffset->QuadPart + IoStatus->Information) <= (ULONGLONG)Fcb->FileSize.QuadPart));
}
else
{
/* Forward to Cc */
CcFastCopyRead(FileObject, FileOffset->LowPart, Length, PageCount, Buffer, IoStatus);
SetFlag(FileObject->Flags, FO_FILE_FAST_IO_READ);
/* Validate output */
ASSERT((IoStatus->Status == STATUS_END_OF_FILE) || ((FileOffset->LowPart + IoStatus->Information) <= Fcb->FileSize.LowPart));
}
/* If read was successful, update the byte offset in the FO */
if (Ret)
{
FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart + IoStatus->Information;
}
}
_SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
Ret = FALSE;
}
_SEH2_END;
/* Reset TLI */
IoSetTopLevelIrp(NULL);
Resource:
ExReleaseResourceLite(Fcb->Resource);
CriticalSection:
FsRtlExitFileSystem();
return Ret;
}

View File

@ -0,0 +1,18 @@
#ifndef _COPYSUP_H_
#define _COPYSUP_H_
#include <ntifs.h>
BOOLEAN
FsRtlCopyRead2(
_In_ PFILE_OBJECT FileObject,
_In_ PLARGE_INTEGER FileOffset,
_In_ ULONG Length,
_In_ BOOLEAN Wait,
_In_ ULONG LockKey,
_Out_ PVOID Buffer,
_Out_ PIO_STATUS_BLOCK IoStatus,
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PVOID TopLevelContext);
#endif

View File

@ -30,6 +30,7 @@
#include <pseh/pseh2.h>
#include <limits.h>
#include <dfs.h>
#include <copysup.h>
#define NDEBUG
#include <debug.h>
@ -357,6 +358,11 @@ RxpQueryInfoMiniRdr(
FILE_INFORMATION_CLASS FileInfoClass,
PVOID Buffer);
VOID
RxPurgeNetFcb(
PFCB Fcb,
PRX_CONTEXT LocalContext);
NTSTATUS
RxQueryAlternateNameInfo(
PRX_CONTEXT RxContext,
@ -779,6 +785,13 @@ RxAllocateCanonicalNameBuffer(
return STATUS_SUCCESS;
}
VOID
RxCancelNotifyChangeDirectoryRequestsForFobx(
PFOBX Fobx)
{
UNIMPLEMENTED;
}
VOID
NTAPI
RxCancelRoutine(
@ -971,17 +984,6 @@ RxCanonicalizeNameAndObtainNetRoot(
return Status;
}
NTSTATUS
NTAPI
RxChangeBufferingState(
PSRV_OPEN SrvOpen,
PVOID Context,
BOOLEAN ComputeNewState)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
VOID
NTAPI
RxCheckFcbStructuresForAlignment(
@ -1058,13 +1060,202 @@ RxCheckShareAccessPerSrvOpens(
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
RxCloseAssociatedSrvOpen(
IN PFOBX Fobx,
IN PRX_CONTEXT RxContext OPTIONAL)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
PFCB Fcb;
NTSTATUS Status;
PSRV_OPEN SrvOpen;
BOOLEAN CloseSrvOpen;
PRX_CONTEXT LocalContext;
PAGED_CODE();
/* Assume SRV_OPEN is already closed */
CloseSrvOpen = FALSE;
/* If we have a FOBX, we'll have to close it */
if (Fobx != NULL)
{
/* If the FOBX isn't closed yet */
if (!BooleanFlagOn(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED))
{
SrvOpen = Fobx->SrvOpen;
Fcb = (PFCB)SrvOpen->pFcb;
/* Check whether we've to close SRV_OPEN first */
if (!BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
{
CloseSrvOpen = TRUE;
}
else
{
ASSERT(RxIsFcbAcquiredExclusive(Fcb));
/* Not much to do */
SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
if (SrvOpen->OpenCount > 0)
{
--SrvOpen->OpenCount;
}
}
}
/* No need to close SRV_OPEN, so close FOBX */
if (!CloseSrvOpen)
{
RxMarkFobxOnClose(Fobx);
return STATUS_SUCCESS;
}
}
else
{
/* No FOBX? No RX_CONTEXT, ok, job done! */
if (RxContext == NULL)
{
return STATUS_SUCCESS;
}
/* Get the FCB from RX_CONTEXT */
Fcb = (PFCB)RxContext->pFcb;
SrvOpen == NULL;
}
/* If we don't have RX_CONTEXT, allocte one, we'll need it */
if (RxContext == NULL)
{
ASSERT(Fobx != NULL);
LocalContext = RxCreateRxContext(NULL, Fcb->RxDeviceObject, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING | RX_CONTEXT_FLAG_WAIT);
if (LocalContext == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
LocalContext->MajorFunction = 2;
LocalContext->pFcb = RX_GET_MRX_FCB(Fcb);
LocalContext->pFobx = (PMRX_FOBX)Fobx;
LocalContext->pRelevantSrvOpen = (PMRX_SRV_OPEN)Fobx->SrvOpen;
}
else
{
LocalContext = RxContext;
}
ASSERT(RxIsFcbAcquiredExclusive(Fcb));
/* Now, close the FOBX */
if (Fobx != NULL)
{
RxMarkFobxOnClose(Fobx);
}
else
{
InterlockedDecrement((volatile long *)&Fcb->OpenCount);
}
/* If not a "standard" file, SRV_OPEN can be null */
if (SrvOpen == NULL)
{
ASSERT((NodeType(Fcb) == RDBSS_NTC_OPENTARGETDIR_FCB) || (NodeType(Fcb) == RDBSS_NTC_IPC_SHARE) || (NodeType(Fcb) == RDBSS_NTC_MAILSLOT));
RxDereferenceNetFcb(Fcb);
if (LocalContext != RxContext)
{
RxDereferenceAndDeleteRxContext(LocalContext);
}
return STATUS_SUCCESS;
}
/* If SRV_OPEN isn't in a good condition, nothing to close */
if (SrvOpen->Condition != Condition_Good)
{
if (LocalContext != RxContext)
{
RxDereferenceAndDeleteRxContext(LocalContext);
}
return STATUS_SUCCESS;
}
/* Decrease open count */
if (SrvOpen->OpenCount > 0)
{
--SrvOpen->OpenCount;
}
/* If we're the only one left, is there a FOBX handled by Scavenger? */
if (SrvOpen->OpenCount == 1)
{
if (!IsListEmpty(&SrvOpen->FobxList))
{
if (!IsListEmpty(&CONTAINING_RECORD(SrvOpen->FobxList.Flink, FOBX, FobxQLinks)->ScavengerFinalizationList))
{
SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED);
}
}
}
/* Nothing left, purge FCB */
if (SrvOpen->OpenCount == 0 && RxContext == NULL)
{
RxPurgeNetFcb(Fcb, LocalContext);
}
/* Already closed? Job done! */
SrvOpen = Fobx->SrvOpen;
if (SrvOpen == NULL ||
(SrvOpen->OpenCount != 0 && !BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING)) ||
BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
{
SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
if (LocalContext != RxContext)
{
RxDereferenceAndDeleteRxContext(LocalContext);
}
return STATUS_SUCCESS;
}
ASSERT(RxIsFcbAcquiredExclusive(Fcb));
/* Inform mini-rdr about closing */
MINIRDR_CALL(Status, LocalContext, Fcb->MRxDispatch, MRxCloseSrvOpen, (LocalContext));
DPRINT("MRxCloseSrvOpen returned: %lx, called with RX_CONTEXT %p for FOBX %p (FCB %p, SRV_OPEN %p)\n ",
Status, RxContext, Fobx, Fcb, SrvOpen);
/* And mark as such */
SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_CLOSED);
SrvOpen->Key = (PVOID)-1;
/* If we were delayed, we're not! */
if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED))
{
InterlockedDecrement(&((PSRV_CALL)Fcb->pNetRoot->pSrvCall)->NumberOfCloseDelayedFiles);
}
/* Clear access */
RxRemoveShareAccessPerSrvOpens(SrvOpen);
RxPurgeChangeBufferingStateRequestsForSrvOpen(SrvOpen);
/* Dereference */
RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
/* Mark the FOBX closed as well */
SetFlag(Fobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED);
if (LocalContext != RxContext)
{
RxDereferenceAndDeleteRxContext(LocalContext);
}
return Status;
}
/*
@ -1258,9 +1449,12 @@ RxCommonCleanup(
#define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
PFCB Fcb;
PFOBX Fobx;
ULONG OpenCount;
NTSTATUS Status;
BOOLEAN NeedPurge;
PNET_ROOT NetRoot;
PFILE_OBJECT FileObject;
PLARGE_INTEGER TruncateSize;
BOOLEAN NeedPurge, FcbTableAcquired, OneLeft, IsFile, FcbAcquired;
PAGED_CODE();
@ -1300,6 +1494,8 @@ RxCommonCleanup(
return Status;
}
FcbAcquired = TRUE;
Fobx->AssociatedFileObject = NULL;
/* In case SRV_OPEN used is part of FCB */
@ -1326,8 +1522,186 @@ RxCommonCleanup(
return STATUS_SUCCESS;
}
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
/* Report the fact that file could be set as delete on close */
if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
{
SetFlag(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE);
}
/* Cancel any pending notification */
RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx);
/* Backup open count before we start playing with it */
OpenCount = Fcb->ShareAccess.OpenCount;
NetRoot = (PNET_ROOT)Fcb->pNetRoot;
FcbTableAcquired = FALSE;
OneLeft = FALSE;
_SEH2_TRY
{
/* Unclean count and delete on close? Verify whether we're the one */
if (Fcb->UncleanCount == 1 && BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
{
if (RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
{
FcbTableAcquired = TRUE;
}
else
{
RxReleaseFcb(Context, Fcb);
RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
Status = RxAcquireExclusiveFcb(Context, Fcb);
if (Status != STATUS_SUCCESS)
{
RxReleaseFcbTableLock(&NetRoot->FcbTable);
return Status;
}
FcbTableAcquired = TRUE;
}
if (Fcb->UncleanCount == 1)
{
OneLeft = TRUE;
}
else
{
RxReleaseFcbTableLock(&NetRoot->FcbTable);
FcbTableAcquired = FALSE;
}
}
IsFile = FALSE;
TruncateSize = NULL;
/* Handle cleanup for pipes and printers */
if (NetRoot->Type == NET_ROOT_PIPE || NetRoot->Type == NET_ROOT_PRINT)
{
UNIMPLEMENTED;
}
/* Handle cleanup for files */
else if (NetRoot->Type == NET_ROOT_DISK || NetRoot->Type == NET_ROOT_WILD)
{
if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
{
UNIMPLEMENTED;
IsFile = TRUE;
}
}
/* We have to still be there! */
ASSERT(Fcb->UncleanCount != 0);
InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
{
--Fcb->UncachedUncleanCount;
}
/* Inform mini-rdr about ongoing cleanup */
MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
--Fobx->SrvOpen->UncleanFobxCount;
/* Flush cache */
if (DisableFlushOnCleanup)
{
/* Only if we're the last standing */
if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL &&
Fcb->UncleanCount == Fcb->UncachedUncleanCount)
{
DPRINT1("Flushing %p due to last cached handle cleanup\n", Context);
RxFlushFcbInSystemCache(Fcb, TRUE);
}
}
else
{
/* Always */
if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
{
DPRINT1("Flushing %p on cleanup\n", Context);
RxFlushFcbInSystemCache(Fcb, TRUE);
}
}
/* If only remaining uncached & unclean, then flush and purge */
if (!BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
{
if (Fcb->UncachedUncleanCount != 0)
{
if (Fcb->UncachedUncleanCount == Fcb->UncleanCount &&
Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
{
DPRINT1("Flushing FCB in system cache for %p\n", Context);
RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
}
}
}
/* If purge required, flush */
if (!OneLeft && NeedPurge)
{
DPRINT1("Flushing FCB in system cache for %p\n", Context);
RxFlushFcbInSystemCache(Fcb, TRUE);
}
/* If it was a file, drop cache */
if (IsFile)
{
DPRINT1("Uninit cache map for file\n");
RxUninitializeCacheMap(Context, FileObject, TruncateSize);
}
/* If that's the one left, or if it needs purge, flush */
if (OneLeft || NeedPurge)
{
RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, !OneLeft);
/* Also remove from FCB table */
if (OneLeft)
{
RxRemoveNameNetFcb(Fcb);
RxReleaseFcbTableLock(&NetRoot->FcbTable);
FcbTableAcquired = FALSE;
}
}
/* Remove any share access */
if (OpenCount != 0 && NetRoot->Type == NET_ROOT_DISK)
{
RxRemoveShareAccess(FileObject, &Fcb->ShareAccess, "Cleanup the share access", "ClnUpShr");
}
/* In case there's caching, on a file, update file metadata */
if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE && BooleanFlagOn(Fobx->Flags, 0x20000000) &&
BooleanFlagOn(Fcb->FcbState, FCB_STATE_WRITECACHING_ENABLED) && !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING))
{
UNIMPLEMENTED;
}
/* We're clean! */
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
FcbAcquired = FALSE;
RxReleaseFcb(Context, Fcb);
}
_SEH2_FINALLY
{
if (FcbAcquired)
{
RxReleaseFcb(Context, Fcb);
}
if (FcbTableAcquired)
{
RxReleaseFcbTableLock(&NetRoot->FcbTable);
}
}
_SEH2_END;
return Status;
#undef BugCheckFileId
}
@ -3234,6 +3608,96 @@ RxFastIoCheckIfPossible(
PIO_STATUS_BLOCK IoStatus,
PDEVICE_OBJECT DeviceObject)
{
PFCB Fcb;
PSRV_OPEN SrvOpen;
PAGED_CODE();
/* Get the FCB to validate it */
Fcb = FileObject->FsContext;
if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE)
{
DPRINT1("Not a file, FastIO not possible!\n");
return FALSE;
}
if (FileObject->DeletePending)
{
DPRINT1("File delete pending\n");
return FALSE;
}
/* If there's a pending write operation, deny fast operation */
if (Fcb->NonPaged->OutstandingAsyncWrites != 0)
{
DPRINT1("Write operations to be completed\n");
return FALSE;
}
/* Deny read on orphaned node */
SrvOpen = (PSRV_OPEN)((PFOBX)FileObject->FsContext2)->pSrvOpen;
if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_ORPHANED))
{
DPRINT1("SRV_OPEN orphaned\n");
return FALSE;
}
if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_ORPHANED))
{
DPRINT1("FCB orphaned\n");
return FALSE;
}
/* If there's a buffering state change pending, deny fast operation (it might change
* cache status)
*/
if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING))
{
DPRINT1("Buffering change pending\n");
return FALSE;
}
/* File got renamed/deleted, deny operation */
if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_FILE_DELETED) ||
BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED))
{
DPRINT1("File renamed/deleted\n");
return FALSE;
}
/* Process pending change buffering state operations */
FsRtlEnterFileSystem();
RxProcessChangeBufferingStateRequestsForSrvOpen(SrvOpen);
FsRtlExitFileSystem();
/* If operation to come is a read operation */
if (CheckForReadOperation)
{
LARGE_INTEGER LargeLength;
/* Check that read cache is enabled */
if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_READCACHING_ENABLED))
{
DPRINT1("Read caching disabled\n");
return FALSE;
}
/* Check whether there's a lock conflict */
LargeLength.QuadPart = Length;
if (!FsRtlFastCheckLockForRead(&Fcb->Specific.Fcb.FileLock,
FileOffset,
&LargeLength,
LockKey,
FileObject,
PsGetCurrentProcess()))
{
DPRINT1("FsRtlFastCheckLockForRead failed\n");
return FALSE;
}
return TRUE;
}
UNIMPLEMENTED;
return FALSE;
}
@ -3263,6 +3727,9 @@ RxFastIoDeviceControl(
}
}
/*
* @implemented
*/
BOOLEAN
NTAPI
RxFastIoRead(
@ -3275,8 +3742,32 @@ RxFastIoRead(
PIO_STATUS_BLOCK IoStatus,
PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED;
return FALSE;
BOOLEAN Ret;
RX_TOPLEVELIRP_CONTEXT TopLevelContext;
PAGED_CODE();
DPRINT("RxFastIoRead: %p (%p, %p)\n", FileObject, FileObject->FsContext,
FileObject->FsContext2);
DPRINT("Reading %ld at %I64x\n", Length, FileOffset->QuadPart);
/* Prepare a TLI context */
ASSERT(RxIsThisTheTopLevelIrp(NULL));
RxInitializeTopLevelIrpContext(&TopLevelContext, (PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP,
(PRDBSS_DEVICE_OBJECT)DeviceObject);
Ret = FsRtlCopyRead2(FileObject, FileOffset, Length, Wait, LockKey, Buffer,
IoStatus, DeviceObject, &TopLevelContext);
if (Ret)
{
DPRINT("Read OK\n");
}
else
{
DPRINT1("Read failed!\n");
}
return Ret;
}
BOOLEAN
@ -4399,15 +4890,6 @@ RxInitializeRegistrationStructures(
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
RxInitializeRxTimer(
VOID)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @implemented
*/
@ -5022,6 +5504,28 @@ RxpUnregisterMinirdr(
UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID
RxPurgeNetFcb(
PFCB Fcb,
PRX_CONTEXT LocalContext)
{
NTSTATUS Status;
PAGED_CODE();
/* First, flush */
MmFlushImageSection(&Fcb->NonPaged->SectionObjectPointers, MmFlushForWrite);
/* And force close */
RxReleaseFcb(NULL, Fcb);
MmForceSectionClosed(&Fcb->NonPaged->SectionObjectPointers, TRUE);
Status = RxAcquireExclusiveFcb(NULL, Fcb);
ASSERT(Status == STATUS_SUCCESS);
}
NTSTATUS
RxQueryAlternateNameInfo(
PRX_CONTEXT RxContext,
@ -5610,6 +6114,9 @@ RxRemoveOverflowEntry(
return Context;
}
/*
* @implemented
*/
VOID
RxRemoveShareAccess(
_Inout_ PFILE_OBJECT FileObject,
@ -5617,7 +6124,58 @@ RxRemoveShareAccess(
_In_ PSZ where,
_In_ PSZ wherelogtag)
{
UNIMPLEMENTED;
PAGED_CODE();
RxDumpCurrentAccess(where, "before", wherelogtag, ShareAccess);
IoRemoveShareAccess(FileObject, ShareAccess);
RxDumpCurrentAccess(where, "after", wherelogtag, ShareAccess);
}
/*
* @implemented
*/
VOID
RxRemoveShareAccessPerSrvOpens(
IN OUT PSRV_OPEN SrvOpen)
{
ACCESS_MASK DesiredAccess;
BOOLEAN ReadAccess;
BOOLEAN WriteAccess;
BOOLEAN DeleteAccess;
PAGED_CODE();
/* Get access that were granted to SRV_OPEN */
DesiredAccess = SrvOpen->DesiredAccess;
ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
DeleteAccess = (DesiredAccess & DELETE) != 0;
/* If any, drop them */
if ((ReadAccess) || (WriteAccess) || (DeleteAccess))
{
BOOLEAN SharedRead;
BOOLEAN SharedWrite;
BOOLEAN SharedDelete;
ULONG DesiredShareAccess;
PSHARE_ACCESS ShareAccess;
ShareAccess = &((PFCB)SrvOpen->pFcb)->ShareAccessPerSrvOpens;
DesiredShareAccess = SrvOpen->ShareAccess;
ShareAccess->Readers -= ReadAccess;
ShareAccess->Writers -= WriteAccess;
ShareAccess->Deleters -= DeleteAccess;
ShareAccess->OpenCount--;
SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
ShareAccess->SharedRead -= SharedRead;
ShareAccess->SharedWrite -= SharedWrite;
ShareAccess->SharedDelete -= SharedDelete;
}
}
NTSTATUS

File diff suppressed because it is too large Load Diff