2005-08-24 18:29:45 +00:00
|
|
|
/*
|
2001-11-02 22:47:36 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
2003-10-11 17:51:56 +00:00
|
|
|
* FILE: drivers/fs/vfat/misc.c
|
2001-11-02 22:47:36 +00:00
|
|
|
* PURPOSE: VFAT Filesystem
|
2007-10-19 23:21:45 +00:00
|
|
|
* PROGRAMMER:
|
2001-11-02 22:47:36 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include "vfat.h"
|
|
|
|
|
2005-01-25 21:13:28 +00:00
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
|
|
|
const char* MajorFunctionNames[] =
|
|
|
|
{
|
|
|
|
"IRP_MJ_CREATE",
|
|
|
|
"IRP_MJ_CREATE_NAMED_PIPE",
|
|
|
|
"IRP_MJ_CLOSE",
|
|
|
|
"IRP_MJ_READ",
|
|
|
|
"IRP_MJ_WRITE",
|
|
|
|
"IRP_MJ_QUERY_INFORMATION",
|
|
|
|
"IRP_MJ_SET_INFORMATION",
|
|
|
|
"IRP_MJ_QUERY_EA",
|
|
|
|
"IRP_MJ_SET_EA",
|
|
|
|
"IRP_MJ_FLUSH_BUFFERS",
|
|
|
|
"IRP_MJ_QUERY_VOLUME_INFORMATION",
|
|
|
|
"IRP_MJ_SET_VOLUME_INFORMATION",
|
|
|
|
"IRP_MJ_DIRECTORY_CONTROL",
|
|
|
|
"IRP_MJ_FILE_SYSTEM_CONTROL",
|
|
|
|
"IRP_MJ_DEVICE_CONTROL",
|
|
|
|
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
|
|
|
|
"IRP_MJ_SHUTDOWN",
|
|
|
|
"IRP_MJ_LOCK_CONTROL",
|
|
|
|
"IRP_MJ_CLEANUP",
|
|
|
|
"IRP_MJ_CREATE_MAILSLOT",
|
|
|
|
"IRP_MJ_QUERY_SECURITY",
|
|
|
|
"IRP_MJ_SET_SECURITY",
|
|
|
|
"IRP_MJ_POWER",
|
|
|
|
"IRP_MJ_SYSTEM_CONTROL",
|
|
|
|
"IRP_MJ_DEVICE_CHANGE",
|
|
|
|
"IRP_MJ_QUERY_QUOTA",
|
|
|
|
"IRP_MJ_SET_QUOTA",
|
|
|
|
"IRP_MJ_PNP",
|
|
|
|
"IRP_MJ_MAXIMUM_FUNCTION"
|
|
|
|
};
|
|
|
|
|
2001-11-02 22:47:36 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
|
|
|
static LONG QueueCount = 0;
|
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static NTSTATUS VfatLockControl(
|
2003-07-10 11:03:51 +00:00
|
|
|
IN PVFAT_IRP_CONTEXT IrpContext
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PVFATFCB Fcb;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2007-11-21 16:50:07 +00:00
|
|
|
DPRINT("VfatLockControl(IrpContext %p)\n", IrpContext);
|
2004-11-06 13:44:57 +00:00
|
|
|
|
|
|
|
ASSERT(IrpContext);
|
2003-07-10 11:03:51 +00:00
|
|
|
|
|
|
|
Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
|
|
|
|
|
|
|
|
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
goto Fail;
|
|
|
|
}
|
|
|
|
|
2004-12-05 16:31:51 +00:00
|
|
|
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
|
2003-07-10 11:03:51 +00:00
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
goto Fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = FsRtlProcessFileLock(&Fcb->FileLock,
|
|
|
|
IrpContext->Irp,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
VfatFreeIrpContext(IrpContext);
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
Fail:;
|
|
|
|
IrpContext->Irp->IoStatus.Status = Status;
|
2009-07-15 19:40:44 +00:00
|
|
|
IoCompleteRequest(IrpContext->Irp, (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
|
2003-07-10 11:03:51 +00:00
|
|
|
VfatFreeIrpContext(IrpContext);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static NTSTATUS
|
2005-01-25 21:13:28 +00:00
|
|
|
VfatDispatchRequest (IN PVFAT_IRP_CONTEXT IrpContext)
|
2001-11-02 22:47:36 +00:00
|
|
|
{
|
2007-11-21 16:50:07 +00:00
|
|
|
DPRINT ("VfatDispatchRequest (IrpContext %p), is called for %s\n", IrpContext,
|
2005-01-25 21:13:28 +00:00
|
|
|
IrpContext->MajorFunction >= IRP_MJ_MAXIMUM_FUNCTION ? "????" : MajorFunctionNames[IrpContext->MajorFunction]);
|
2001-11-02 22:47:36 +00:00
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(IrpContext);
|
2001-11-02 22:47:36 +00:00
|
|
|
|
|
|
|
switch (IrpContext->MajorFunction)
|
|
|
|
{
|
|
|
|
case IRP_MJ_CLOSE:
|
|
|
|
return VfatClose (IrpContext);
|
|
|
|
case IRP_MJ_CREATE:
|
|
|
|
return VfatCreate (IrpContext);
|
|
|
|
case IRP_MJ_READ:
|
|
|
|
return VfatRead (IrpContext);
|
|
|
|
case IRP_MJ_WRITE:
|
|
|
|
return VfatWrite (IrpContext);
|
|
|
|
case IRP_MJ_FILE_SYSTEM_CONTROL:
|
|
|
|
return VfatFileSystemControl(IrpContext);
|
|
|
|
case IRP_MJ_QUERY_INFORMATION:
|
|
|
|
return VfatQueryInformation (IrpContext);
|
|
|
|
case IRP_MJ_SET_INFORMATION:
|
|
|
|
return VfatSetInformation (IrpContext);
|
|
|
|
case IRP_MJ_DIRECTORY_CONTROL:
|
|
|
|
return VfatDirectoryControl(IrpContext);
|
|
|
|
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
|
|
|
return VfatQueryVolumeInformation(IrpContext);
|
|
|
|
case IRP_MJ_SET_VOLUME_INFORMATION:
|
|
|
|
return VfatSetVolumeInformation(IrpContext);
|
2003-01-25 15:55:08 +00:00
|
|
|
case IRP_MJ_LOCK_CONTROL:
|
|
|
|
return VfatLockControl(IrpContext);
|
2001-11-02 22:47:36 +00:00
|
|
|
case IRP_MJ_CLEANUP:
|
|
|
|
return VfatCleanup(IrpContext);
|
2003-02-09 18:02:56 +00:00
|
|
|
case IRP_MJ_FLUSH_BUFFERS:
|
|
|
|
return VfatFlush(IrpContext);
|
[FASTFAT]
Make our FAT driver PNP aware.
On PNP requests it should handle, it will return STATUS_NOT_IMPLEMENTED.
On the others, it will pass them to lower driver.
This is the first step outside the kernel into getting IoGetRelatedTargetDevice (and so notifications) working.
It doesn't work at the moment, as class2 doesn't handle PNP.
[NTOSKRNL]
Some fixes to IRP cancelation process:
- Renamed IopRemoveThreadIrp() to IopDisassociateThreadIrp() to match Windows 2k3
- Made dead IRP global, to make its debug easier.
- IopDisassociateThreadIrp(), Handle dead IRP at dispatch level, using IoCompletionLock.
- IopDisassociateThreadIrp(), Use the proper error code to write the entry to logs.
- IoCancelIrp(), removed non needed ASSERT, which is even not present on Windows, removed corresponding var as well.
- IoCancelIrp(), fixed parameters to KeBugCheckEx() call.
- IoCancelThreadIo() is pageable.
- IoCancelThreadIo() under Windows isn't using given thread, but using current. Do the same here.
All that stuff doesn't fix bug #5550, it comes from outside.
Patch by Pierre Schweitzer, modified by me to make it compile. If it breaks anything, don't blame me!
svn path=/trunk/; revision=48560
2010-08-18 23:21:15 +00:00
|
|
|
case IRP_MJ_PNP:
|
|
|
|
return VfatPnp(IrpContext);
|
2001-11-02 22:47:36 +00:00
|
|
|
default:
|
|
|
|
DPRINT1 ("Unexpected major function %x\n", IrpContext->MajorFunction);
|
|
|
|
IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
|
|
|
|
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
|
|
|
|
VfatFreeIrpContext(IrpContext);
|
|
|
|
return STATUS_DRIVER_INTERNAL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-03 07:15:12 +00:00
|
|
|
NTSTATUS NTAPI VfatBuildRequest (
|
2001-11-02 22:47:36 +00:00
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVFAT_IRP_CONTEXT IrpContext;
|
|
|
|
|
2007-11-21 16:50:07 +00:00
|
|
|
DPRINT ("VfatBuildRequest (DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
2001-11-02 22:47:36 +00:00
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(DeviceObject);
|
|
|
|
ASSERT(Irp);
|
2001-11-02 22:47:36 +00:00
|
|
|
IrpContext = VfatAllocateIrpContext(DeviceObject, Irp);
|
|
|
|
if (IrpContext == NULL)
|
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-01-12 15:20:22 +00:00
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
Status = VfatDispatchRequest (IrpContext);
|
|
|
|
FsRtlExitFileSystem();
|
2001-11-02 22:47:36 +00:00
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID VfatFreeIrpContext (PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
{
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(IrpContext);
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
ExFreeToNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList, IrpContext);
|
2001-11-02 22:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
|
|
{
|
|
|
|
PVFAT_IRP_CONTEXT IrpContext;
|
2003-07-24 19:00:42 +00:00
|
|
|
/*PIO_STACK_LOCATION Stack;*/
|
2001-11-02 22:47:36 +00:00
|
|
|
UCHAR MajorFunction;
|
2007-11-21 16:50:07 +00:00
|
|
|
DPRINT ("VfatAllocateIrpContext(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
2001-11-02 22:47:36 +00:00
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(DeviceObject);
|
|
|
|
ASSERT(Irp);
|
2001-11-02 22:47:36 +00:00
|
|
|
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
|
2001-11-02 22:47:36 +00:00
|
|
|
if (IrpContext)
|
|
|
|
{
|
2004-05-15 23:00:02 +00:00
|
|
|
RtlZeroMemory(IrpContext, sizeof(VFAT_IRP_CONTEXT));
|
2001-11-02 22:47:36 +00:00
|
|
|
IrpContext->Irp = Irp;
|
|
|
|
IrpContext->DeviceObject = DeviceObject;
|
|
|
|
IrpContext->DeviceExt = DeviceObject->DeviceExtension;
|
|
|
|
IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(IrpContext->Stack);
|
2001-11-02 22:47:36 +00:00
|
|
|
MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
|
|
|
|
IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
|
|
|
|
IrpContext->FileObject = IrpContext->Stack->FileObject;
|
2004-05-15 23:00:02 +00:00
|
|
|
IrpContext->Flags = 0;
|
2001-11-02 22:47:36 +00:00
|
|
|
if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
|
|
|
|
MajorFunction == IRP_MJ_DEVICE_CONTROL ||
|
|
|
|
MajorFunction == IRP_MJ_SHUTDOWN)
|
|
|
|
{
|
|
|
|
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
|
|
|
}
|
|
|
|
else if (MajorFunction != IRP_MJ_CLEANUP &&
|
|
|
|
MajorFunction != IRP_MJ_CLOSE &&
|
2002-09-30 20:49:44 +00:00
|
|
|
IoIsOperationSynchronous(Irp))
|
2001-11-02 22:47:36 +00:00
|
|
|
{
|
|
|
|
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
|
|
|
}
|
2004-05-15 23:00:02 +00:00
|
|
|
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
|
|
|
|
IrpContext->RefCount = 0;
|
2001-11-02 22:47:36 +00:00
|
|
|
}
|
|
|
|
return IrpContext;
|
|
|
|
}
|
|
|
|
|
2005-10-06 21:39:18 +00:00
|
|
|
static VOID NTAPI VfatDoRequest (PVOID IrpContext)
|
2001-11-02 22:47:36 +00:00
|
|
|
{
|
2003-10-11 17:51:56 +00:00
|
|
|
InterlockedDecrement(&QueueCount);
|
2007-11-21 16:50:07 +00:00
|
|
|
DPRINT ("VfatDoRequest (IrpContext %p), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
|
2004-03-04 01:29:24 +00:00
|
|
|
FsRtlEnterFileSystem();
|
2001-11-02 22:47:36 +00:00
|
|
|
VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
|
2004-03-04 01:29:24 +00:00
|
|
|
FsRtlExitFileSystem();
|
2001-11-02 22:47:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
|
|
|
|
{
|
2003-10-11 17:51:56 +00:00
|
|
|
InterlockedIncrement(&QueueCount);
|
2007-11-21 16:50:07 +00:00
|
|
|
DPRINT ("VfatQueueRequest (IrpContext %p), %d\n", IrpContext, QueueCount);
|
2001-11-02 22:47:36 +00:00
|
|
|
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(IrpContext != NULL);
|
|
|
|
ASSERT(IrpContext->Irp != NULL);
|
2001-11-02 22:47:36 +00:00
|
|
|
|
|
|
|
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
|
|
|
|
IoMarkIrpPending (IrpContext->Irp);
|
|
|
|
ExInitializeWorkItem (&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext);
|
|
|
|
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
|
|
|
|
return STATUS_PENDING;
|
|
|
|
}
|
|
|
|
|
2002-05-05 20:19:45 +00:00
|
|
|
PVOID VfatGetUserBuffer(IN PIRP Irp)
|
|
|
|
{
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(Irp);
|
2002-05-05 20:19:45 +00:00
|
|
|
|
|
|
|
if (Irp->MdlAddress)
|
|
|
|
{
|
2005-01-12 13:07:17 +00:00
|
|
|
/* This call may be in the paging path, so use maximum priority */
|
|
|
|
/* FIXME: call with normal priority in the non-paging path */
|
|
|
|
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
|
2002-05-05 20:19:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Irp->UserBuffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
|
|
|
|
{
|
2004-11-06 13:44:57 +00:00
|
|
|
ASSERT(Irp);
|
2002-05-05 20:19:45 +00:00
|
|
|
|
|
|
|
if (Irp->MdlAddress)
|
|
|
|
{
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
|
|
|
|
|
|
|
|
if (!Irp->MdlAddress)
|
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2001-11-02 22:47:36 +00:00
|
|
|
|
|
|
|
|