mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-24 09:23:37 -05:00
sys: IRP_MJ_CREATE: refactoring to support Overwrite
This commit is contained in:
parent
9b93df1788
commit
16895a5b68
@ -46,6 +46,7 @@ enum
|
|||||||
{
|
{
|
||||||
FspFsctlTransactUnknownKind = 0,
|
FspFsctlTransactUnknownKind = 0,
|
||||||
FspFsctlTransactCreateKind,
|
FspFsctlTransactCreateKind,
|
||||||
|
FspFsctlTransactCreate2Kind,
|
||||||
FspFsctlTransactCleanupKind,
|
FspFsctlTransactCleanupKind,
|
||||||
FspFsctlTransactCloseKind,
|
FspFsctlTransactCloseKind,
|
||||||
FspFsctlTransactReadKind,
|
FspFsctlTransactReadKind,
|
||||||
@ -120,6 +121,14 @@ typedef struct
|
|||||||
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
UINT32 CaseSensitive:1; /* FileName comparisons should be case-sensitive */
|
||||||
} Create;
|
} Create;
|
||||||
struct
|
struct
|
||||||
|
{
|
||||||
|
UINT64 UserContext;
|
||||||
|
UINT64 UserContext2;
|
||||||
|
UINT32 CloseStatus; /* if non-0 close the file (and do NOT overwrite!) */
|
||||||
|
UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */
|
||||||
|
UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */
|
||||||
|
} Create2;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
UINT64 UserContext;
|
UINT64 UserContext;
|
||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
@ -169,6 +178,13 @@ typedef struct
|
|||||||
FSP_FSCTL_TRANSACT_BUF FileName; /* file name to use for STATUS_REPARSE */
|
FSP_FSCTL_TRANSACT_BUF FileName; /* file name to use for STATUS_REPARSE */
|
||||||
} Reparse;
|
} Reparse;
|
||||||
} Create;
|
} Create;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UINT64 UserContext; /* open file user context (unique file id) */
|
||||||
|
UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */
|
||||||
|
UINT64 AllocationSize; /* file allocation size */
|
||||||
|
UINT64 FileSize; /* file size */
|
||||||
|
} Create2;
|
||||||
} Rsp;
|
} Rsp;
|
||||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
|
||||||
} FSP_FSCTL_TRANSACT_RSP;
|
} FSP_FSCTL_TRANSACT_RSP;
|
||||||
|
@ -60,19 +60,8 @@ static NTSTATUS FspFsvolCleanup(
|
|||||||
UINT64 UserContext = FsContext->UserContext;
|
UINT64 UserContext = FsContext->UserContext;
|
||||||
UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2;
|
UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
LONG OpenCount;
|
|
||||||
|
|
||||||
/* all handles on this FileObject are gone; close the FileObject */
|
FspFileContextClose(FsvolDeviceObject, FsContext);
|
||||||
OpenCount = FspFileContextClose(FsContext);
|
|
||||||
|
|
||||||
/* is the FsContext going away as well? */
|
|
||||||
if (0 == OpenCount)
|
|
||||||
{
|
|
||||||
/* remove the FsContext from the volume device generic table */
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
|
||||||
FspFsvolDeviceDeleteContext(FsvolDeviceObject, FsContext->UserContext, 0);
|
|
||||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */
|
/* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */
|
||||||
FspIopCreateRequestMustSucceed(Irp, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
|
FspIopCreateRequestMustSucceed(Irp, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
|
||||||
|
167
src/sys/create.c
167
src/sys/create.c
@ -292,10 +292,16 @@ NTSTATUS FspFsvolCreatePrepare(
|
|||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
BOOLEAN Success;
|
||||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
PACCESS_STATE AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
|
PACCESS_STATE AccessState;
|
||||||
HANDLE UserModeAccessToken;
|
HANDLE UserModeAccessToken;
|
||||||
PEPROCESS Process;
|
PEPROCESS Process;
|
||||||
|
FSP_FILE_CONTEXT *FsContext;
|
||||||
|
|
||||||
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
|
{
|
||||||
|
AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
|
||||||
|
|
||||||
/* get a user-mode handle to the access token */
|
/* get a user-mode handle to the access token */
|
||||||
Result = ObOpenObjectByPointer(SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext),
|
Result = ObOpenObjectByPointer(SeQuerySubjectContextToken(&AccessState->SubjectSecurityContext),
|
||||||
@ -314,6 +320,45 @@ NTSTATUS FspFsvolCreatePrepare(
|
|||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
else if (FspFsctlTransactCreate2Kind == Request->Kind)
|
||||||
|
{
|
||||||
|
FsContext = FspIopRequestContext(Request, RequestFsContext);
|
||||||
|
|
||||||
|
/* lock the FsContext for Paging IO */
|
||||||
|
Success = FspFileContextPgioLockExclusive(FsContext, FALSE);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
/* repost the IRP to retry later */
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension =
|
||||||
|
FspFsvolDeviceExtension(IrpSp->DeviceObject);
|
||||||
|
if (FspIoqPostIrpNoCap(FsvolDeviceExtension->Ioq, Irp, &Result))
|
||||||
|
Result = STATUS_PENDING;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* see what the MM thinks about all this */
|
||||||
|
LARGE_INTEGER Zero = { 0 };
|
||||||
|
Success = MmCanFileBeTruncated(&FsContext->NonPaged->SectionObjectPointers, &Zero);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
/* cannot truncate; tell user mode that we are closing the file */
|
||||||
|
FspFileContextPgioUnlock(FsContext);
|
||||||
|
Request->Req.Create2.CloseStatus = (UINT32)STATUS_USER_MAPPED_FILE;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* purge any caches on this file */
|
||||||
|
CcPurgeCacheSection(&FsContext->NonPaged->SectionObjectPointers, 0, 0, FALSE);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(0);
|
||||||
|
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspFsvolCreateComplete(
|
VOID FspFsvolCreateComplete(
|
||||||
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
@ -325,14 +370,15 @@ VOID FspFsvolCreateComplete(
|
|||||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
SHARE_ACCESS TemporaryShareAccess;
|
SHARE_ACCESS TemporaryShareAccess;
|
||||||
UNICODE_STRING ReparseFileName;
|
UNICODE_STRING ReparseFileName;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
FSP_FILE_CONTEXT *FsContext;
|
FSP_FILE_CONTEXT *FsContext = FspIopRequestContext(Request, RequestFsContext);
|
||||||
BOOLEAN Inserted;
|
|
||||||
|
|
||||||
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
|
{
|
||||||
/* did the user-mode file system sent us a failure code? */
|
/* did the user-mode file system sent us a failure code? */
|
||||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information;
|
Irp->IoStatus.Information = 0;
|
||||||
Result = Response->IoStatus.Status;
|
Result = Response->IoStatus.Status;
|
||||||
FSP_RETURN();
|
FSP_RETURN();
|
||||||
}
|
}
|
||||||
@ -395,41 +441,19 @@ VOID FspFsvolCreateComplete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get the FsContext from our Request and associate it with the Response UserContext */
|
/* get the FsContext from our Request and associate it with the Response UserContext */
|
||||||
Request = FspIrpRequest(Irp);
|
|
||||||
FsContext = FspIopRequestContext(Request, RequestFsContext);
|
|
||||||
FsContext->Header.AllocationSize.QuadPart = Response->Rsp.Create.Opened.AllocationSize;
|
FsContext->Header.AllocationSize.QuadPart = Response->Rsp.Create.Opened.AllocationSize;
|
||||||
FsContext->Header.FileSize.QuadPart = Response->Rsp.Create.Opened.AllocationSize;
|
FsContext->Header.FileSize.QuadPart = Response->Rsp.Create.Opened.AllocationSize;
|
||||||
FsContext->UserContext = Response->Rsp.Create.Opened.UserContext;
|
FsContext->UserContext = Response->Rsp.Create.Opened.UserContext;
|
||||||
|
|
||||||
/*
|
/* open the FsContext */
|
||||||
* Attempt to insert our FsContext into the volume device's generic table.
|
FspIopRequestContext(Request, RequestFsContext) =
|
||||||
* If an FsContext with the same UserContext already exists, then use that
|
FspFileContextOpen(FsvolDeviceObject, FsContext);
|
||||||
* FsContext instead.
|
|
||||||
*/
|
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
|
||||||
FsContext = FspFsvolDeviceInsertContext(FsvolDeviceObject,
|
|
||||||
FsContext->UserContext, FsContext, &FsContext->ElementStorage, &Inserted);
|
|
||||||
ASSERT(0 != FsContext);
|
|
||||||
if (Inserted)
|
|
||||||
/* Our FsContext was inserted into the volume device's generic table.
|
|
||||||
* Disassociate it from the Request.
|
|
||||||
*/
|
|
||||||
FspIopRequestContext(Request, RequestFsContext) = 0;
|
|
||||||
else
|
|
||||||
/*
|
|
||||||
* We are using a previously inserted FsContext. We must retain it.
|
|
||||||
* Our own FsContext is still associated with the Request and will be
|
|
||||||
* deleted during IRP completion.
|
|
||||||
*/
|
|
||||||
FspFileContextRetain(FsContext);
|
|
||||||
FspFileContextOpen(FsContext);
|
|
||||||
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
|
||||||
|
|
||||||
/* set up share access on FileObject; user-mode file system assumed to have done share check */
|
/* set up share access on FileObject; user-mode file system assumed to have done share check */
|
||||||
IoSetShareAccess(Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess,
|
IoSetShareAccess(Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess,
|
||||||
FileObject, &TemporaryShareAccess);
|
FileObject, &TemporaryShareAccess);
|
||||||
|
|
||||||
/* finish seting up the FileObject */
|
/* finish setting up the FileObject */
|
||||||
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
|
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
|
||||||
FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb;
|
FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb;
|
||||||
FileObject->SectionObjectPointer = &FsContext->NonPaged->SectionObjectPointers;
|
FileObject->SectionObjectPointer = &FsContext->NonPaged->SectionObjectPointers;
|
||||||
@ -437,9 +461,90 @@ VOID FspFsvolCreateComplete(
|
|||||||
FileObject->FsContext = FsContext;
|
FileObject->FsContext = FsContext;
|
||||||
FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.Opened.UserContext2;
|
FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.Opened.UserContext2;
|
||||||
|
|
||||||
|
if (FILE_SUPERSEDED == Response->IoStatus.Information ||
|
||||||
|
FILE_OVERWRITTEN == Response->IoStatus.Information)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Oh, noes! We have to go back to user mode to overwrite the file!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* delete the old request */
|
||||||
|
FspIopRequestContext(Request, RequestFsContext) = 0;
|
||||||
|
FspIrpRequest(Irp) = 0;
|
||||||
|
FspIopDeleteRequest(Request);
|
||||||
|
|
||||||
|
/* create the Create2 request; MustSucceed because we must either overwrite or close */
|
||||||
|
FspIopCreateRequestMustSucceed(Irp,
|
||||||
|
FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0, 0,
|
||||||
|
&Request);
|
||||||
|
|
||||||
|
/* associate the FsContext with the Create2 request */
|
||||||
|
FspIopRequestContext(Request, RequestFsContext) = FsContext;
|
||||||
|
|
||||||
|
/* populate the Create2 request */
|
||||||
|
Request->Kind = FspFsctlTransactCreate2Kind;
|
||||||
|
Request->Req.Create2.UserContext = FsContext->UserContext;
|
||||||
|
Request->Req.Create2.UserContext2 = (UINT_PTR)FileObject->FsContext2;
|
||||||
|
Request->Req.Create2.FileAttributes = IrpSp->Parameters.Create.FileAttributes;
|
||||||
|
Request->Req.Create2.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information;
|
||||||
|
Request->Req.Create2.CloseStatus = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that it is still possible for this request to not be delivered,
|
||||||
|
* if the volume device Ioq is stopped. But such failures are benign
|
||||||
|
* from our perspective, because they mean that the file system is going
|
||||||
|
* away and should correctly tear things down.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (FspIoqPostIrpNoCap(FsvolDeviceExtension->Ioq, Irp, &Result))
|
||||||
|
Result = STATUS_PENDING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* SUCCESS! */
|
/* SUCCESS! */
|
||||||
Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information;
|
Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FspFsctlTransactCreate2Kind == Request->Kind)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* A Create2 request will either succeed or else fail and close the corresponding file.
|
||||||
|
* There is no need to reach out to user-mode again and ask them to close the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* was this a close request? */
|
||||||
|
if (STATUS_SUCCESS != Request->Req.Create2.CloseStatus)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Result = STATUS_SUCCESS != Request->Req.Create2.CloseStatus;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* did the user-mode file system sent us a failure code? */
|
||||||
|
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||||
|
{
|
||||||
|
FspFileContextPgioUnlock(FsContext);
|
||||||
|
FspFileContextClose(FsvolDeviceObject, FsContext);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
Result = Response->IoStatus.Status;
|
Result = Response->IoStatus.Status;
|
||||||
|
FSP_RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* file was successfully overwritten/superseded */
|
||||||
|
FsContext->Header.AllocationSize.QuadPart = Response->Rsp.Create.Opened.AllocationSize;
|
||||||
|
FsContext->Header.FileSize.QuadPart = Response->Rsp.Create.Opened.AllocationSize;
|
||||||
|
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&FsContext->Header.AllocationSize);
|
||||||
|
|
||||||
|
FspFileContextPgioUnlock(FsContext);
|
||||||
|
|
||||||
|
/* SUCCESS! */
|
||||||
|
Irp->IoStatus.Information = Request->Req.Create2.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ASSERT(0);
|
||||||
|
|
||||||
FSP_LEAVE_IOC(
|
FSP_LEAVE_IOC(
|
||||||
"FileObject=%p[%p:\"%wZ\"]",
|
"FileObject=%p[%p:\"%wZ\"]",
|
||||||
|
@ -527,12 +527,21 @@ typedef struct
|
|||||||
NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
|
||||||
ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext);
|
ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext);
|
||||||
VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext);
|
VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext);
|
||||||
|
FSP_FILE_CONTEXT *FspFileContextOpen(PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
FSP_FILE_CONTEXT *FsContext);
|
||||||
|
VOID FspFileContextClose(PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
FSP_FILE_CONTEXT *FsContext);
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileContextRetain(FSP_FILE_CONTEXT *FsContext)
|
VOID FspFileContextRetain(FSP_FILE_CONTEXT *FsContext)
|
||||||
{
|
{
|
||||||
InterlockedIncrement(&FsContext->RefCount);
|
InterlockedIncrement(&FsContext->RefCount);
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
|
VOID FspFileContextRetain2(FSP_FILE_CONTEXT *FsContext)
|
||||||
|
{
|
||||||
|
InterlockedAdd(&FsContext->RefCount, 2);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
VOID FspFileContextRelease(FSP_FILE_CONTEXT *FsContext)
|
VOID FspFileContextRelease(FSP_FILE_CONTEXT *FsContext)
|
||||||
{
|
{
|
||||||
LONG RefCount = InterlockedDecrement(&FsContext->RefCount);
|
LONG RefCount = InterlockedDecrement(&FsContext->RefCount);
|
||||||
@ -540,14 +549,34 @@ VOID FspFileContextRelease(FSP_FILE_CONTEXT *FsContext)
|
|||||||
FspFileContextDelete(FsContext);
|
FspFileContextDelete(FsContext);
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
VOID FspFileContextOpen(FSP_FILE_CONTEXT *FsContext)
|
BOOLEAN FspFileContextLockShared(FSP_FILE_CONTEXT *FsContext, BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
InterlockedIncrement(&FsContext->OpenCount);
|
return ExAcquireResourceSharedLite(FsContext->Header.Resource, Wait);
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
LONG FspFileContextClose(FSP_FILE_CONTEXT *FsContext)
|
BOOLEAN FspFileContextLockExclusive(FSP_FILE_CONTEXT *FsContext, BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
return InterlockedDecrement(&FsContext->OpenCount);
|
return ExAcquireResourceExclusiveLite(FsContext->Header.Resource, Wait);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
VOID FspFileContextUnlock(FSP_FILE_CONTEXT *FsContext)
|
||||||
|
{
|
||||||
|
ExReleaseResourceLite(FsContext->Header.Resource);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
BOOLEAN FspFileContextPgioLockShared(FSP_FILE_CONTEXT *FsContext, BOOLEAN Wait)
|
||||||
|
{
|
||||||
|
return ExAcquireResourceSharedLite(FsContext->Header.PagingIoResource, Wait);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
BOOLEAN FspFileContextPgioLockExclusive(FSP_FILE_CONTEXT *FsContext, BOOLEAN Wait)
|
||||||
|
{
|
||||||
|
return ExAcquireResourceExclusiveLite(FsContext->Header.PagingIoResource, Wait);
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
VOID FspFileContextPgioUnlock(FSP_FILE_CONTEXT *FsContext)
|
||||||
|
{
|
||||||
|
ExReleaseResourceLite(FsContext->Header.PagingIoResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* debug */
|
/* debug */
|
||||||
|
@ -72,3 +72,74 @@ VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext)
|
|||||||
|
|
||||||
FspFree(FsContext);
|
FspFree(FsContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_FILE_CONTEXT *FspFileContextOpen(PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
FSP_FILE_CONTEXT *FsContext)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Attempt to insert our FsContext into the volume device's generic table.
|
||||||
|
* If an FsContext with the same UserContext already exists, then use that
|
||||||
|
* FsContext instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FSP_FILE_CONTEXT *OpenedFsContext;
|
||||||
|
BOOLEAN Inserted;
|
||||||
|
|
||||||
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
OpenedFsContext = FspFsvolDeviceInsertContext(FsvolDeviceObject,
|
||||||
|
FsContext->UserContext, FsContext, &FsContext->ElementStorage, &Inserted);
|
||||||
|
ASSERT(0 != OpenedFsContext);
|
||||||
|
|
||||||
|
if (Inserted)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The new FsContext was inserted into the Context table.
|
||||||
|
* Retain it. There should be (at least) two references to this FsContext,
|
||||||
|
* one from our caller and one from the Context table.
|
||||||
|
*/
|
||||||
|
ASSERT(OpenedFsContext == FsContext);
|
||||||
|
|
||||||
|
FspFileContextRetain(OpenedFsContext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The new FsContext was NOT inserted into the Context table,
|
||||||
|
* instead a prior FsContext is being opened.
|
||||||
|
* Release the new FsContext since the caller will no longer reference it,
|
||||||
|
* and retain the prior FsContext TWICE, once for our caller and once for
|
||||||
|
* the Context table.
|
||||||
|
*/
|
||||||
|
ASSERT(OpenedFsContext != FsContext);
|
||||||
|
|
||||||
|
FspFileContextRetain2(OpenedFsContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterlockedIncrement(&OpenedFsContext->OpenCount);
|
||||||
|
|
||||||
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
|
||||||
|
if (!Inserted)
|
||||||
|
FspFileContextRelease(FsContext);
|
||||||
|
|
||||||
|
return OpenedFsContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspFileContextClose(PDEVICE_OBJECT FsvolDeviceObject,
|
||||||
|
FSP_FILE_CONTEXT *FsContext)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Close the FsContext. If the OpenCount becomes zero remove it
|
||||||
|
* from the Context table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (0 == InterlockedDecrement(&FsContext->OpenCount))
|
||||||
|
{
|
||||||
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
|
FspFsvolDeviceDeleteContext(FsvolDeviceObject, FsContext->UserContext, 0);
|
||||||
|
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileContextRelease(FsContext);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user