Major refactoring: IRP_MJ_CREATE

This commit is contained in:
Bill Zissimopoulos 2015-12-24 15:46:54 -08:00
parent 1bd9c09d22
commit e3c04e15ba
3 changed files with 126 additions and 55 deletions

View File

@ -123,7 +123,6 @@ typedef struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 Delete:1; /* if set, the file or directory must be deleted */
} Cleanup;
struct
{
@ -154,6 +153,7 @@ typedef struct
{
UINT64 UserContext; /* open file user context (unique file id) */
UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
} Opened;
/* IoStatus.Status == STATUS_REPARSE */
struct

View File

@ -105,7 +105,7 @@ static NTSTATUS FspFsvolCreate(
BOOLEAN IsAbsoluteSecurityDescriptor = FALSE;
BOOLEAN IsSelfRelativeSecurityDescriptor = FALSE;
BOOLEAN HasTrailingBackslash = FALSE;
FSP_FILE_CONTEXT *FsContext = 0, *RelatedFsContext;
FSP_FILE_CONTEXT *FsContext, *RelatedFsContext;
FSP_FSCTL_TRANSACT_REQ *Request;
/* cannot open files by fileid */
@ -313,6 +313,110 @@ VOID FspFsvolCreateComplete(
{
FSP_ENTER_IOC(PAGED_CODE());
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PFILE_OBJECT FileObject = IrpSp->FileObject;
SHARE_ACCESS TemporaryShareAccess;
UNICODE_STRING ReparseFileName;
FSP_FSCTL_TRANSACT_REQ *Request;
FSP_FILE_CONTEXT *FsContext;
BOOLEAN Inserted;
/* did the user-mode file system sent us a failure code? */
if (!NT_SUCCESS(Response->IoStatus.Status))
{
Irp->IoStatus.Information = Response->IoStatus.Information;
Result = Response->IoStatus.Status;
FSP_RETURN();
}
/* special case STATUS_REPARSE */
if (STATUS_REPARSE == Result)
{
ReparseFileName.Buffer =
(PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset);
ReparseFileName.Length = ReparseFileName.MaximumLength =
Response->Rsp.Create.Reparse.FileName.Size;
Result = STATUS_ACCESS_DENIED;
if (IO_REPARSE == Response->IoStatus.Information)
{
if (0 == ReparseFileName.Length ||
(PUINT8)ReparseFileName.Buffer + ReparseFileName.Length >
(PUINT8)Response + Response->Size)
FSP_RETURN();
if (ReparseFileName.Length > FileObject->FileName.MaximumLength)
{
PVOID Buffer = FspAllocExternal(ReparseFileName.Length);
if (0 == Buffer)
FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES);
FspFreeExternal(FileObject->FileName.Buffer);
FileObject->FileName.MaximumLength = ReparseFileName.Length;
FileObject->FileName.Buffer = Buffer;
}
FileObject->FileName.Length = 0;
RtlCopyUnicodeString(&FileObject->FileName, &ReparseFileName);
}
else
if (IO_REMOUNT == Response->IoStatus.Information)
{
if (0 != ReparseFileName.Length)
FSP_RETURN();
}
else
FSP_RETURN();
Irp->IoStatus.Information = Response->IoStatus.Information;
Result = Response->IoStatus.Status;
FSP_RETURN();
}
/* get the FsContext from our Request and associate it with the Response UserContext */
Request = FspIrpRequest(Irp);
FsContext = FspIopRequestContext(Request, RequestFsContext);
FsContext->UserContext = Response->Rsp.Create.Opened.UserContext;
/*
* 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.
*/
FspFsvolDeviceLockContext(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);
FspFsvolDeviceUnlockContext(FsvolDeviceObject);
/* 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,
FileObject, &TemporaryShareAccess);
/* finish seting up the FileObject */
if (0 != FsvolDeviceExtension->FsvrtDeviceObject)
FileObject->Vpb = FsvolDeviceExtension->FsvrtDeviceObject->Vpb;
FileObject->SectionObjectPointer = &FsContext->NonPaged->SectionObjectPointers;
FileObject->PrivateCacheMap = 0;
FileObject->FsContext = FsContext;
FileObject->FsContext2 = (PVOID)(UINT_PTR)Response->Rsp.Create.Opened.UserContext2;
/* SUCCESS! */
Irp->IoStatus.Information = Response->IoStatus.Information;
Result = Response->IoStatus.Status;
FSP_LEAVE_IOC(
"FileObject=%p[%p:\"%wZ\"]",
IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName);

View File

@ -456,6 +456,7 @@ typedef struct
ERESOURCE Resource;
ERESOURCE PagingIoResource;
FAST_MUTEX HeaderFastMutex;
SECTION_OBJECT_POINTERS SectionObjectPointers;
} FSP_FILE_CONTEXT_NONPAGED;
typedef struct
{
@ -463,34 +464,38 @@ typedef struct
FSP_FILE_CONTEXT_NONPAGED *NonPaged;
/* interlocked access */
LONG RefCount;
#if 0
/* protected by Header.Resource */
LONG OpenCount;
SHARE_ACCESS ShareAccess;
BOOLEAN DeletePending; /* FileDispositionInformation */
BOOLEAN DeleteOnClose; /* FILE_DELETE_ON_CLOSE */
FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage;
UINT64 UserContext;
#endif
/* read-only after creation */
/* read-only after creation (and insertion in the GenericTable) */
PDEVICE_OBJECT FsvolDeviceObject;
UINT64 UserContext;
FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage;
UNICODE_STRING FileName;
WCHAR FileNameBuf[];
} FSP_FILE_CONTEXT;
NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext);
VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context);
VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext);
static inline
VOID FspFileContextRetain(FSP_FILE_CONTEXT *Context)
VOID FspFileContextRetain(FSP_FILE_CONTEXT *FsContext)
{
InterlockedIncrement(&Context->RefCount);
InterlockedIncrement(&FsContext->RefCount);
}
static inline
VOID FspFileContextRelease(FSP_FILE_CONTEXT *Context)
VOID FspFileContextRelease(FSP_FILE_CONTEXT *FsContext)
{
LONG RefCount = InterlockedDecrement(&Context->RefCount);
LONG RefCount = InterlockedDecrement(&FsContext->RefCount);
if (0 == RefCount)
FspFileContextDelete(Context);
FspFileContextDelete(FsContext);
}
static inline
VOID FspFileContextOpen(FSP_FILE_CONTEXT *FsContext)
{
InterlockedIncrement(&FsContext->OpenCount);
}
static inline
LONG FspFileContextClose(FSP_FILE_CONTEXT *FsContext)
{
return InterlockedDecrement(&FsContext->OpenCount);
}
/* debug */
@ -508,42 +513,4 @@ extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
#if 0
typedef struct
{
FSRTL_ADVANCED_FCB_HEADER Header;
FSP_FILE_CONTEXT_NONPAGED *NonPaged;
/* interlocked access */
LONG RefCount;
/* protected by Header.Resource */
LONG OpenCount;
SHARE_ACCESS ShareAccess;
BOOLEAN DeletePending; /* FileDispositionInformation */
BOOLEAN DeleteOnClose; /* FILE_DELETE_ON_CLOSE */
/* read-only after creation */
FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage;
PDEVICE_OBJECT FsvolDeviceObject;
UINT64 UserContext;
UNICODE_STRING FileName;
WCHAR FileNameBuf[];
} FSP_FILE_CONTEXT;
NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext);
VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context);
static inline
VOID FspFileContextOpen(FSP_FILE_CONTEXT *Context)
{
ASSERT(0 == Context->OpenCount || ExIsResourceAcquiredExclusiveLite(Context->Header.Resource));
Context->OpenCount++;
}
static inline
LONG FspFileContextClose(FSP_FILE_CONTEXT *Context)
{
ASSERT(ExIsResourceAcquiredExclusiveLite(Context->Header.Resource));
ASSERT(0 < Context->OpenCount);
return --Context->OpenCount;
}
#endif
#endif