mirror of
https://github.com/reactos/reactos.git
synced 2024-11-09 08:08:38 +00:00
401 lines
8.7 KiB
C
401 lines
8.7 KiB
C
/*++
|
|
|
|
Copyright (c) 1989-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ResrcSup.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the Cdfs Resource acquisition routines
|
|
|
|
|
|
--*/
|
|
|
|
#include "cdprocs.h"
|
|
|
|
//
|
|
// The Bug check file id for this module
|
|
//
|
|
|
|
#define BugCheckFileId (CDFS_BUG_CHECK_RESRCSUP)
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, CdAcquireForCache)
|
|
#pragma alloc_text(PAGE, CdFilterCallbackAcquireForCreateSection)
|
|
#pragma alloc_text(PAGE, CdAcquireResource)
|
|
#pragma alloc_text(PAGE, CdNoopAcquire)
|
|
#pragma alloc_text(PAGE, CdNoopRelease)
|
|
#pragma alloc_text(PAGE, CdReleaseForCreateSection)
|
|
#pragma alloc_text(PAGE, CdReleaseFromCache)
|
|
#endif
|
|
|
|
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
_When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource))
|
|
_When_(Type == AcquireShared && return != FALSE, _Acquires_shared_lock_(*Resource))
|
|
_When_(Type == AcquireSharedStarveExclusive && return != FALSE, _Acquires_shared_lock_(*Resource))
|
|
_When_(IgnoreWait == FALSE, _Post_satisfies_(return == TRUE))
|
|
BOOLEAN
|
|
CdAcquireResource (
|
|
_In_ PIRP_CONTEXT IrpContext,
|
|
_Inout_ PERESOURCE Resource,
|
|
_In_ BOOLEAN IgnoreWait,
|
|
_In_ TYPE_OF_ACQUIRE Type
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the single routine used to acquire file system resources. It
|
|
looks at the IgnoreWait flag to determine whether to try to acquire the
|
|
resource without waiting. Returning TRUE/FALSE to indicate success or
|
|
failure. Otherwise it is driven by the WAIT flag in the IrpContext and
|
|
will raise CANT_WAIT on a failure.
|
|
|
|
Arguments:
|
|
|
|
Resource - This is the resource to try and acquire.
|
|
|
|
IgnoreWait - If TRUE then this routine will not wait to acquire the
|
|
resource and will return a boolean indicating whether the resource was
|
|
acquired. Otherwise we use the flag in the IrpContext and raise
|
|
if the resource is not acquired.
|
|
|
|
Type - Indicates how we should try to get the resource.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if the resource is acquired. FALSE if not acquired and
|
|
IgnoreWait is specified. Otherwise we raise CANT_WAIT.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN Wait = FALSE;
|
|
BOOLEAN Acquired;
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// We look first at the IgnoreWait flag, next at the flag in the Irp
|
|
// Context to decide how to acquire this resource.
|
|
//
|
|
|
|
if (!IgnoreWait && FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
|
|
|
|
Wait = TRUE;
|
|
}
|
|
|
|
//
|
|
// Attempt to acquire the resource either shared or exclusively.
|
|
//
|
|
|
|
switch (Type) {
|
|
case AcquireExclusive:
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma prefast( suppress:28137, "prefast believes Wait should be a constant, but this is ok for CDFS" )
|
|
#endif
|
|
Acquired = ExAcquireResourceExclusiveLite( Resource, Wait );
|
|
break;
|
|
|
|
case AcquireShared:
|
|
|
|
Acquired = ExAcquireResourceSharedLite( Resource, Wait );
|
|
break;
|
|
|
|
case AcquireSharedStarveExclusive:
|
|
|
|
Acquired = ExAcquireSharedStarveExclusive( Resource, Wait );
|
|
break;
|
|
|
|
default:
|
|
Acquired = FALSE;
|
|
NT_ASSERT( FALSE );
|
|
}
|
|
|
|
//
|
|
// If not acquired and the user didn't specifiy IgnoreWait then
|
|
// raise CANT_WAIT.
|
|
//
|
|
|
|
if (!Acquired && !IgnoreWait) {
|
|
|
|
CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
|
|
}
|
|
|
|
return Acquired;
|
|
}
|
|
|
|
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
_When_(return!=0, _Acquires_shared_lock_(*Fcb->Resource))
|
|
BOOLEAN
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdAcquireForCache (
|
|
_Inout_ PFCB Fcb,
|
|
_In_ BOOLEAN Wait
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The address of this routine is specified when creating a CacheMap for
|
|
a file. It is subsequently called by the Lazy Writer for synchronization.
|
|
|
|
Arguments:
|
|
|
|
Fcb - The pointer supplied as context to the cache initialization
|
|
routine.
|
|
|
|
Wait - TRUE if the caller is willing to block.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
NT_ASSERT(IoGetTopLevelIrp() == NULL);
|
|
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
_Releases_lock_(*Fcb->Resource)
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdReleaseFromCache (
|
|
_Inout_ PFCB Fcb
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The address of this routine is specified when creating a CacheMap for
|
|
a virtual file. It is subsequently called by the Lazy Writer to release
|
|
a resource acquired above.
|
|
|
|
Arguments:
|
|
|
|
Fcb - The pointer supplied as context to the cache initialization
|
|
routine.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NT_ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
|
IoSetTopLevelIrp( NULL );
|
|
|
|
ExReleaseResourceLite( Fcb->Resource );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdNoopAcquire (
|
|
_In_ PVOID Fcb,
|
|
_In_ BOOLEAN Wait
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does nothing.
|
|
|
|
Arguments:
|
|
|
|
Fcb - The Fcb/Vcb which was specified as a context parameter for this
|
|
routine.
|
|
|
|
Wait - TRUE if the caller is willing to block.
|
|
|
|
Return Value:
|
|
|
|
TRUE
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
UNREFERENCED_PARAMETER( Fcb );
|
|
UNREFERENCED_PARAMETER( Wait );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdNoopRelease (
|
|
_In_ PVOID Fcb
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does nothing.
|
|
|
|
Arguments:
|
|
|
|
Fcb - The Fcb/Vcb which was specified as a context parameter for this
|
|
routine.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
UNREFERENCED_PARAMETER( Fcb );
|
|
}
|
|
|
|
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
NTSTATUS
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdFilterCallbackAcquireForCreateSection (
|
|
_In_ PFS_FILTER_CALLBACK_DATA CallbackData,
|
|
_Unreferenced_parameter_ PVOID *CompletionContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the callback routine for MM to use to acquire the file exclusively.
|
|
|
|
Arguments:
|
|
|
|
FS_FILTER_CALLBACK_DATA - Filter based callback data that provides the file object we
|
|
want to acquire.
|
|
|
|
CompletionContext - Ignored.
|
|
|
|
Return Value:
|
|
|
|
On success we return STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY.
|
|
|
|
If SyncType is SyncTypeCreateSection, we return a status that indicates there are no
|
|
writers to this file.
|
|
|
|
--*/
|
|
|
|
{
|
|
PFILE_OBJECT FileObject;
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
NT_ASSERT( CallbackData->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION );
|
|
NT_ASSERT( CallbackData->SizeOfFsFilterCallbackData == sizeof(FS_FILTER_CALLBACK_DATA) );
|
|
|
|
//
|
|
// Get the file object from the callback data.
|
|
//
|
|
|
|
FileObject = CallbackData->FileObject;
|
|
|
|
//
|
|
// Get the Fcb resource exclusively.
|
|
//
|
|
|
|
ExAcquireResourceExclusiveLite( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource,
|
|
TRUE );
|
|
|
|
//
|
|
// Take the File resource shared. We need this later on when MM calls
|
|
// QueryStandardInfo to get the file size.
|
|
//
|
|
// If we don't use StarveExclusive, then we can get wedged behind an
|
|
// exclusive waiter who is waiting on someone else holding it shared in the
|
|
// read->initializecachemap path (which calls createsection) who is in turn
|
|
// waiting on us to finish the create section.
|
|
//
|
|
|
|
ExAcquireSharedStarveExclusive( ((PFCB) FileObject->FsContext)->Resource,
|
|
TRUE );
|
|
|
|
//
|
|
// CDFS is a read-only file system, so we can always indicate no writers.
|
|
// We only do this for create section synchronization. For others we
|
|
// return the generic success STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY.
|
|
//
|
|
|
|
if (CallbackData->Parameters.AcquireForSectionSynchronization.SyncType == SyncTypeCreateSection) {
|
|
|
|
return STATUS_FILE_LOCKED_WITH_ONLY_READERS;
|
|
|
|
} else {
|
|
|
|
return STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
|
|
}
|
|
|
|
UNREFERENCED_PARAMETER( CompletionContext );
|
|
}
|
|
|
|
|
|
_Function_class_(FAST_IO_RELEASE_FILE)
|
|
_Requires_lock_held_(_Global_critical_region_)
|
|
VOID
|
|
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
|
|
CdReleaseForCreateSection (
|
|
_In_ PFILE_OBJECT FileObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the callback routine for MM to use to release a file acquired with
|
|
the AcquireForCreateSection call above.
|
|
|
|
Arguments:
|
|
|
|
FileObject - File object for a Cdfs stream.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Release the resources.
|
|
//
|
|
|
|
ExReleaseResourceLite( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource );
|
|
ExReleaseResourceLite( ((PFCB) FileObject->FsContext)->Resource);
|
|
}
|
|
|