コード例 #1
0
NTSTATUS
xixfs_CommonQueryVolumeInformation(
	IN PXIXFS_IRPCONTEXT pIrpContext
	)
{
	NTSTATUS				RC = STATUS_SUCCESS;
	PIRP					pIrp = NULL;
	PIO_STACK_LOCATION		pIrpSp = NULL;
	PXIXFS_VCB				pVCB = NULL;
	PXIXFS_FCB				pFCB = NULL;
	PXIXFS_CCB				pCCB = NULL;
	PFILE_OBJECT				pFileObject = NULL;
	BOOLEAN					Wait = FALSE;
	uint32					BytesToReturn = 0;
	uint32					Length = 0;
	TYPE_OF_OPEN			TypeOfOpen = UnopenedFileObject;

	PAGED_CODE();
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT),
		("Enter xixfs_CommonQueryVolumeInformation \n"));

	ASSERT(pIrpContext);

	pIrp = pIrpContext->Irp;
	ASSERT(pIrp);

	pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
	ASSERT(pIrp);

	pFileObject = pIrpSp->FileObject;
	ASSERT(pFileObject);

	TypeOfOpen = xixfs_DecodeFileObject( pFileObject, &pFCB, &pCCB );

    if (TypeOfOpen == UnopenedFileObject) {
		RC = STATUS_INVALID_PARAMETER;
        xixfs_CompleteRequest( pIrpContext, STATUS_INVALID_PARAMETER, 0 );
        return RC;
    }


	DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, 
					("!!!!VolumeInformation  pCCB(%p)\n", pCCB));

	pVCB = pFCB->PtrVCB;
	ASSERT_VCB(pVCB);


	Wait = XIXCORE_TEST_FLAGS(pIrpContext->IrpContextFlags, XIFSD_IRP_CONTEXT_WAIT);
	




	if(!ExAcquireResourceSharedLite(&(pVCB->VCBResource), Wait)){
		DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT),
					("PostRequest IrpContext(%p) Irp(%p)\n", pIrpContext, pIrp));
		RC = xixfs_PostRequest(pIrpContext, pIrp);
		return RC;
	}

	try{


		Length = pIrpSp->Parameters.QueryVolume.Length ;


		DebugTrace(DEBUG_LEVEL_INFO, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT),
					 ("pIrpSp->Parameters.QueryVolume.FsInformationClass (0x%x)\n", 
					 pIrpSp->Parameters.QueryVolume.FsInformationClass));
	

		switch (pIrpSp->Parameters.QueryVolume.FsInformationClass) {

		case FileFsSizeInformation:
		{
	

			RC = xixfs_QueryFsSizeInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn );
			xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn);
			break;
		}
		case FileFsVolumeInformation:
		{

			RC = xixfs_QueryFsVolumeInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn );
			xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn);
			break;
		}
		case FileFsDeviceInformation:
		{

			RC = xixfs_QueryFsDeviceInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn );
			xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn);
			break;
		}
		case FileFsAttributeInformation:
		{

			RC = xixfs_QueryFsAttributeInfo( pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn );
			xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn);
			break;
		}		
		case FileFsFullSizeInformation:
		{
			RC = xixfs_QueryFsFullSizeInfo(pIrpContext, pVCB, pIrp->AssociatedIrp.SystemBuffer, Length, &BytesToReturn);
			xixfs_CompleteRequest(pIrpContext, RC, BytesToReturn);
			break;
		}
		default:
			DebugTrace( DEBUG_LEVEL_ERROR, DEBUG_TARGET_ALL,
				("default Not supported Volume Info %ld\n",pIrpSp->Parameters.QueryVolume.FsInformationClass));
			RC = STATUS_INVALID_PARAMETER;
			xixfs_CompleteRequest(pIrpContext, RC, 0);
		break;
		 }

		

	}finally{
		ExReleaseResourceLite(&(pVCB->VCBResource));
	}
	DebugTrace(DEBUG_LEVEL_TRACE, (DEBUG_TARGET_VOLINFO|DEBUG_TARGET_IRPCONTEXT),
		("Exit xixfs_CommonQueryVolumeInformation \n"));
	return RC;	
}
コード例 #2
0
ファイル: fileinfo.c プロジェクト: ApocalypticOctopus/dokan
VOID
DokanCompleteSetInformation(
	__in PIRP_ENTRY		IrpEntry,
	__in PEVENT_INFORMATION EventInfo
	)
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status;
	ULONG				info	 = 0;
	PDokanCCB			ccb;
	PDokanFCB			fcb;
	UNICODE_STRING		oldFileName;

	FILE_INFORMATION_CLASS infoClass;

	__try {

		DDbgPrint("==> DokanCompleteSetInformation\n");

		irp = IrpEntry->Irp;
		irpSp = IrpEntry->IrpSp;

		ccb = IrpEntry->FileObject->FsContext2;
		ASSERT(ccb != NULL);

		ExAcquireResourceExclusiveLite(&ccb->Resource, TRUE);

		fcb = ccb->Fcb;
		ASSERT(fcb != NULL);

		ccb->UserContext = EventInfo->Context;

		status = EventInfo->Status;
		info = EventInfo->BufferLength;

		infoClass = irpSp->Parameters.SetFile.FileInformationClass;

		RtlZeroMemory(&oldFileName, sizeof(UNICODE_STRING));

		if (NT_SUCCESS(status)) {
			
			if (infoClass == FileDispositionInformation) {

				if (EventInfo->Delete.DeleteOnClose) {

					if (!MmFlushImageSection(
						&fcb->SectionObjectPointers,
						MmFlushForDelete)) {
						DDbgPrint("  Cannot delete user mapped image\n");
						status = STATUS_CANNOT_DELETE;
					} else {
						ccb->Flags |= DOKAN_DELETE_ON_CLOSE;
						fcb->Flags |= DOKAN_DELETE_ON_CLOSE;
						DDbgPrint("   FileObject->DeletePending = TRUE\n");
						IrpEntry->FileObject->DeletePending = TRUE;
					}

				} else {
					ccb->Flags &= ~DOKAN_DELETE_ON_CLOSE;
					fcb->Flags &= ~DOKAN_DELETE_ON_CLOSE;
					DDbgPrint("   FileObject->DeletePending = FALSE\n");
					IrpEntry->FileObject->DeletePending = FALSE;
				}
			}

			// if rename is executed, reassign the file name
			if(infoClass == FileRenameInformation) {
				PVOID buffer = NULL;

				ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE);

				// this is used to inform rename in the bellow switch case
				oldFileName.Buffer = fcb->FileName.Buffer;
				oldFileName.Length = (USHORT)fcb->FileName.Length;
				oldFileName.MaximumLength = (USHORT)fcb->FileName.Length;

				// copy new file name
				buffer = ExAllocatePool(EventInfo->BufferLength+sizeof(WCHAR));

				if (buffer == NULL) {
					status = STATUS_INSUFFICIENT_RESOURCES;
					ExReleaseResourceLite(&fcb->Resource);
					ExReleaseResourceLite(&ccb->Resource);
					__leave;
				}

				fcb->FileName.Buffer = buffer;

				ASSERT(fcb->FileName.Buffer != NULL);

				RtlZeroMemory(fcb->FileName.Buffer, EventInfo->BufferLength+sizeof(WCHAR));
				RtlCopyMemory(fcb->FileName.Buffer, EventInfo->Buffer, EventInfo->BufferLength);

				fcb->FileName.Length = (USHORT)EventInfo->BufferLength;
				fcb->FileName.MaximumLength = (USHORT)EventInfo->BufferLength;

				ExReleaseResourceLite(&fcb->Resource);
			}
		}

		ExReleaseResourceLite(&ccb->Resource);

		if (NT_SUCCESS(status)) {
			switch (irpSp->Parameters.SetFile.FileInformationClass) {
			case FileAllocationInformation:
				DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED);
				break;
			case FileBasicInformation:
				DokanNotifyReportChange(fcb,
					FILE_NOTIFY_CHANGE_ATTRIBUTES |
					FILE_NOTIFY_CHANGE_LAST_WRITE |
					FILE_NOTIFY_CHANGE_LAST_ACCESS |
					FILE_NOTIFY_CHANGE_CREATION,
					FILE_ACTION_MODIFIED);
				break;
			case FileDispositionInformation:
				if (IrpEntry->FileObject->DeletePending) {
					if (fcb->Flags & DOKAN_FILE_DIRECTORY) {
						DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED);
					} else {
						DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED);
					}
				}
				break;
			case FileEndOfFileInformation:
				DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED);
				break;
			case FileLinkInformation:
				// TODO: should check whether this is a directory
				// TODO: should notify new link name
				//DokanNotifyReportChange(vcb, ccb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED);
				break;
			case FilePositionInformation:
				// this is never used
				break;
			case FileRenameInformation:
				{
					DokanNotifyReportChange0(fcb, &oldFileName,
						FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_RENAMED_OLD_NAME);
					
					// free old file name
					ExFreePool(oldFileName.Buffer);

					DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_RENAMED_NEW_NAME);
				}
				break;
			case FileValidDataLengthInformation:
				DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED);
				break;
			default:
				DDbgPrint("  unknown type:%d\n", irpSp->Parameters.SetFile.FileInformationClass);
				break;
			}
		}

	} __finally {

		irp->IoStatus.Status = status;
		irp->IoStatus.Information = info;
		IoCompleteRequest(irp, IO_NO_INCREMENT);

		DokanPrintNTStatus(status);

		DDbgPrint("<== DokanCompleteSetInformation\n");
	}
}
コード例 #3
0
ファイル: read.c プロジェクト: GYGit/reactos
BOOLEAN
NTAPI
NpCommonRead(IN PFILE_OBJECT FileObject,
             IN PVOID Buffer,
             IN ULONG BufferSize,
             OUT PIO_STATUS_BLOCK IoStatus,
             IN PIRP Irp,
             IN PLIST_ENTRY List)
{
    NODE_TYPE_CODE NodeType;
    PNP_DATA_QUEUE ReadQueue;
    PNP_EVENT_BUFFER EventBuffer;
    NTSTATUS Status;
    ULONG NamedPipeEnd;
    PNP_CCB Ccb;
    PNP_NONPAGED_CCB NonPagedCcb;
    BOOLEAN ReadOk;
    PAGED_CODE();

    IoStatus->Information = 0;
    NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &NamedPipeEnd);

    if (!NodeType)
    {
        IoStatus->Status = STATUS_PIPE_DISCONNECTED;
        return TRUE;
    }

    if (NodeType != NPFS_NTC_CCB)
    {
        IoStatus->Status = STATUS_INVALID_PARAMETER;
        return TRUE;
    }

    NonPagedCcb = Ccb->NonPagedCcb;
    ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);

    if (Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE || Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE)
    {
        IoStatus->Status = Ccb->NamedPipeState != FILE_PIPE_DISCONNECTED_STATE ? STATUS_PIPE_LISTENING : STATUS_PIPE_DISCONNECTED;
        ReadOk = TRUE;
        goto Quickie;
    }

    ASSERT((Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE) || (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE));

    if ((NamedPipeEnd == FILE_PIPE_SERVER_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND) ||
        (NamedPipeEnd == FILE_PIPE_CLIENT_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND))
    {
        IoStatus->Status = STATUS_INVALID_PARAMETER;
        ReadOk = TRUE;
        goto Quickie;
    }

    if (NamedPipeEnd == FILE_PIPE_SERVER_END)
    {
        ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
    }
    else
    {
        ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
    }

    EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];

    if (ReadQueue->QueueState == WriteEntries)
    {
        *IoStatus = NpReadDataQueue(ReadQueue,
                                    FALSE,
                                    FALSE,
                                    Buffer,
                                    BufferSize,
                                    Ccb->ReadMode[NamedPipeEnd],
                                    Ccb,
                                    List);
        if (!NT_SUCCESS(IoStatus->Status))
        {
            ReadOk = TRUE;
            goto Quickie;
        }

        ReadOk = TRUE;
        if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
        goto Quickie;
    }

    if (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE)
    {
        IoStatus->Status = STATUS_PIPE_BROKEN;
        ReadOk = TRUE;
        if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
        goto Quickie;
    }

    if (Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION)
    {
        IoStatus->Status = STATUS_PIPE_EMPTY;
        ReadOk = TRUE;
        if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
        goto Quickie;
    }

    if (!Irp)
    {
        ReadOk = FALSE;
        goto Quickie;
    }

    Status = NpAddDataQueueEntry(NamedPipeEnd,
                                 Ccb,
                                 ReadQueue,
                                 ReadEntries,
                                 Buffered,
                                 BufferSize,
                                 Irp,
                                 NULL,
                                 0);
    IoStatus->Status = Status;
    if (!NT_SUCCESS(Status))
    {
        ReadOk = FALSE;
    }
    else
    {
        ReadOk = TRUE;
        if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
    }

Quickie:
    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
    return ReadOk;
}
コード例 #4
0
NTSTATUS
FatPostStackOverflowRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine posts a read request that could not be processed by
    the fsp thread because of stack overflow potential.

Arguments:

    Irp - Supplies the request to process.

    Fcb - Supplies the file.

Return Value:

    STATUS_PENDING.

--*/

{
    KEVENT Event;
    PERESOURCE Resource;
    PVCB Vcb;

    PAGED_CODE();

    DebugTrace(0, Dbg, "Getting too close to stack limit pass request to Fsp\n", 0 );

    //
    //  Initialize an event and get shared on the resource we will
    //  be later using the common read.
    //

    KeInitializeEvent( &Event, NotificationEvent, FALSE );

    //
    //  Preacquire the resource the read path will require so we know the
    //  worker thread can proceed without waiting.
    //
    
    if (FlagOn(Irp->Flags, IRP_PAGING_IO) && (Fcb->Header.PagingIoResource != NULL)) {

        Resource = Fcb->Header.PagingIoResource;

    } else {

        Resource = Fcb->Header.Resource;
    }
    
    //
    //  If there are no resources assodicated with the file (case: the virtual
    //  volume file), it is OK.  No resources will be acquired on the other side
    //  as well.
    //

    if (Resource) {
        
        ExAcquireResourceSharedLite( Resource, TRUE );
    }

    if (NodeType( Fcb ) == FAT_NTC_VCB) {

        Vcb = (PVCB) Fcb;
    
    } else {

        Vcb = Fcb->Vcb;
    }
    
    try {
        
        //
        //  Make the Irp just like a regular post request and
        //  then send the Irp to the special overflow thread.
        //  After the post we will wait for the stack overflow
        //  read routine to set the event that indicates we can
        //  now release the scb resource and return.
        //

        FatPrePostIrp( IrpContext, Irp );

        //
        //  If this read is the result of a verify, we have to
        //  tell the overflow read routne to temporarily
        //  hijack the Vcb->VerifyThread field so that reads
        //  can go through.
        //

        if (Vcb->VerifyThread == KeGetCurrentThread()) {

            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ);
        }

        FsRtlPostStackOverflow( IrpContext, &Event, FatStackOverflowRead );

        //
        //  And wait for the worker thread to complete the item
        //

        KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );

    } finally {

        if (Resource) {

            ExReleaseResourceLite( Resource );
        }
    }

    return STATUS_PENDING;
}
コード例 #5
0
ファイル: fsctl.c プロジェクト: HBelusca/NasuTek-Odyssey
static NTSTATUS
VfatMount (PVFAT_IRP_CONTEXT IrpContext)
/*
 * FUNCTION: Mount the filesystem
 */
{
   PDEVICE_OBJECT DeviceObject = NULL;
   PDEVICE_EXTENSION DeviceExt = NULL;
   BOOLEAN RecognizedFS;
   NTSTATUS Status;
   PVFATFCB Fcb = NULL;
   PVFATFCB VolumeFcb = NULL;
   PVFATCCB Ccb = NULL;
   PDEVICE_OBJECT DeviceToMount;
   PVPB Vpb;
   UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
   UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
   ULONG HashTableSize;
   ULONG eocMark;
   FATINFO FatInfo;

   DPRINT("VfatMount(IrpContext %p)\n", IrpContext);

   ASSERT(IrpContext);

   if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject)
   {
      Status = STATUS_INVALID_DEVICE_REQUEST;
      goto ByeBye;
   }

   DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
   Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb;

   Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, &FatInfo);
   if (!NT_SUCCESS(Status))
   {
      goto ByeBye;
   }

   if (RecognizedFS == FALSE)
   {
      DPRINT("VFAT: Unrecognized Volume\n");
      Status = STATUS_UNRECOGNIZED_VOLUME;
      goto ByeBye;
   }

   /* Use prime numbers for the table size */
   if (FatInfo.FatType == FAT12)
   {
      HashTableSize = 4099; // 4096 = 4 * 1024
   }
   else if (FatInfo.FatType == FAT16 ||
            FatInfo.FatType == FATX16)
   {
      HashTableSize = 16411; // 16384 = 16 * 1024
   }
   else
   {
      HashTableSize = 65537; // 65536 = 64 * 1024;
   }
   HashTableSize = FCB_HASH_TABLE_SIZE;
   DPRINT("VFAT: Recognized volume\n");
   Status = IoCreateDevice(VfatGlobalData->DriverObject,
                           ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize,
                           NULL,
                           FILE_DEVICE_DISK_FILE_SYSTEM,
                           DeviceToMount->Characteristics,
                           FALSE,
                           &DeviceObject);
   if (!NT_SUCCESS(Status))
   {
      goto ByeBye;
   }

   DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
   DeviceExt = (PVOID) DeviceObject->DeviceExtension;
   RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize);
   DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)));
   DeviceExt->HashTableSize = HashTableSize;

   /* use same vpb as device disk */
   DeviceObject->Vpb = Vpb;
   DeviceToMount->Vpb = Vpb;

   Status = VfatMountDevice(DeviceExt, DeviceToMount);
   if (!NT_SUCCESS(Status))
   {
      /* FIXME: delete device object */
      goto ByeBye;
   }

   DPRINT("BytesPerSector:     %d\n", DeviceExt->FatInfo.BytesPerSector);
   DPRINT("SectorsPerCluster:  %d\n", DeviceExt->FatInfo.SectorsPerCluster);
   DPRINT("FATCount:           %d\n", DeviceExt->FatInfo.FATCount);
   DPRINT("FATSectors:         %d\n", DeviceExt->FatInfo.FATSectors);
   DPRINT("RootStart:          %d\n", DeviceExt->FatInfo.rootStart);
   DPRINT("DataStart:          %d\n", DeviceExt->FatInfo.dataStart);
   if (DeviceExt->FatInfo.FatType == FAT32)
   {
      DPRINT("RootCluster:        %d\n", DeviceExt->FatInfo.RootCluster);
   }

   switch (DeviceExt->FatInfo.FatType)
   {
      case FAT12:
         DeviceExt->GetNextCluster = FAT12GetNextCluster;
         DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
         DeviceExt->WriteCluster = FAT12WriteCluster;
         DeviceExt->CleanShutBitMask = 0;
         break;

      case FAT16:
      case FATX16:
         DeviceExt->GetNextCluster = FAT16GetNextCluster;
         DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
         DeviceExt->WriteCluster = FAT16WriteCluster;
         DeviceExt->CleanShutBitMask = 0x8000;
         break;

      case FAT32:
      case FATX32:
         DeviceExt->GetNextCluster = FAT32GetNextCluster;
         DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
         DeviceExt->WriteCluster = FAT32WriteCluster;
         DeviceExt->CleanShutBitMask = 0x80000000;
         break;
   }

   if (DeviceExt->FatInfo.FatType == FATX16
      || DeviceExt->FatInfo.FatType == FATX32)
   {
      DeviceExt->Flags |= VCB_IS_FATX;
      DeviceExt->GetNextDirEntry = FATXGetNextDirEntry;
      DeviceExt->BaseDateYear = 2000;
   }
   else
   {
      DeviceExt->GetNextDirEntry = FATGetNextDirEntry;
      DeviceExt->BaseDateYear = 1980;
   }

   DeviceExt->StorageDevice = DeviceToMount;
   DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
   DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
   DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
   DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
   DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

   DPRINT("FsDeviceObject %p\n", DeviceObject);

   /* Initialize this resource early ... it's used in VfatCleanup */
   ExInitializeResourceLite(&DeviceExt->DirResource);

   DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
   Fcb = vfatNewFCB(DeviceExt, &NameU);
   if (Fcb == NULL)
   {
      Status = STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
   }
   Ccb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
   if (Ccb == NULL)
   {
      Status =  STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
   }

   RtlZeroMemory(Ccb, sizeof (VFATCCB));
   DeviceExt->FATFileObject->FsContext = Fcb;
   DeviceExt->FATFileObject->FsContext2 = Ccb;
   DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
   DeviceExt->FATFileObject->PrivateCacheMap = NULL;
   DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb;
   Fcb->FileObject = DeviceExt->FATFileObject;

   Fcb->Flags |= FCB_IS_FAT;

   Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
   Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize;
   Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;

   CcInitializeCacheMap(DeviceExt->FATFileObject,
                        (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
                        TRUE,
                        &VfatGlobalData->CacheMgrCallbacks,
                        Fcb);

   DeviceExt->LastAvailableCluster = 2;
   ExInitializeResourceLite(&DeviceExt->FatResource);

   InitializeListHead(&DeviceExt->FcbListHead);

   VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU);
   if (VolumeFcb == NULL)
   {
      Status = STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
   }
   VolumeFcb->Flags = FCB_IS_VOLUME;
   VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
   VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
   VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
   DeviceExt->VolumeFcb = VolumeFcb;

   ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
   InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
   ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);

   /* read serial number */
   DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;

   /* read volume label */
   ReadVolumeLabel(DeviceExt,  DeviceObject->Vpb);

   /* read clean shutdown bit status */
   Status = GetNextCluster(DeviceExt, 1, &eocMark);
   if (NT_SUCCESS(Status))
   {
      if (eocMark & DeviceExt->CleanShutBitMask)
      {
         /* unset clean shutdown bit */
         eocMark &= ~DeviceExt->CleanShutBitMask;
         WriteCluster(DeviceExt, 1, eocMark);
         VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
      }
   }
   VolumeFcb->Flags |= VCB_IS_DIRTY;

   FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT);

   Status = STATUS_SUCCESS;
ByeBye:

  if (!NT_SUCCESS(Status))
  {
     // cleanup
     if (DeviceExt && DeviceExt->FATFileObject)
        ObDereferenceObject (DeviceExt->FATFileObject);
     if (Fcb)
        vfatDestroyFCB(Fcb);
     if (Ccb)
        vfatDestroyCCB(Ccb);
     if (DeviceObject)
       IoDeleteDevice(DeviceObject);
     if (VolumeFcb)
        vfatDestroyFCB(VolumeFcb);
  }
  return Status;
}
コード例 #6
0
ファイル: device.c プロジェクト: asharudeen/dokany
NTSTATUS
DokanDispatchDeviceControl(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

/*++

Routine Description:

        This device control dispatcher handles IOCTLs.

Arguments:

        DeviceObject - Context for the activity.
        Irp 		 - The device control argument block.

Return Value:

        NTSTATUS

--*/

{
  PDokanVCB vcb;
  PDokanDCB dcb;
  PIO_STACK_LOCATION irpSp;
  NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  ULONG controlCode = 0;
  ULONG outputLength = 0;
  // {DCA0E0A5-D2CA-4f0f-8416-A6414657A77A}
  // GUID dokanGUID = { 0xdca0e0a5, 0xd2ca, 0x4f0f, { 0x84, 0x16, 0xa6, 0x41,
  // 0x46, 0x57, 0xa7, 0x7a } };

  __try {
    Irp->IoStatus.Information = 0;

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    outputLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

    controlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;

    if (controlCode != IOCTL_EVENT_WAIT && controlCode != IOCTL_EVENT_INFO &&
        controlCode != IOCTL_KEEPALIVE) {

      DDbgPrint("==> DokanDispatchIoControl\n");
      DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    }

    vcb = DeviceObject->DeviceExtension;
    PrintIdType(vcb);
    if (GetIdentifierType(vcb) == DGL) {
      status = GlobalDeviceControl(DeviceObject, Irp);
      __leave;
    } else if (GetIdentifierType(vcb) == DCB) {
      status = DiskDeviceControl(DeviceObject, Irp);
      __leave;
    } else if (GetIdentifierType(vcb) != VCB) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }
    dcb = vcb->Dcb;

    switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
    case IOCTL_EVENT_WAIT:
      DDbgPrint("  IOCTL_EVENT_WAIT\n");
      status = DokanRegisterPendingIrpForEvent(DeviceObject, Irp);
      break;

    case IOCTL_EVENT_INFO:
      // DDbgPrint("  IOCTL_EVENT_INFO\n");
      status = DokanCompleteIrp(DeviceObject, Irp);
      break;

    case IOCTL_EVENT_RELEASE:
      DDbgPrint("  IOCTL_EVENT_RELEASE\n");
      status = DokanEventRelease(DeviceObject);
      break;

    case IOCTL_EVENT_WRITE:
      DDbgPrint("  IOCTL_EVENT_WRITE\n");
      status = DokanEventWrite(DeviceObject, Irp);
      break;

    case IOCTL_KEEPALIVE:
      DDbgPrint("  IOCTL_KEEPALIVE\n");
      if (dcb->Mounted) {
        ExAcquireResourceExclusiveLite(&dcb->Resource, TRUE);
        DokanUpdateTimeout(&dcb->TickCount, DOKAN_KEEPALIVE_TIMEOUT);
        ExReleaseResourceLite(&dcb->Resource);
        status = STATUS_SUCCESS;
      } else {
        DDbgPrint(" device is not mounted\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
      }
      break;

    case IOCTL_RESET_TIMEOUT:
      status = DokanResetPendingIrpTimeout(DeviceObject, Irp);
      break;

    case IOCTL_GET_ACCESS_TOKEN:
      status = DokanGetAccessToken(DeviceObject, Irp);
      break;

    default: {
      ULONG baseCode = DEVICE_TYPE_FROM_CTL_CODE(
          irpSp->Parameters.DeviceIoControl.IoControlCode);
      status = STATUS_NOT_IMPLEMENTED;
      // In case of IOCTL_STORAGE_BASE or IOCTL_DISK_BASE OR
      // FILE_DEVICE_NETWORK_FILE_SYSTEM or MOUNTDEVCONTROLTYPE ioctl type, pass
      // to DiskDeviceControl to avoid code duplication
      // TODO: probably not the best way to pass down Irp...
      if (baseCode == IOCTL_STORAGE_BASE || baseCode == IOCTL_DISK_BASE ||
          baseCode == FILE_DEVICE_NETWORK_FILE_SYSTEM ||
          baseCode == MOUNTDEVCONTROLTYPE) {
        status = DiskDeviceControl(dcb->DeviceObject, Irp);
      }

      if (status == STATUS_NOT_IMPLEMENTED) {
        PrintUnknownDeviceIoctlCode(
            irpSp->Parameters.DeviceIoControl.IoControlCode);
      }
    } break;
    } // switch IoControlCode

  } __finally {

    if (status != STATUS_PENDING) {
      DokanCompleteIrpRequest(Irp, status, Irp->IoStatus.Information);
    }

    if (controlCode != IOCTL_EVENT_WAIT && controlCode != IOCTL_EVENT_INFO &&
        controlCode != IOCTL_KEEPALIVE) {

      DokanPrintNTStatus(status);
      DDbgPrint("<== DokanDispatchIoControl\n");
    }
  }

  return status;
}
コード例 #7
0
ファイル: event.c プロジェクト: ApocalypticOctopus/dokan
// start event dispatching
NTSTATUS
DokanEventStart(
    __in PDEVICE_OBJECT DeviceObject,
    __in PIRP Irp
   )
{
	ULONG				outBufferLen;
	ULONG				inBufferLen;
	PVOID				buffer;
	PIO_STACK_LOCATION	irpSp;
	EVENT_START			eventStart;
	PEVENT_DRIVER_INFO	driverInfo;
	PDOKAN_GLOBAL		dokanGlobal;
	PDokanDCB			dcb;
	NTSTATUS			status;
	DEVICE_TYPE			deviceType;
	ULONG				deviceCharacteristics;
	WCHAR				baseGuidString[64];
	GUID				baseGuid = DOKAN_BASE_GUID;
	UNICODE_STRING		unicodeGuid;
	ULONG				deviceNamePos;
	

	DDbgPrint("==> DokanEventStart\n");

	dokanGlobal = DeviceObject->DeviceExtension;
	if (GetIdentifierType(dokanGlobal) != DGL) {
		return STATUS_INVALID_PARAMETER;
	}

	irpSp = IoGetCurrentIrpStackLocation(Irp);

	outBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
	inBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;

	if (outBufferLen != sizeof(EVENT_DRIVER_INFO) ||
		inBufferLen != sizeof(EVENT_START)) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	RtlCopyMemory(&eventStart, Irp->AssociatedIrp.SystemBuffer, sizeof(EVENT_START));
	driverInfo = Irp->AssociatedIrp.SystemBuffer;

	if (eventStart.UserVersion != DOKAN_DRIVER_VERSION) {
		driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;
		driverInfo->Status = DOKAN_START_FAILED;
		Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);
		return STATUS_SUCCESS;
	}

	deviceCharacteristics = FILE_DEVICE_IS_MOUNTED;

	switch (eventStart.DeviceType) {
	case DOKAN_DISK_FILE_SYSTEM:
		deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
		break;
	case DOKAN_NETWORK_FILE_SYSTEM:
		deviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
		deviceCharacteristics |= FILE_REMOTE_DEVICE;
		break;
	default:
		DDbgPrint("  Unknown device type: %d\n", eventStart.DeviceType);
		deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
	}

	if (eventStart.Flags & DOKAN_EVENT_REMOVABLE) {
		DDbgPrint("  DeviceCharacteristics |= FILE_REMOVABLE_MEDIA\n");
		deviceCharacteristics |= FILE_REMOVABLE_MEDIA;
	}

	baseGuid.Data2 = (USHORT)(dokanGlobal->MountId & 0xFFFF) ^ baseGuid.Data2;
	baseGuid.Data3 = (USHORT)(dokanGlobal->MountId >> 16) ^ baseGuid.Data3;

	status = RtlStringFromGUID(&baseGuid, &unicodeGuid);
	if (!NT_SUCCESS(status)) {
		return status;
	}
	RtlZeroMemory(baseGuidString, sizeof(baseGuidString));
	RtlStringCchCopyW(baseGuidString, sizeof(baseGuidString) / sizeof(WCHAR), unicodeGuid.Buffer);
	RtlFreeUnicodeString(&unicodeGuid);

	InterlockedIncrement(&dokanGlobal->MountId);

	KeEnterCriticalRegion();
	ExAcquireResourceExclusiveLite(&dokanGlobal->Resource, TRUE);

	status = DokanCreateDiskDevice(
				DeviceObject->DriverObject,
				dokanGlobal->MountId,
				baseGuidString,
				dokanGlobal,
				deviceType,
				deviceCharacteristics,
				&dcb);

	if (!NT_SUCCESS(status)) {
		ExReleaseResourceLite(&dokanGlobal->Resource);
		KeLeaveCriticalRegion();
		return status;
	}

	DDbgPrint("  MountId:%d\n", dcb->MountId);
	driverInfo->DeviceNumber = dokanGlobal->MountId;
	driverInfo->MountId = dokanGlobal->MountId;
	driverInfo->Status = DOKAN_MOUNTED;
	driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;

	// SymbolicName is \\DosDevices\\Global\\Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
	// Finds the last '\' and copy into DeviceName.
	// DeviceName is \Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
	deviceNamePos = dcb->SymbolicLinkName->Length / sizeof(WCHAR) - 1;
	for (; dcb->SymbolicLinkName->Buffer[deviceNamePos] != L'\\'; --deviceNamePos)
		;
	RtlStringCchCopyW(driverInfo->DeviceName,
			sizeof(driverInfo->DeviceName) / sizeof(WCHAR),
			&(dcb->SymbolicLinkName->Buffer[deviceNamePos]));

	DDbgPrint("  DeviceName:%ws\n", driverInfo->DeviceName);
	DokanUpdateTimeout(&dcb->TickCount, DOKAN_KEEPALIVE_TIMEOUT);

	dcb->UseAltStream = 0;
	if (eventStart.Flags & DOKAN_EVENT_ALTERNATIVE_STREAM_ON) {
		DDbgPrint("  ALT_STREAM_ON\n");
		dcb->UseAltStream = 1;
	}
	dcb->UseKeepAlive = 0;
	if (eventStart.Flags & DOKAN_EVENT_KEEP_ALIVE_ON) {
		DDbgPrint("  KEEP_ALIVE_ON\n");
		dcb->UseKeepAlive = 1;
	}
	dcb->Mounted = 1;

	DokanStartEventNotificationThread(dcb);
	DokanStartCheckThread(dcb);

	ExReleaseResourceLite(&dokanGlobal->Resource);
	KeLeaveCriticalRegion();

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);

	DDbgPrint("<== DokanEventStart\n");

	return Irp->IoStatus.Status;
}
コード例 #8
0
ファイル: volume.c プロジェクト: HBelusca/NasuTek-Odyssey
/*
 * @implemented
 */
VOID
NTAPI
IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
{
    PLIST_ENTRY FsList = NULL;
    PAGED_CODE();

    /* Acquire the FS lock */
    KeEnterCriticalRegion();
    ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);

    /* Check what kind of FS this is */
    if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM)
    {
        /* Use the disk list */
        FsList = &IopDiskFileSystemQueueHead;
    }
    else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
    {
        /* Use the network device list */
        FsList = &IopNetworkFileSystemQueueHead;
    }
    else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
    {
        /* Use the CD-ROM list */
        FsList = &IopCdRomFileSystemQueueHead;
    }
    else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM)
    {
        /* Use the tape list */
        FsList = &IopTapeFileSystemQueueHead;
    }

    /* Make sure that we have a valid list */
    if (FsList)
    {
        /* Check if we should insert it at the top or bottom of the list */
        if (DeviceObject->Flags & DO_LOW_PRIORITY_FILESYSTEM)
        {
            /* At the bottom */
            InsertTailList(FsList->Blink, &DeviceObject->Queue.ListEntry);
        }
        else
        {
            /* On top */
            InsertHeadList(FsList, &DeviceObject->Queue.ListEntry);
        }
    }

    /* Update operations counter */
    IopFsRegistrationOps++;

    /* Clear the initializing flag */
    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    /* Notify file systems of the addition */
    IopNotifyFileSystemChange(DeviceObject, TRUE);

    /* Release the FS Lock */
    ExReleaseResourceLite(&IopDatabaseResource);
    KeLeaveCriticalRegion();

    /* Ensure driver won't be unloaded */
    IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
}
コード例 #9
0
ファイル: flush.c プロジェクト: Moteesh/reactos
NTSTATUS
VfatFlushVolume(
    PDEVICE_EXTENSION DeviceExt,
    PVFATFCB VolumeFcb)
{
    PLIST_ENTRY ListEntry;
    PVFATFCB Fcb;
    NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
    PIRP Irp;
    KEVENT Event;
    IO_STATUS_BLOCK IoStatusBlock;

    DPRINT("VfatFlushVolume(DeviceExt %p, VolumeFcb %p)\n", DeviceExt, VolumeFcb);

    ASSERT(VolumeFcb == DeviceExt->VolumeFcb);

    ListEntry = DeviceExt->FcbListHead.Flink;
    while (ListEntry != &DeviceExt->FcbListHead)
    {
        Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
        ListEntry = ListEntry->Flink;
        if (!vfatFCBIsDirectory(Fcb))
        {
            ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
            Status = VfatFlushFile(DeviceExt, Fcb);
            ExReleaseResourceLite (&Fcb->MainResource);
            if (!NT_SUCCESS(Status))
            {
                DPRINT1("VfatFlushFile failed, status = %x\n", Status);
                ReturnStatus = Status;
            }
        }
        /* FIXME: Stop flushing if this is a removable media and the media was removed */
    }

    ListEntry = DeviceExt->FcbListHead.Flink;
    while (ListEntry != &DeviceExt->FcbListHead)
    {
        Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
        ListEntry = ListEntry->Flink;
        if (vfatFCBIsDirectory(Fcb))
        {
            ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
            Status = VfatFlushFile(DeviceExt, Fcb);
            ExReleaseResourceLite (&Fcb->MainResource);
            if (!NT_SUCCESS(Status))
            {
                DPRINT1("VfatFlushFile failed, status = %x\n", Status);
                ReturnStatus = Status;
            }
        }
        /* FIXME: Stop flushing if this is a removable media and the media was removed */
    }

    Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext;

    ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
    Status = VfatFlushFile(DeviceExt, Fcb);
    ExReleaseResourceLite(&DeviceExt->FatResource);

    /* Prepare an IRP to flush device buffers */
    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
                                       DeviceExt->StorageDevice,
                                       NULL, 0, NULL, &Event,
                                       &IoStatusBlock);
    if (Irp != NULL)
    {
        KeInitializeEvent(&Event, NotificationEvent, FALSE);

        Status = IoCallDriver(DeviceExt->StorageDevice, Irp);
        if (Status == STATUS_PENDING)
        {
            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
            Status = IoStatusBlock.Status;
        }

        /* Ignore device not supporting flush operation */
        if (Status == STATUS_INVALID_DEVICE_REQUEST)
        {
            DPRINT1("Flush not supported, ignored\n");
            Status = STATUS_SUCCESS;

        }
    }
    else
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
    }

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("VfatFlushFile failed, status = %x\n", Status);
        ReturnStatus = Status;
    }

    return ReturnStatus;
}
コード例 #10
0
ファイル: volume.c プロジェクト: HBelusca/NasuTek-Odyssey
/*
 * @implemented
 */
NTSTATUS
NTAPI
IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
                               IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine)
{
    PFS_CHANGE_NOTIFY_ENTRY Entry;
    PAGED_CODE();

    /* Acquire the list lock */
    KeEnterCriticalRegion();
    ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);

    /* Check if that driver is already registered (successive calls)
     * See MSDN note: http://msdn.microsoft.com/en-us/library/ff548499%28v=vs.85%29.aspx
     */
    if (!IsListEmpty(&IopFsNotifyChangeQueueHead))
    {
        Entry = CONTAINING_RECORD(IopFsNotifyChangeQueueHead.Blink,
                                  FS_CHANGE_NOTIFY_ENTRY,
                                  FsChangeNotifyList);

        if (Entry->DriverObject == DriverObject &&
            Entry->FSDNotificationProc == DriverNotificationRoutine)
        {
            /* Release the lock */
            ExReleaseResourceLite(&IopDatabaseResource);

            return STATUS_DEVICE_ALREADY_ATTACHED;
        }
    }

    /* Allocate a notification entry */
    Entry = ExAllocatePoolWithTag(PagedPool,
                                  sizeof(FS_CHANGE_NOTIFY_ENTRY),
                                  TAG_FS_CHANGE_NOTIFY);
    if (!Entry)
    {
        /* Release the lock */
        ExReleaseResourceLite(&IopDatabaseResource);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Save the driver object and notification routine */
    Entry->DriverObject = DriverObject;
    Entry->FSDNotificationProc = DriverNotificationRoutine;

    /* Insert it into the notification list */
    InsertTailList(&IopFsNotifyChangeQueueHead, &Entry->FsChangeNotifyList);

    /* Start notifying all already present FS */
    IopNotifyAlreadyRegisteredFileSystems(&IopNetworkFileSystemQueueHead, DriverNotificationRoutine, FALSE);
    IopNotifyAlreadyRegisteredFileSystems(&IopCdRomFileSystemQueueHead, DriverNotificationRoutine, TRUE);
    IopNotifyAlreadyRegisteredFileSystems(&IopDiskFileSystemQueueHead, DriverNotificationRoutine, TRUE);
    IopNotifyAlreadyRegisteredFileSystems(&IopTapeFileSystemQueueHead, DriverNotificationRoutine, TRUE);

    /* Release the lock */
    ExReleaseResourceLite(&IopDatabaseResource);
    KeLeaveCriticalRegion();

    /* Reference the driver */
    ObReferenceObject(DriverObject);
    return STATUS_SUCCESS;
}
コード例 #11
0
ファイル: volume.c プロジェクト: HBelusca/NasuTek-Odyssey
/*
 * @implemented
 */
NTSTATUS
NTAPI
IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
               IN BOOLEAN AllowRawMount,
               IN BOOLEAN DeviceIsLocked,
               IN BOOLEAN Alertable,
               OUT PVPB *Vpb)
{
    KEVENT Event;
    NTSTATUS Status;
    IO_STATUS_BLOCK IoStatusBlock;
    PIRP Irp;
    PIO_STACK_LOCATION StackPtr;
    PLIST_ENTRY FsList, ListEntry;
    LIST_ENTRY LocalList;
    PDEVICE_OBJECT AttachedDeviceObject = DeviceObject;
    PDEVICE_OBJECT FileSystemDeviceObject, ParentFsDeviceObject;
    ULONG FsStackOverhead, RegistrationOps;
    PAGED_CODE();

    /* Check if the device isn't already locked */
    if (!DeviceIsLocked)
    {
        /* Lock it ourselves */
        Status = KeWaitForSingleObject(&DeviceObject->DeviceLock,
                                       Executive,
                                       KeGetPreviousMode(),
                                       Alertable,
                                       NULL);
        if ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC))
        {
            /* Don't mount if we were interrupted */
            return Status;
        }
    }

    /* Acquire the FS Lock*/
    KeEnterCriticalRegion();
    ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);

    /* Make sure we weren't already mounted */
    if (!(DeviceObject->Vpb->Flags & (VPB_MOUNTED | VPB_REMOVE_PENDING)))
    {
        /* Initialize the event to wait on */
        KeInitializeEvent(&Event, NotificationEvent, FALSE);

        /* Remove the verify flag and get the actual device to mount */
        DeviceObject->Flags &= ~DO_VERIFY_VOLUME;
        while (AttachedDeviceObject->AttachedDevice)
        {
            /* Get the next one */
            AttachedDeviceObject = AttachedDeviceObject->AttachedDevice;
        }

        /* Reference it */
        ObReferenceObject(AttachedDeviceObject);

        /* For a mount operation, this can only be a Disk, CD-ROM or tape */
        if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) ||
            (DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK))
        {
            /* Use the disk list */
            FsList = &IopDiskFileSystemQueueHead;
        }
        else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM)
        {
            /* Use the CD-ROM list */
            FsList = &IopCdRomFileSystemQueueHead;
        }
        else
        {
            /* It's gotta be a tape... */
            FsList = &IopTapeFileSystemQueueHead;
        }

        /* Now loop the fs list until one of the file systems accepts us */
        Status = STATUS_UNSUCCESSFUL;
        ListEntry = FsList->Flink;
        while ((ListEntry != FsList) && !(NT_SUCCESS(Status)))
        {
            /*
             * If we're not allowed to mount this volume and this is our last
             * (but not only) chance to mount it...
             */
            if (!(AllowRawMount) &&
                (ListEntry->Flink == FsList) &&
                (ListEntry != FsList->Flink))
            {
                /* Then fail this mount request */
                break;
            }

            /*
             * Also check if this is a raw mount and there are other file
             * systems on the list.
             */
            if ((DeviceObject->Vpb->Flags & VPB_RAW_MOUNT) &&
                (ListEntry->Flink != FsList))
            {
                /* Then skip this entry */
                continue;
            }

            /* Get the Device Object for this FS */
            FileSystemDeviceObject = CONTAINING_RECORD(ListEntry,
                                                       DEVICE_OBJECT,
                                                       Queue.ListEntry);
            ParentFsDeviceObject = FileSystemDeviceObject;

            /*
             * If this file system device is attached to some other device,
             * then we must make sure to increase the stack size for the IRP.
             * The default is +1, for the FS device itself.
             */
            FsStackOverhead = 1;
            while (FileSystemDeviceObject->AttachedDevice)
            {
                /* Get the next attached device and increase overhead */
                FileSystemDeviceObject = FileSystemDeviceObject->
                                         AttachedDevice;
                FsStackOverhead++;
            }

            /* Clear the event */
            KeClearEvent(&Event);

            /* Allocate the IRP */
            Irp = IoAllocateIrp(AttachedDeviceObject->StackSize +
                                (UCHAR)FsStackOverhead,
                                TRUE);
            if (!Irp)
            {
                /* Fail */
                Status =  STATUS_INSUFFICIENT_RESOURCES;
                break;
            }

            /* Setup the IRP */
            Irp->UserIosb = &IoStatusBlock;
            Irp->UserEvent = &Event;
            Irp->Tail.Overlay.Thread = PsGetCurrentThread();
            Irp->Flags = IRP_MOUNT_COMPLETION | IRP_SYNCHRONOUS_PAGING_IO;
            Irp->RequestorMode = KernelMode;

            /* Get the I/O Stack location and set it up */
            StackPtr = IoGetNextIrpStackLocation(Irp);
            StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
            StackPtr->MinorFunction = IRP_MN_MOUNT_VOLUME;
            StackPtr->Flags = AllowRawMount;
            StackPtr->Parameters.MountVolume.Vpb = DeviceObject->Vpb;
            StackPtr->Parameters.MountVolume.DeviceObject =
                AttachedDeviceObject;

            /* Save registration operations */
            RegistrationOps = IopFsRegistrationOps;

            /* Release locks */
            IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
            ExReleaseResourceLite(&IopDatabaseResource);

            /* Call the driver */
            Status = IoCallDriver(FileSystemDeviceObject, Irp);
            if (Status == STATUS_PENDING)
            {
                /* Wait on it */
                KeWaitForSingleObject(&Event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      NULL);
                Status = IoStatusBlock.Status;
            }

            ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
            IopInterlockedDecrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);

            /* Check if mounting was successful */
            if (NT_SUCCESS(Status))
            {
                /* Mount the VPB */
                *Vpb = IopMountInitializeVpb(DeviceObject,
                                             AttachedDeviceObject,
                                             (DeviceObject->Vpb->Flags &
                                              VPB_RAW_MOUNT));
            }
            else
            {
                /* Check if we failed because of the user */
                if ((IoIsErrorUserInduced(Status)) &&
                    (IoStatusBlock.Information == 1))
                {
                    /* Break out and fail */
                    break;
                }

                /* If there were registration operations in the meanwhile */
                if (RegistrationOps != IopFsRegistrationOps)
                {
                    /* We need to setup a local list to pickup where we left */
                    LocalList.Flink = FsList->Flink;
                    ListEntry = &LocalList;

                    Status = STATUS_UNRECOGNIZED_VOLUME;
                }

                /* Otherwise, check if we need to load the FS driver */
                if (Status == STATUS_FS_DRIVER_REQUIRED)
                {
                    /* We need to release the lock */
                    IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
                    ExReleaseResourceLite(&IopDatabaseResource);

                    /* Release the device lock if we're holding it */
                    if (!DeviceIsLocked)
                    {
                        KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE);
                    }

                    /* Leave critical section */
                    KeLeaveCriticalRegion();

                    /* Load the FS */
                    IopLoadFileSystemDriver(ParentFsDeviceObject);

                    /* Check if the device isn't already locked */
                    if (!DeviceIsLocked)
                    {
                        /* Lock it ourselves */
                        Status = KeWaitForSingleObject(&DeviceObject->
                                                       DeviceLock,
                                                       Executive,
                                                       KeGetPreviousMode(),
                                                       Alertable,
                                                       NULL);
                        if ((Status == STATUS_ALERTED) ||
                            (Status == STATUS_USER_APC))
                        {
                            /* Don't mount if we were interrupted */
                            ObDereferenceObject(AttachedDeviceObject);
                            return Status;
                        }
                    }

                    /* Reacquire the lock */
                    KeEnterCriticalRegion();
                    ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);

                    /* When we released the lock, make sure nobody beat us */
                    if (DeviceObject->Vpb->Flags & VPB_MOUNTED)
                    {
                        /* Someone did, break out */
                        Status = STATUS_SUCCESS;
                        break;
                    }

                    /* Start over by setting a failure */
                    Status = STATUS_UNRECOGNIZED_VOLUME;

                    /* We need to setup a local list to pickup where we left */
                    LocalList.Flink = FsList->Flink;
                    ListEntry = &LocalList;
                }

                /*
                 * Check if we failed with any other error then an unrecognized
                 * volume, and if this request doesn't allow mounting the raw
                 * file system.
                 */
                if (!(AllowRawMount) &&
                    (Status != STATUS_UNRECOGNIZED_VOLUME) &&
                    (FsRtlIsTotalDeviceFailure(Status)))
                {
                    /* Break out and give up */
                    break;
                }
            }

            /* Go to the next FS entry */
            ListEntry = ListEntry->Flink;
        }

        /* Dereference the device if we failed */
        if (!NT_SUCCESS(Status)) ObDereferenceObject(AttachedDeviceObject);
    }
    else if (DeviceObject->Vpb->Flags & VPB_REMOVE_PENDING)
    {
        /* Someone wants to remove us */
        Status = STATUS_DEVICE_DOES_NOT_EXIST;
    }
    else
    {
        /* Someone already mounted us */
        Status = STATUS_SUCCESS;
    }

    /* Release the FS lock */
    ExReleaseResourceLite(&IopDatabaseResource);
    KeLeaveCriticalRegion();

    /* Release the device lock if we're holding it */
    if (!DeviceIsLocked) KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE);

    /* Check if we failed to mount the boot partition */
    if ((!NT_SUCCESS(Status)) &&
        (DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION) &&
        ExpInitializationPhase < 2)
    {
        /* Bugcheck the system */
        KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE,
                     (ULONG_PTR)DeviceObject,
                     Status,
                     0,
                     0);
    }

    /* Return the mount status */
    return Status;
}
コード例 #12
0
ファイル: read.c プロジェクト: jrfl/ext2fsd
NTSTATUS
Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    PEXT2_VCB           Vcb = NULL;
    PEXT2_CCB           Ccb = NULL;
    PEXT2_FCBVCB        FcbOrVcb = NULL;
    PFILE_OBJECT        FileObject = NULL;

    PDEVICE_OBJECT      DeviceObject = NULL;

    PIRP                Irp = NULL;
    PIO_STACK_LOCATION  IoStackLocation = NULL;

    ULONG               Length;
    LARGE_INTEGER       ByteOffset;

    BOOLEAN             PagingIo;
    BOOLEAN             Nocache;
    BOOLEAN             SynchronousIo;
    BOOLEAN             MainResourceAcquired = FALSE;

    PUCHAR              Buffer = NULL;
    EXT2_EXTENT         BlockArray;

    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;
        FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
        ASSERT(FcbOrVcb);

        if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {

            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        Irp = IrpContext->Irp;
        Irp->IoStatus.Information = 0;
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        Length = IoStackLocation->Parameters.Read.Length;
        ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;

        PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
        Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE) || (Ccb != NULL);
        SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

        if (PagingIo) {
            ASSERT(Nocache);
        }

        if (Length == 0) {
            Irp->IoStatus.Information = 0;
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
            ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
            Status = STATUS_PENDING;
            __leave;
        }

        if (ByteOffset.QuadPart >=
                Vcb->PartitionInformation.PartitionLength.QuadPart  ) {
            Irp->IoStatus.Information = 0;
            Status = STATUS_END_OF_FILE;
            __leave;
        }

        if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
            Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
        }

        /*
         *  User direct volume access
         */

        if (Ccb != NULL && !PagingIo) {

            if (!ExAcquireResourceExclusiveLite(
                        &Vcb->MainResource,
                        IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
                Status = STATUS_PENDING;
                __leave;
            }
            MainResourceAcquired = TRUE;

            if (!FlagOn(Ccb->Flags, CCB_VOLUME_DASD_PURGE)) {

                if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
                    Ext2FlushVolume(IrpContext, Vcb, FALSE);
                }

                SetFlag(Ccb->Flags, CCB_VOLUME_DASD_PURGE);
            }

            ExReleaseResourceLite(&Vcb->MainResource);
            MainResourceAcquired = FALSE;

            /* will do Nocache i/o */
        }

        /*
         *  I/O to volume StreamObject
         */

        if (!Nocache) {

            if (IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {

                CcMdlRead(
                    Vcb->Volume,
                    &ByteOffset,
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );

                Status = Irp->IoStatus.Status;

            } else {

                Buffer = Ext2GetUserBuffer(Irp);
                if (Buffer == NULL) {
                    DbgBreak();
                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }

                if (!CcCopyRead(
                            Vcb->Volume,
                            &ByteOffset,
                            Length,
                            Ext2CanIWait(),
                            Buffer,
                            &Irp->IoStatus )) {
                    Status = STATUS_PENDING;
                    __leave;
                }

                Status = Irp->IoStatus.Status;
            }

        } else {

            Length &= ~((ULONG)SECTOR_SIZE - 1);
            Status = Ext2LockUserBuffer(
                         IrpContext->Irp,
                         Length,
                         IoWriteAccess );

            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            BlockArray.Irp = NULL;
            BlockArray.Lba = ByteOffset.QuadPart;
            BlockArray.Offset = 0;
            BlockArray.Length = Length;
            BlockArray.Next = NULL;

            Status = Ext2ReadWriteBlocks(IrpContext,
                                         Vcb,
                                         &BlockArray,
                                         Length );

            Irp = IrpContext->Irp;
            if (!Irp) {
                __leave;
            }
        }

    } __finally {

        if (MainResourceAcquired) {
            ExReleaseResourceLite(&Vcb->MainResource);
        }

        if (!IrpContext->ExceptionInProgress) {

            if (Irp) {

                if (Status == STATUS_PENDING &&
                    !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) {

                    Status = Ext2LockUserBuffer(
                                 IrpContext->Irp,
                                 Length,
                                 IoWriteAccess );

                    if (NT_SUCCESS(Status)) {
                        Status = Ext2QueueRequest(IrpContext);
                    } else {
                        Ext2CompleteIrpContext(IrpContext, Status);
                    }

                } else {

                    if (NT_SUCCESS(Status)) {

                        if (!PagingIo) {

                            if (SynchronousIo) {

                                FileObject->CurrentByteOffset.QuadPart =
                                    ByteOffset.QuadPart + Irp->IoStatus.Information;
                            }

                            FileObject->Flags |= FO_FILE_FAST_IO_READ;
                        }
                    }

                    Ext2CompleteIrpContext(IrpContext, Status);;
                }

            } else {
                Ext2FreeIrpContext(IrpContext);
            }
        }
    }

    return Status;
}
コード例 #13
0
ファイル: read.c プロジェクト: jrfl/ext2fsd
NTSTATUS
Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    PEXT2_VCB           Vcb = NULL;
    PEXT2_FCB           Fcb = NULL;
    PEXT2_CCB           Ccb = NULL;
    PFILE_OBJECT        FileObject = NULL;

    PDEVICE_OBJECT      DeviceObject = NULL;

    PIRP                Irp = NULL;
    PIO_STACK_LOCATION  IoStackLocation = NULL;

    ULONG               Length;
    ULONG               ReturnedLength = 0;
    LARGE_INTEGER       ByteOffset;

    BOOLEAN             OpPostIrp = FALSE;
    BOOLEAN             PagingIo;
    BOOLEAN             Nocache;
    BOOLEAN             SynchronousIo;
    BOOLEAN             MainResourceAcquired = FALSE;
    BOOLEAN             PagingIoResourceAcquired = FALSE;

    PUCHAR              Buffer;

    __try {

        ASSERT(IrpContext);
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;
        Fcb = (PEXT2_FCB) FileObject->FsContext;
        ASSERT(Fcb);
        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
               (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        Ccb = (PEXT2_CCB) FileObject->FsContext2;

        Irp = IrpContext->Irp;
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

        Length = IoStackLocation->Parameters.Read.Length;
        ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;

        PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO);
        Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE);
        SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

        if (PagingIo) {
            ASSERT(Nocache);
        }

        DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
                       &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));

        if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ||
            IsFileDeleted(Fcb->Mcb)) {
            Status = STATUS_FILE_DELETED;
            __leave;
        }

        if (Length == 0) {
            Irp->IoStatus.Information = 0;
            Status = STATUS_SUCCESS;
            __leave;
        }

        if (Nocache &&
                (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
                 Length & (SECTOR_SIZE - 1))) {
            Status = STATUS_INVALID_PARAMETER;
            DbgBreak();
            __leave;
        }

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
            ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
            Status = STATUS_PENDING;
            DbgBreak();
            __leave;
        }

        if (!PagingIo && Nocache && (FileObject->SectionObjectPointer->DataSectionObject != NULL)) {
            CcFlushCache( FileObject->SectionObjectPointer,
                          &ByteOffset,
                          Length,
                          &Irp->IoStatus );

            if (!NT_SUCCESS(Irp->IoStatus.Status)) {
                __leave;
            }
        }

        ReturnedLength = Length;

        if (PagingIo) {

            if (!ExAcquireResourceSharedLite(
                        &Fcb->PagingIoResource,
                        IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
                Status = STATUS_PENDING;
                __leave;
            }
            PagingIoResourceAcquired = TRUE;

        } else {

            if (Nocache) {

                if (!ExAcquireResourceExclusiveLite(
                            &Fcb->MainResource,
                            IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
                    Status = STATUS_PENDING;
                    __leave;
                }
                MainResourceAcquired = TRUE;

            } else {

                if (!ExAcquireResourceSharedLite(
                            &Fcb->MainResource,
                            IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
                    Status = STATUS_PENDING;
                    __leave;
                }
                MainResourceAcquired = TRUE;
            }

            if (!FsRtlCheckLockForReadAccess(
                        &Fcb->FileLockAnchor,
                        Irp         )) {
                Status = STATUS_FILE_LOCK_CONFLICT;
                __leave;
            }
        }

        if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.FileSize.QuadPart) {
            if (ByteOffset.QuadPart >= Fcb->Header.FileSize.QuadPart) {
                Irp->IoStatus.Information = 0;
                Status = STATUS_END_OF_FILE;
                __leave;
            }
            ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
        }


        if (!IsDirectory(Fcb) && Ccb != NULL) {

            Status = FsRtlCheckOplock( &Fcb->Oplock,
                                       Irp,
                                       IrpContext,
                                       Ext2OplockComplete,
                                       Ext2LockIrp );

            if (Status != STATUS_SUCCESS) {
                OpPostIrp = TRUE;
                __leave;
            }

            //
            //  Set the flag indicating if Fast I/O is possible
            //

            Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
        }

        if (!Nocache) {

            if (IsDirectory(Fcb)) {
                __leave;
            }

            if (FileObject->PrivateCacheMap == NULL) {
                CcInitializeCacheMap(
                        FileObject,
                        (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
                        FALSE,
                        &Ext2Global->CacheManagerCallbacks,
                        Fcb );
                CcSetReadAheadGranularity(
                        FileObject,
                        READ_AHEAD_GRANULARITY );
            }

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
                CcMdlRead(
                    FileObject,
                    (&ByteOffset),
                    ReturnedLength,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );

                Status = Irp->IoStatus.Status;

            } else {

                Buffer = Ext2GetUserBuffer(Irp);
                if (Buffer == NULL) {
                    Status = STATUS_INVALID_USER_BUFFER;
                    DbgBreak();
                    __leave;
                }

                if (!CcCopyRead(FileObject, &ByteOffset, ReturnedLength,
                                Ext2CanIWait(), Buffer, &Irp->IoStatus)) {

                    if (Ext2CanIWait() || !CcCopyRead(FileObject, &ByteOffset,
                                                      ReturnedLength, TRUE,
                                                      Buffer, &Irp->IoStatus)) {
                        Status = STATUS_PENDING;
                        DbgBreak();
                        __leave;
                    }
                }
                Status = Irp->IoStatus.Status;
            }

        } else {

            ULONG   BytesRead = ReturnedLength;
            PUCHAR  SystemVA  = Ext2GetUserBuffer(IrpContext->Irp);

            if (ByteOffset.QuadPart + BytesRead > Fcb->Header.ValidDataLength.QuadPart) {

                if (ByteOffset.QuadPart >= Fcb->Header.ValidDataLength.QuadPart) {
                    if (SystemVA) {
                        SafeZeroMemory(SystemVA, Length);
                    }
                    Irp->IoStatus.Information = ReturnedLength;
                    Status = STATUS_SUCCESS;
                    __leave;
                } else {
                    BytesRead = (ULONG)(Fcb->Header.ValidDataLength.QuadPart - ByteOffset.QuadPart);
                    if (SystemVA) {
                        SafeZeroMemory(SystemVA + BytesRead, Length - BytesRead);
                    }
                }
            }

            Status = Ext2LockUserBuffer(
                         IrpContext->Irp,
                         BytesRead,
                         IoReadAccess );

            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            Status = Ext2ReadInode(
                         IrpContext,
                         Vcb,
                         Fcb->Mcb,
                         ByteOffset.QuadPart,
                         NULL,
                         BytesRead,
                         TRUE,
                         NULL );

            /* we need re-queue this request in case STATUS_CANT_WAIT
               and fail it in other failure cases  */
            if (!NT_SUCCESS(Status)) {
                __leave;
            }

            /* pended by low level device */
            if (Status == STATUS_PENDING) {
                IrpContext->Irp = Irp = NULL;
                __leave;
            }

            Irp = IrpContext->Irp;
            ASSERT(Irp);
            Status = Irp->IoStatus.Status;

            if (!NT_SUCCESS(Status)) {
                Ext2NormalizeAndRaiseStatus(IrpContext, Status);
            }
        }

        Irp->IoStatus.Information = ReturnedLength;

    } __finally {

        if (Irp) {
            if (PagingIoResourceAcquired) {
                ExReleaseResourceLite(&Fcb->PagingIoResource);
            }

            if (MainResourceAcquired) {
                ExReleaseResourceLite(&Fcb->MainResource);
            }
        }

        if (!OpPostIrp && !IrpContext->ExceptionInProgress) {

            if (Irp) {
                if ( Status == STATUS_PENDING ||
                     Status == STATUS_CANT_WAIT) {

                    Status = Ext2LockUserBuffer(
                                 IrpContext->Irp,
                                 Length,
                                 IoWriteAccess );

                    if (NT_SUCCESS(Status)) {
                        Status = Ext2QueueRequest(IrpContext);
                    } else {
                        Ext2CompleteIrpContext(IrpContext, Status);
                    }
                } else {
                    if (NT_SUCCESS(Status)) {
                        if (!PagingIo) {
                            if (SynchronousIo) {
                                FileObject->CurrentByteOffset.QuadPart =
                                    ByteOffset.QuadPart + Irp->IoStatus.Information;
                            }
                            FileObject->Flags |= FO_FILE_FAST_IO_READ;
                        }
                    }

                    Ext2CompleteIrpContext(IrpContext, Status);
                }

            } else {

                Ext2FreeIrpContext(IrpContext);
            }
        }
    }

    DEBUG(DL_IO, ("Ext2ReadFile: %wZ fetch at Off=%I64xh Len=%xh Paging=%xh Nocache=%xh Returned=%xh Status=%xh\n",
                  &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache, ReturnedLength, Status));
    return Status;

}
コード例 #14
0
ファイル: cleanup.c プロジェクト: GYGit/reactos
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdCleanup (IN PRFSD_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status = STATUS_SUCCESS;
    PRFSD_VCB       Vcb = 0;
    BOOLEAN         VcbResourceAcquired = FALSE;
    PFILE_OBJECT    FileObject;
    PRFSD_FCB       Fcb = 0;
    BOOLEAN         FcbResourceAcquired = FALSE;
    BOOLEAN         FcbPagingIoAcquired = FALSE;
    PRFSD_CCB       Ccb;
    PIRP            Irp;

    PAGED_CODE();

    _SEH2_TRY {

        ASSERT(IrpContext != NULL);
        
        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
            (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
        
        DeviceObject = IrpContext->DeviceObject;
        
        if (DeviceObject == RfsdGlobal->DeviceObject) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
        
        ASSERT(Vcb != NULL);
        
        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
            (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
        if (!ExAcquireResourceExclusiveLite(
                 &Vcb->MainResource,
                 IrpContext->IsSynchronous
                 ))  {
            Status = STATUS_PENDING;
            _SEH2_LEAVE;
        }

        VcbResourceAcquired = TRUE;
        
        FileObject = IrpContext->FileObject;
        
        Fcb = (PRFSD_FCB) FileObject->FsContext;
        
        if (!Fcb) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        if (Fcb->Identifier.Type == RFSDVCB) {
            if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
                (Vcb->LockFile == FileObject) ) {
                ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
                Vcb->LockFile = NULL;

                RfsdClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
            }

            Vcb->OpenHandleCount--;

            if (!Vcb->OpenHandleCount) {
                IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
            }

            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }
        
        ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
            (Fcb->Identifier.Size == sizeof(RFSD_FCB)));

/*
        if ( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
             !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))
*/
        {
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
            if (!ExAcquireResourceExclusiveLite(
                     &Fcb->MainResource,
                     IrpContext->IsSynchronous
                     ))
            {
                Status = STATUS_PENDING;
                _SEH2_LEAVE;
            }

            FcbResourceAcquired = TRUE;
        }
        
        Ccb = (PRFSD_CCB) FileObject->FsContext2;

        if (!Ccb) {
            Status = STATUS_SUCCESS;
            _SEH2_LEAVE;
        }

        if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
            if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
                 IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
                 !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) {
                Status = RfsdFlushFile(Fcb);
            }
            _SEH2_LEAVE;
        }
        
        ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
            (Ccb->Identifier.Size == sizeof(RFSD_CCB)));        
        Irp = IrpContext->Irp;

        Fcb->OpenHandleCount--;

        if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED )) {
            Fcb->NonCachedOpenCount--;
        }

        Vcb->OpenFileHandleCount--;

        if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE))  {
            SetFlag(Fcb->Flags, FCB_DELETE_PENDING);

            if (IsDirectory(Fcb)) {
                FsRtlNotifyFullChangeDirectory(
                                            Vcb->NotifySync,
                                            &Vcb->NotifyList,
                                            Fcb,
                                            NULL,
                                            FALSE,
                                            FALSE,
                                            0,
                                            NULL,
                                            NULL,
                                            NULL );
            }
        }

        if (IsDirectory(Fcb)) {

            FsRtlNotifyCleanup(
                Vcb->NotifySync,
                &Vcb->NotifyList,
                Ccb   );

        } else {

            //
            // Drop any byte range locks this process may have on the file.
            //

            FsRtlFastUnlockAll(
                &Fcb->FileLockAnchor,
                FileObject,
                IoGetRequestorProcess(Irp),
                NULL  );

            //
            // If there are no byte range locks owned by other processes on the
            // file the fast I/O read/write functions doesn't have to check for
            // locks so we set IsFastIoPossible to FastIoIsPossible again.
            //
            if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
                if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
                    RfsdPrint((
                        DBG_INFO, ": %-16.16s %-31s %s\n",
                        RfsdGetCurrentProcessName(),
                        "FastIoIsPossible",
                        Fcb->AnsiFileName.Buffer
                        ));

                    Fcb->Header.IsFastIoPossible = FastIoIsPossible;
                }
            }
        }

        if ( IsFlagOn( FileObject->Flags, FO_CACHE_SUPPORTED) &&
             (Fcb->NonCachedOpenCount != 0) &&
             (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) &&
             (Fcb->SectionObject.DataSectionObject != NULL)) {

            if( !IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
                !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
                CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
            }

            ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE);
            ExReleaseResourceLite(&(Fcb->PagingIoResource));

            CcPurgeCacheSection( &Fcb->SectionObject,
                                 NULL,
                                 0,
                                 FALSE );
        }

        if (Fcb->OpenHandleCount == 0) {

            if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
                //
                //  Have to delete this file...
                //

#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
                if (!ExAcquireResourceExclusiveLite(
                         &Fcb->PagingIoResource,
                         IrpContext->IsSynchronous
                         )) {
                    Status = STATUS_PENDING;
                    _SEH2_LEAVE;
                }

                FcbPagingIoAcquired = TRUE;
DbgBreak();
#if DISABLED
                Status = RfsdDeleteFile(IrpContext, Vcb, Fcb);

                if (NT_SUCCESS(Status)) {
                    if (IsDirectory(Fcb)) {
                        RfsdNotifyReportChange( IrpContext, Vcb, Fcb,
                                                FILE_NOTIFY_CHANGE_DIR_NAME,
                                                FILE_ACTION_REMOVED );
                    } else {
                        RfsdNotifyReportChange( IrpContext, Vcb, Fcb,
                                                FILE_NOTIFY_CHANGE_FILE_NAME,
                                                FILE_ACTION_REMOVED );
                    }
                }
#endif
                if (CcIsFileCached(FileObject)) {

                    CcSetFileSizes(FileObject, 
                            (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
                    SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }

                if (FcbPagingIoAcquired) {
                    ExReleaseResourceForThreadLite(
                        &Fcb->PagingIoResource,
                        ExGetCurrentResourceThread() );

                    FcbPagingIoAcquired = FALSE;
                }
            }
        }

        if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap) {
            RfsdPrint((DBG_INFO, "RfsdCleanup: CcUninitializeCacheMap is called for %s.\n",
                                  Fcb->AnsiFileName.Buffer ));

            CcUninitializeCacheMap(
                    FileObject,
                    (PLARGE_INTEGER)(&(Fcb->Header.FileSize)),
                    NULL );
        }

        if (!Fcb->OpenHandleCount) {
            IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
        }

        RfsdPrint((DBG_INFO, "RfsdCleanup: OpenCount: %u ReferCount: %u %s\n",
            Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer ));

        Status = STATUS_SUCCESS;

        if (FileObject) {
            SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
        }

    } _SEH2_FINALLY {
       
        if (FcbPagingIoAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->PagingIoResource,
                ExGetCurrentResourceThread() );
        }

        if (FcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread() );
        }
        
        if (VcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread());
        }
        
        if (!IrpContext->ExceptionInProgress) {
            if (Status == STATUS_PENDING) {
                RfsdQueueRequest(IrpContext);
            } else {
                IrpContext->Irp->IoStatus.Status = Status;
                RfsdCompleteIrpContext(IrpContext, Status);
            }
        }
    } _SEH2_END;
    
    return Status;
}
コード例 #15
0
ファイル: event.c プロジェクト: Corillian/dokany
NTSTATUS
RegisterPendingIrpMain(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp,
                       __in ULONG SerialNumber, __in PIRP_LIST IrpList,
                       __in ULONG Flags, __in ULONG CheckMount) {
  PIRP_ENTRY irpEntry;
  PIO_STACK_LOCATION irpSp;
  KIRQL oldIrql;
  PDokanVCB vcb = NULL;

  DDbgPrint("==> DokanRegisterPendingIrpMain\n");

  if (GetIdentifierType(DeviceObject->DeviceExtension) == VCB) {
    vcb = DeviceObject->DeviceExtension;
    if (CheckMount && IsUnmountPendingVcb(vcb)) {
      DDbgPrint(" device is not mounted\n");
      return STATUS_NO_SUCH_DEVICE;
    }
  }

  irpSp = IoGetCurrentIrpStackLocation(Irp);

  // Allocate a record and save all the event context.
  irpEntry = DokanAllocateIrpEntry();

  if (NULL == irpEntry) {
    DDbgPrint("  can't allocate IRP_ENTRY\n");
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  RtlZeroMemory(irpEntry, sizeof(IRP_ENTRY));

  InitializeListHead(&irpEntry->ListEntry);

  irpEntry->SerialNumber = SerialNumber;
  irpEntry->FileObject = irpSp->FileObject;
  irpEntry->Irp = Irp;
  irpEntry->IrpSp = irpSp;
  irpEntry->IrpList = IrpList;
  irpEntry->Flags = Flags;

  // Update the irp timeout for the entry
  if (vcb) {
    ExAcquireResourceExclusiveLite(&vcb->Dcb->Resource, TRUE);
    DokanUpdateTimeout(&irpEntry->TickCount, vcb->Dcb->IrpTimeout);
    ExReleaseResourceLite(&vcb->Dcb->Resource);
  } else {
    DokanUpdateTimeout(&irpEntry->TickCount, DOKAN_IRP_PENDING_TIMEOUT);
  }

  // DDbgPrint("  Lock IrpList.ListLock\n");
  ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  KeAcquireSpinLock(&IrpList->ListLock, &oldIrql);

  IoSetCancelRoutine(Irp, DokanIrpCancelRoutine);

  if (Irp->Cancel) {
    if (IoSetCancelRoutine(Irp, NULL) != NULL) {
      // DDbgPrint("  Release IrpList.ListLock %d\n", __LINE__);
      KeReleaseSpinLock(&IrpList->ListLock, oldIrql);

      DokanFreeIrpEntry(irpEntry);

      return STATUS_CANCELLED;
    }
  }

  IoMarkIrpPending(Irp);

  InsertTailList(&IrpList->ListHead, &irpEntry->ListEntry);

  irpEntry->CancelRoutineFreeMemory = FALSE;

  // save the pointer in order to be accessed by cancel routine
  Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_IRP_ENTRY] = irpEntry;

  KeSetEvent(&IrpList->NotEmpty, IO_NO_INCREMENT, FALSE);

  // DDbgPrint("  Release IrpList.ListLock\n");
  KeReleaseSpinLock(&IrpList->ListLock, oldIrql);

  DDbgPrint("<== DokanRegisterPendingIrpMain\n");
  return STATUS_PENDING;
}
コード例 #16
0
NTSTATUS
VfatRead(
    PVFAT_IRP_CONTEXT IrpContext)
{
    NTSTATUS Status;
    PVFATFCB Fcb;
    ULONG Length = 0;
    ULONG ReturnedLength = 0;
    PERESOURCE Resource = NULL;
    LARGE_INTEGER ByteOffset;
    PVOID Buffer;
    ULONG BytesPerSector;

    ASSERT(IrpContext);

    DPRINT("VfatRead(IrpContext %p)\n", IrpContext);

    ASSERT(IrpContext->DeviceObject);

    // This request is not allowed on the main device object
    if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
    {
        DPRINT("VfatRead is called with the main device object.\n");
        Status = STATUS_INVALID_DEVICE_REQUEST;
        goto ByeBye;
    }

    ASSERT(IrpContext->DeviceExt);
    ASSERT(IrpContext->FileObject);
    Fcb = IrpContext->FileObject->FsContext;
    ASSERT(Fcb);

    if (Fcb->Flags & FCB_IS_PAGE_FILE)
    {
        PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
        IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
        IoSkipCurrentIrpStackLocation(IrpContext->Irp);
        DPRINT("Read from page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart);
        Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
        VfatFreeIrpContext(IrpContext);
        return Status;
    }

    DPRINT("<%wZ>\n", &Fcb->PathNameU);

    ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset;
    Length = IrpContext->Stack->Parameters.Read.Length;
    BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;

    /* fail if file is a directory and no paged read */
    if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
    {
        Status = STATUS_INVALID_PARAMETER;
        goto ByeBye;
    }

    DPRINT("'%wZ', Offset: %u, Length %u\n", &Fcb->PathNameU, ByteOffset.u.LowPart, Length);

    if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME))
    {
       Status = STATUS_INVALID_PARAMETER;
       goto ByeBye;
    }

    if (ByteOffset.QuadPart >= Fcb->RFCB.FileSize.QuadPart)
    {
       IrpContext->Irp->IoStatus.Information = 0;
       Status = STATUS_END_OF_FILE;
       goto ByeBye;
    }

    if (IrpContext->Irp->Flags & (IRP_PAGING_IO | IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME))
    {
        if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
        {
            DPRINT("%u %u\n", ByteOffset.u.LowPart, Length);
            // non cached read must be sector aligned
            Status = STATUS_INVALID_PARAMETER;
            goto ByeBye;
        }
    }

    if (Length == 0)
    {
        IrpContext->Irp->IoStatus.Information = 0;
        Status = STATUS_SUCCESS;
        goto ByeBye;
    }

    if (Fcb->Flags & FCB_IS_VOLUME)
    {
        Resource = &IrpContext->DeviceExt->DirResource;
    }
    else if (IrpContext->Irp->Flags & IRP_PAGING_IO)
    {
        Resource = &Fcb->PagingIoResource;
    }
    else
    {
        Resource = &Fcb->MainResource;
    }

    if (!ExAcquireResourceSharedLite(Resource,
                                     IrpContext->Flags & IRPCONTEXT_CANWAIT ? TRUE : FALSE))
    {
        Resource = NULL;
        Status = STATUS_PENDING;
        goto ByeBye;
    }

    if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
        FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
    {
        if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp))
        {
            Status = STATUS_FILE_LOCK_CONFLICT;
            goto ByeBye;
        }
    }

    Buffer = VfatGetUserBuffer(IrpContext->Irp);
    if (!Buffer)
    {
        Status = STATUS_INVALID_USER_BUFFER;
        goto ByeBye;
    }

    if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) &&
        !(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME)))
    {
        // cached read
        Status = STATUS_SUCCESS;
        if (ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
        {
            Length = Fcb->RFCB.FileSize.u.LowPart - ByteOffset.u.LowPart;
            Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS;
        }

        if (IrpContext->FileObject->PrivateCacheMap == NULL)
        {
            CcInitializeCacheMap(IrpContext->FileObject,
                                 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
                                 FALSE,
                                 &(VfatGlobalData->CacheMgrCallbacks),
                                 Fcb);
        }

        if (!CcCopyRead(IrpContext->FileObject, &ByteOffset, Length,
                        (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT), Buffer,
                        &IrpContext->Irp->IoStatus))
        {
            Status = STATUS_PENDING;
            goto ByeBye;
        }

        if (!NT_SUCCESS(IrpContext->Irp->IoStatus.Status))
        {
            Status = IrpContext->Irp->IoStatus.Status;
        }
    }
    else
    {
        // non cached read
        if (ByteOffset.QuadPart + Length > ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector))
        {
            Length = (ULONG)(ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart);
        }

        Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess);
        if (!NT_SUCCESS(Status))
        {
            goto ByeBye;
        }

        Status = VfatReadFileData(IrpContext, Length, ByteOffset, &ReturnedLength);
        if (NT_SUCCESS(Status))
        {
            IrpContext->Irp->IoStatus.Information = ReturnedLength;
        }
    }

ByeBye:
    if (Resource)
    {
        ExReleaseResourceLite(Resource);
    }

    if (Status == STATUS_PENDING)
    {
        Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess);
        if (NT_SUCCESS(Status))
        {
            Status = VfatQueueRequest(IrpContext);
        }
        else
        {
            IrpContext->Irp->IoStatus.Status = Status;
            IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
            VfatFreeIrpContext(IrpContext);
        }
    }
    else
    {
        IrpContext->Irp->IoStatus.Status = Status;
        if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO &&
            !(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
            (NT_SUCCESS(Status) || Status == STATUS_END_OF_FILE))
        {
            IrpContext->FileObject->CurrentByteOffset.QuadPart =
                ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
        }

        IoCompleteRequest(IrpContext->Irp,
                          (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
        VfatFreeIrpContext(IrpContext);
    }
    DPRINT("%x\n", Status);
    return Status;
}
コード例 #17
0
ファイル: event.c プロジェクト: Corillian/dokany
// start event dispatching
NTSTATUS
DokanEventStart(__in PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) {
  ULONG outBufferLen;
  ULONG inBufferLen;
  PIO_STACK_LOCATION irpSp = NULL;
  PEVENT_START eventStart = NULL;
  PEVENT_DRIVER_INFO driverInfo = NULL;
  PDOKAN_GLOBAL dokanGlobal = NULL;
  PDokanDCB dcb = NULL;
  NTSTATUS status;
  DEVICE_TYPE deviceType;
  ULONG deviceCharacteristics = 0;
  WCHAR *baseGuidString;
  GUID baseGuid = DOKAN_BASE_GUID;
  UNICODE_STRING unicodeGuid;
  ULONG deviceNamePos;
  BOOLEAN useMountManager = FALSE;
  BOOLEAN mountGlobally = TRUE;
  BOOLEAN fileLockUserMode = FALSE;

  DDbgPrint("==> DokanEventStart\n");

  dokanGlobal = DeviceObject->DeviceExtension;
  if (GetIdentifierType(dokanGlobal) != DGL) {
    return STATUS_INVALID_PARAMETER;
  }

  irpSp = IoGetCurrentIrpStackLocation(Irp);

  outBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  inBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;

  eventStart = ExAllocatePool(sizeof(EVENT_START));
  baseGuidString = ExAllocatePool(64 * sizeof(WCHAR));

  if (outBufferLen != sizeof(EVENT_DRIVER_INFO) ||
      inBufferLen != sizeof(EVENT_START) || eventStart == NULL ||
      baseGuidString == NULL) {
    if (eventStart)
      ExFreePool(eventStart);
    if (baseGuidString)
      ExFreePool(baseGuidString);
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  RtlCopyMemory(eventStart, Irp->AssociatedIrp.SystemBuffer,
                sizeof(EVENT_START));
  driverInfo = Irp->AssociatedIrp.SystemBuffer;

  if (eventStart->UserVersion != DOKAN_DRIVER_VERSION) {
    driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;
    driverInfo->Status = DOKAN_START_FAILED;
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return STATUS_SUCCESS;
  }

  switch (eventStart->DeviceType) {
  case DOKAN_DISK_FILE_SYSTEM:
    deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
    break;
  case DOKAN_NETWORK_FILE_SYSTEM:
    deviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
    deviceCharacteristics |= FILE_REMOTE_DEVICE;
    break;
  default:
    DDbgPrint("  Unknown device type: %d\n", eventStart->DeviceType);
    deviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
  }

  if (eventStart->Flags & DOKAN_EVENT_REMOVABLE) {
    DDbgPrint("  DeviceCharacteristics |= FILE_REMOVABLE_MEDIA\n");
    deviceCharacteristics |= FILE_REMOVABLE_MEDIA;
  }

  if (eventStart->Flags & DOKAN_EVENT_WRITE_PROTECT) {
    DDbgPrint("  DeviceCharacteristics |= FILE_READ_ONLY_DEVICE\n");
    deviceCharacteristics |= FILE_READ_ONLY_DEVICE;
  }

  if (eventStart->Flags & DOKAN_EVENT_MOUNT_MANAGER) {
    DDbgPrint("  Using Mount Manager\n");
    useMountManager = TRUE;
  }

  if (eventStart->Flags & DOKAN_EVENT_CURRENT_SESSION) {
    DDbgPrint("  Mounting on current session only\n");
    mountGlobally = FALSE;
  }

  if (eventStart->Flags & DOKAN_EVENT_FILELOCK_USER_MODE) {
    DDbgPrint("  FileLock in User Mode\n");
    fileLockUserMode = TRUE;
  }

  KeEnterCriticalRegion();
  ExAcquireResourceExclusiveLite(&dokanGlobal->Resource, TRUE);

  DOKAN_CONTROL dokanControl;
  RtlZeroMemory(&dokanControl, sizeof(dokanControl));
  RtlStringCchCopyW(dokanControl.MountPoint, MAXIMUM_FILENAME_LENGTH,
                    L"\\DosDevices\\");
  if (wcslen(eventStart->MountPoint) == 1) {
    dokanControl.MountPoint[12] = towupper(eventStart->MountPoint[0]);
    dokanControl.MountPoint[13] = L':';
    dokanControl.MountPoint[14] = L'\0';
  } else {
    RtlStringCchCatW(dokanControl.MountPoint, MAXIMUM_FILENAME_LENGTH,
                     eventStart->MountPoint);
  }

  DDbgPrint("  Checking for MountPoint %ls \n", dokanControl.MountPoint);
  PMOUNT_ENTRY foundEntry = FindMountEntry(dokanGlobal, &dokanControl, FALSE);
  if (foundEntry != NULL) {
    DDbgPrint("  MountPoint exists already %ls \n", dokanControl.MountPoint);
    driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;
    driverInfo->Status = DOKAN_START_FAILED;
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);
    ExReleaseResourceLite(&dokanGlobal->Resource);
    KeLeaveCriticalRegion();
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return STATUS_SUCCESS;
  }

  baseGuid.Data2 = (USHORT)(dokanGlobal->MountId & 0xFFFF) ^ baseGuid.Data2;
  baseGuid.Data3 = (USHORT)(dokanGlobal->MountId >> 16) ^ baseGuid.Data3;

  status = RtlStringFromGUID(&baseGuid, &unicodeGuid);
  if (!NT_SUCCESS(status)) {
    ExReleaseResourceLite(&dokanGlobal->Resource);
    KeLeaveCriticalRegion();
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return status;
  }
  RtlZeroMemory(baseGuidString, 64 * sizeof(WCHAR));
  RtlStringCchCopyW(baseGuidString, 64,
                    unicodeGuid.Buffer);
  RtlFreeUnicodeString(&unicodeGuid);

  InterlockedIncrement((LONG *)&dokanGlobal->MountId);

  status = DokanCreateDiskDevice(
      DeviceObject->DriverObject, dokanGlobal->MountId, eventStart->MountPoint,
      eventStart->UNCName, baseGuidString, dokanGlobal, deviceType,
      deviceCharacteristics, mountGlobally, useMountManager, &dcb);

  if (!NT_SUCCESS(status)) {
    ExReleaseResourceLite(&dokanGlobal->Resource);
    KeLeaveCriticalRegion();
    ExFreePool(eventStart);
    ExFreePool(baseGuidString);
    return status;
  }

  dcb->FileLockInUserMode = fileLockUserMode;

  DDbgPrint("  MountId:%d\n", dcb->MountId);
  driverInfo->DeviceNumber = dokanGlobal->MountId;
  driverInfo->MountId = dokanGlobal->MountId;
  driverInfo->Status = DOKAN_MOUNTED;
  driverInfo->DriverVersion = DOKAN_DRIVER_VERSION;

  // SymbolicName is
  // \\DosDevices\\Global\\Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
  // Finds the last '\' and copy into DeviceName.
  // DeviceName is \Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9}
  deviceNamePos = dcb->SymbolicLinkName->Length / sizeof(WCHAR) - 1;
  for (; dcb->SymbolicLinkName->Buffer[deviceNamePos] != L'\\'; --deviceNamePos)
    ;
  RtlStringCchCopyW(driverInfo->DeviceName,
                    sizeof(driverInfo->DeviceName) / sizeof(WCHAR),
                    &(dcb->SymbolicLinkName->Buffer[deviceNamePos]));

  // Set the irp timeout in milliseconds
  // If the IrpTimeout is 0, we assume that the value was not changed
  dcb->IrpTimeout = DOKAN_IRP_PENDING_TIMEOUT;
  if (eventStart->IrpTimeout > 0) {
    if (eventStart->IrpTimeout > DOKAN_IRP_PENDING_TIMEOUT_RESET_MAX) {
      eventStart->IrpTimeout = DOKAN_IRP_PENDING_TIMEOUT_RESET_MAX;
    }

    if (eventStart->IrpTimeout < DOKAN_IRP_PENDING_TIMEOUT) {
      eventStart->IrpTimeout = DOKAN_IRP_PENDING_TIMEOUT;
    }
    dcb->IrpTimeout = eventStart->IrpTimeout;
  }

  DDbgPrint("  DeviceName:%ws\n", driverInfo->DeviceName);

  dcb->UseAltStream = 0;
  if (eventStart->Flags & DOKAN_EVENT_ALTERNATIVE_STREAM_ON) {
    DDbgPrint("  ALT_STREAM_ON\n");
    dcb->UseAltStream = 1;
  }

  DokanStartEventNotificationThread(dcb);

  ExReleaseResourceLite(&dokanGlobal->Resource);
  KeLeaveCriticalRegion();

  IoVerifyVolume(dcb->DeviceObject, FALSE);

  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO);

  ExFreePool(eventStart);
  ExFreePool(baseGuidString);

  DDbgPrint("<== DokanEventStart\n");

  return Irp->IoStatus.Status;
}
コード例 #18
0
NTSTATUS
VfatWrite(
    PVFAT_IRP_CONTEXT IrpContext)
{
    PVFATFCB Fcb;
    PERESOURCE Resource = NULL;
    LARGE_INTEGER ByteOffset;
    LARGE_INTEGER OldFileSize;
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG Length = 0;
    PVOID Buffer;
    ULONG BytesPerSector;

    ASSERT(IrpContext);

    DPRINT("VfatWrite(IrpContext %p)\n", IrpContext);

    ASSERT(IrpContext->DeviceObject);

    // This request is not allowed on the main device object
    if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
    {
        DPRINT("VfatWrite is called with the main device object.\n");
        Status = STATUS_INVALID_DEVICE_REQUEST;
        goto ByeBye;
    }

    ASSERT(IrpContext->DeviceExt);
    ASSERT(IrpContext->FileObject);
    Fcb = IrpContext->FileObject->FsContext;
    ASSERT(Fcb);

    if (Fcb->Flags & FCB_IS_PAGE_FILE)
    {
        PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
        IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
        IoSkipCurrentIrpStackLocation(IrpContext->Irp);
        DPRINT("Write to page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart);
        Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
        VfatFreeIrpContext(IrpContext);
        return Status;
    }

    DPRINT("<%wZ>\n", &Fcb->PathNameU);

    /* fail if file is a directory and no paged read */
    if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
    {
        Status = STATUS_INVALID_PARAMETER;
        goto ByeBye;
    }

    ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset;
    if (ByteOffset.u.LowPart == FILE_WRITE_TO_END_OF_FILE &&
        ByteOffset.u.HighPart == -1)
    {
        ByteOffset.QuadPart = Fcb->RFCB.FileSize.QuadPart;
    }
    Length = IrpContext->Stack->Parameters.Write.Length;
    BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;

    if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME))
    {
        Status = STATUS_INVALID_PARAMETER;
        goto ByeBye;
    }

    if (Fcb->Flags & (FCB_IS_FAT | FCB_IS_VOLUME) ||
        vfatDirEntryGetFirstCluster(IrpContext->DeviceExt, &Fcb->entry) == 1)
    {
        if (ByteOffset.QuadPart + Length > Fcb->RFCB.FileSize.QuadPart)
        {
            // we can't extend the FAT, the volume or the root on FAT12/FAT16
            Status = STATUS_END_OF_FILE;
            goto ByeBye;
        }
    }

    if (IrpContext->Irp->Flags & (IRP_PAGING_IO|IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME))
    {
        if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
        {
            // non cached write must be sector aligned
            Status = STATUS_INVALID_PARAMETER;
            goto ByeBye;
        }
    }

    if (Length == 0)
    {
        /* FIXME: Update last write time */
        IrpContext->Irp->IoStatus.Information = 0;
        Status = STATUS_SUCCESS;
        goto ByeBye;
    }

    if (IrpContext->Irp->Flags & IRP_PAGING_IO)
    {
        if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
        {
            Status = STATUS_INVALID_PARAMETER;
            goto ByeBye;
        }

        if (ByteOffset.u.LowPart + Length > ROUND_UP(Fcb->RFCB.AllocationSize.u.LowPart, BytesPerSector))
        {
            Length =  ROUND_UP(Fcb->RFCB.FileSize.u.LowPart, BytesPerSector) - ByteOffset.u.LowPart;
        }
    }

    if (Fcb->Flags & FCB_IS_VOLUME)
    {
        Resource = &IrpContext->DeviceExt->DirResource;
    }
    else if (IrpContext->Irp->Flags & IRP_PAGING_IO)
    {
        Resource = &Fcb->PagingIoResource;
    }
    else
    {
        Resource = &Fcb->MainResource;
    }

    if (Fcb->Flags & FCB_IS_PAGE_FILE)
    {
        if (!ExAcquireResourceSharedLite(Resource,
                                         (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
        {
            Resource = NULL;
            Status = STATUS_PENDING;
            goto ByeBye;
        }
    }
    else
    {
        if (!ExAcquireResourceExclusiveLite(Resource,
                                            (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
        {
            Resource = NULL;
            Status = STATUS_PENDING;
            goto ByeBye;
        }
    }

    if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
        FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
    {
        if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLock, IrpContext->Irp))
        {
            Status = STATUS_FILE_LOCK_CONFLICT;
            goto ByeBye;
        }
    }

    if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT) && !(Fcb->Flags & FCB_IS_VOLUME))
    {
        if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
        {
            Status = STATUS_PENDING;
            goto ByeBye;
        }
    }

    OldFileSize = Fcb->RFCB.FileSize;

    Buffer = VfatGetUserBuffer(IrpContext->Irp);
    if (!Buffer)
    {
        Status = STATUS_INVALID_USER_BUFFER;
        goto ByeBye;
    }


    if (!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)) &&
        !(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
        ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
    {
        LARGE_INTEGER AllocationSize;
        AllocationSize.QuadPart = ByteOffset.u.LowPart + Length;
        Status = VfatSetAllocationSizeInformation(IrpContext->FileObject, Fcb,
                                                  IrpContext->DeviceExt, &AllocationSize);
        if (!NT_SUCCESS (Status))
        {
            goto ByeBye;
        }
    }

    if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) &&
        !(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME)))
    {
        // cached write

        if (IrpContext->FileObject->PrivateCacheMap == NULL)
        {
            CcInitializeCacheMap(IrpContext->FileObject,
                                 (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
                                 FALSE,
                                 &VfatGlobalData->CacheMgrCallbacks,
                                 Fcb);
        }

        if (ByteOffset.QuadPart > OldFileSize.QuadPart)
        {
            CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
        }

        if (CcCopyWrite(IrpContext->FileObject, &ByteOffset, Length,
                        1 /*IrpContext->Flags & IRPCONTEXT_CANWAIT*/, Buffer))
        {
            IrpContext->Irp->IoStatus.Information = Length;
            Status = STATUS_SUCCESS;
        }
        else
        {
            Status = STATUS_UNSUCCESSFUL;
        }
    }
    else
    {
        // non cached write

        if (ByteOffset.QuadPart > OldFileSize.QuadPart)
        {
            CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
        }

        Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
        if (!NT_SUCCESS(Status))
        {
            goto ByeBye;
        }

        Status = VfatWriteFileData(IrpContext, Length, ByteOffset);
        if (NT_SUCCESS(Status))
        {
            IrpContext->Irp->IoStatus.Information = Length;
        }
    }

    if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
        !(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)))
    {
        if(!(*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
        {
            LARGE_INTEGER SystemTime;
            // set dates and times
            KeQuerySystemTime (&SystemTime);
            if (Fcb->Flags & FCB_IS_FATX_ENTRY)
            {
                FsdSystemTimeToDosDateTime(IrpContext->DeviceExt,
                                           &SystemTime, &Fcb->entry.FatX.UpdateDate,
                                           &Fcb->entry.FatX.UpdateTime);
                Fcb->entry.FatX.AccessDate = Fcb->entry.FatX.UpdateDate;
                Fcb->entry.FatX.AccessTime = Fcb->entry.FatX.UpdateTime;
            }
            else
            {
                FsdSystemTimeToDosDateTime(IrpContext->DeviceExt,
                                           &SystemTime, &Fcb->entry.Fat.UpdateDate,
                                           &Fcb->entry.Fat.UpdateTime);
                Fcb->entry.Fat.AccessDate = Fcb->entry.Fat.UpdateDate;
            }
            /* set date and times to dirty */
            Fcb->Flags |= FCB_IS_DIRTY;
        }
    }

ByeBye:
    if (Resource)
    {
        ExReleaseResourceLite(Resource);
    }

    if (Status == STATUS_PENDING)
    {
        Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
        if (NT_SUCCESS(Status))
        {
            Status = VfatQueueRequest(IrpContext);
        }
        else
        {
            IrpContext->Irp->IoStatus.Status = Status;
            IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
            VfatFreeIrpContext(IrpContext);
        }
    }
    else
    {
        IrpContext->Irp->IoStatus.Status = Status;
        if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO &&
            !(IrpContext->Irp->Flags & IRP_PAGING_IO) && NT_SUCCESS(Status))
        {
            IrpContext->FileObject->CurrentByteOffset.QuadPart =
                ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
        }

        IoCompleteRequest(IrpContext->Irp,
                          (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
        VfatFreeIrpContext(IrpContext);
    }
    DPRINT("%x\n", Status);
    return Status;
}
コード例 #19
0
ファイル: flush.c プロジェクト: Uroc327/ext2fsd
NTSTATUS
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS                Status = STATUS_SUCCESS;

    PIRP                    Irp = NULL;
    PIO_STACK_LOCATION      IrpSp = NULL;

    PEXT2_VCB               Vcb = NULL;
    PEXT2_FCB               Fcb = NULL;
    PEXT2_FCBVCB            FcbOrVcb = NULL;
    PEXT2_CCB               Ccb = NULL;
    PFILE_OBJECT            FileObject = NULL;

    PDEVICE_OBJECT          DeviceObject = NULL;

    BOOLEAN                 MainResourceAcquired = FALSE;

    __try {

        ASSERT(IrpContext);

        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;

        //
        // This request is not allowed on the main device object
        //
        if (IsExt2FsDevice(DeviceObject)) {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        ASSERT(Vcb != NULL);
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        ASSERT(IsMounted(Vcb));
        if ( IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
                IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
            Status =  STATUS_SUCCESS;
            __leave;
        }

        Irp = IrpContext->Irp;
        IrpSp = IoGetCurrentIrpStackLocation(Irp);

        FileObject = IrpContext->FileObject;
        FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
        ASSERT(FcbOrVcb != NULL);

        Ccb = (PEXT2_CCB) FileObject->FsContext2;
        if (Ccb == NULL) {
            Status =  STATUS_SUCCESS;
            __leave;
        }

        MainResourceAcquired =
            ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource,
                                           IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));

        ASSERT(MainResourceAcquired);
        DEBUG(DL_INF, ("Ext2Flush-pre:  total mcb records=%u\n",
                       FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));

        if (FcbOrVcb->Identifier.Type == EXT2VCB) {

            Ext2VerifyVcb(IrpContext, Vcb);
            Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
            if (NT_SUCCESS(Status)) {
                __leave;
            }

            Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);

            if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
                ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
            }

        } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {

            Fcb = (PEXT2_FCB)(FcbOrVcb);

            Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
            if (NT_SUCCESS(Status)) {
                if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
                    Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
                    ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
                }
            }
        }

        DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
                       FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));


    } __finally {

        if (MainResourceAcquired) {
            ExReleaseResourceLite(&FcbOrVcb->MainResource);
        }

        if (!IrpContext->ExceptionInProgress) {

            if (Vcb && Irp && IrpSp && (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))) {

                // Call the disk driver to flush the physial media.
                NTSTATUS DriverStatus;
                PIO_STACK_LOCATION NextIrpSp;

                NextIrpSp = IoGetNextIrpStackLocation(Irp);

                *NextIrpSp = *IrpSp;

                IoSetCompletionRoutine( Irp,
                                        Ext2FlushCompletionRoutine,
                                        NULL,
                                        TRUE,
                                        TRUE,
                                        TRUE );

                DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);

                Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
                         Status : DriverStatus;

                IrpContext->Irp = Irp = NULL;
            }

            Ext2CompleteIrpContext(IrpContext, Status);
        }
    }

    return Status;
}
コード例 #20
0
ファイル: moure.c プロジェクト: matt-wu/Moure
VOID MrUnlockGlobal()
{
    ExReleaseResourceLite(&g_core.mc_lock);
    KeLeaveCriticalRegion();
}
コード例 #21
0
ファイル: lockctrl.c プロジェクト: derfsubterfuge/CSE451
BOOLEAN
FatFastUnlockAllByKey (
    IN PFILE_OBJECT FileObject,
    PVOID ProcessId,
    ULONG Key,
    OUT PIO_STATUS_BLOCK IoStatus,
    IN PDEVICE_OBJECT DeviceObject
)

/*++

Routine Description:

    This is a call back routine for doing the fast unlock all by key call.

Arguments:

    FileObject - Supplies the file object used in this operation

    ProcessId - Supplies the process ID used in this operation

    Key - Supplies the key used in this operation

    Status - Receives the Status if this operation is successful

Return Value:

    BOOLEAN - TRUE if this operation completed and FALSE if caller
        needs to take the long route.

--*/

{
    BOOLEAN Results;
    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

    DebugTrace(+1, Dbg, "FatFastUnlockAllByKey\n", 0);

    IoStatus->Information = 0;

    //
    //  Decode the type of file object we're being asked to process and make sure
    //  it is only a user file open.
    //

    if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) {

        IoStatus->Status = STATUS_INVALID_PARAMETER;

        DebugTrace(-1, Dbg, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
        return TRUE;
    }

    //
    //  Acquire exclusive access to the Fcb this operation can always wait
    //

    FsRtlEnterFileSystem();

    (VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );

    try {

        //
        //  We check whether we can proceed based on the state of the file oplocks.
        //

        if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {

            try_return( Results = FALSE );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request.  The call will always succeed.
        //

        Results = TRUE;
        IoStatus->Status = FsRtlFastUnlockAllByKey( &Fcb->Specific.Fcb.FileLock,
                           FileObject,
                           ProcessId,
                           Key,
                           NULL );

        //
        //  Set the flag indicating if Fast I/O is possible
        //

        Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );

try_exit:
        NOTHING;
    }
    finally {

        DebugUnwind( FatFastUnlockAllByKey );

        //
        //  Release the Fcb, and return to our caller
        //

        ExReleaseResourceLite( (Fcb)->Header.Resource );

        FsRtlExitFileSystem();

        DebugTrace(-1, Dbg, "FatFastUnlockAllByKey -> %08lx\n", Results);
    }

    return Results;
}
コード例 #22
0
ファイル: read.c プロジェクト: Corillian/dokany
NTSTATUS
DokanDispatchRead(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

/*++

Routine Description:

        This device control dispatcher handles read IRPs.

Arguments:

        DeviceObject - Context for the activity.
        Irp          - The device control argument block.

Return Value:

        NTSTATUS

--*/
{
  PIO_STACK_LOCATION irpSp;
  PFILE_OBJECT fileObject;
  ULONG bufferLength;
  LARGE_INTEGER byteOffset;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  ULONG readLength = 0;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PVOID currentAddress = NULL;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  BOOLEAN fcbLocked = FALSE;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN isSynchronousIo = FALSE;
  BOOLEAN noCache = FALSE;

  __try {

    DDbgPrint("==> DokanRead\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    //
    //  If this is a zero length read then return SUCCESS immediately.
    //
    if (irpSp->Parameters.Read.Length == 0) {
      DDbgPrint("  Parameters.Read.Length == 0 \n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (irpSp->MinorFunction == IRP_MN_COMPLETE) {
      Irp->MdlAddress = NULL;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL && Irp->MdlAddress != NULL) {
      DDbgPrint("  Reads by File System Recognizers\n");

      currentAddress = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
      if (currentAddress == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        __leave;
      }

      // here we could return the bootsector. If we don't have one
      // the requested read lenght must be returned as requested
      readLength = irpSp->Parameters.Read.Length;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;
    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    bufferLength = irpSp->Parameters.Read.Length;
    if (irpSp->Parameters.Read.ByteOffset.LowPart ==
            FILE_USE_FILE_POINTER_POSITION &&
        irpSp->Parameters.Read.ByteOffset.HighPart == -1) {

      // irpSp->Parameters.Read.ByteOffset == NULL don't need check?

      DDbgPrint("use FileObject ByteOffset\n");

      byteOffset = fileObject->CurrentByteOffset;

    } else {
      byteOffset = irpSp->Parameters.Read.ByteOffset;
    }

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);
    DDbgPrint("  ByteCount:%lu ByteOffset:%I64d\n", bufferLength,
              byteOffset.QuadPart);

    if (bufferLength == 0) {
      status = STATUS_SUCCESS;
      readLength = 0;
      __leave;
    }

    // make a MDL for UserBuffer that can be used later on another thread
    // context
    if (Irp->MdlAddress == NULL) {
      status = DokanAllocateMdl(Irp, irpSp->Parameters.Read.Length);
      if (!NT_SUCCESS(status)) {
        __leave;
      }
    }

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) {
      DDbgPrint("   DOKAN_FILE_DIRECTORY %p\n", fcb);
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }
    if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
      isSynchronousIo = TRUE;
    }

    if (Irp->Flags & IRP_NOCACHE) {
      noCache = TRUE;
    }

    if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) &&
        (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {
      ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
      CcFlushCache(&fcb->SectionObjectPointers,
                   &irpSp->Parameters.Read.ByteOffset,
                   irpSp->Parameters.Read.Length, NULL);
      ExReleaseResourceLite(&fcb->PagingIoResource);
    }

    DokanFCBLockRO(fcb);
    fcbLocked = TRUE;
    // length of EventContext is sum of file name length and itself
    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);
    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;
    // DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

    if (isPagingIo) {
      DDbgPrint("  Paging IO\n");
      eventContext->FileFlags |= DOKAN_PAGING_IO;
    }
    if (isSynchronousIo) {
      DDbgPrint("  Synchronous IO\n");
      eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
    }

    if (noCache) {
      DDbgPrint("  Nocache\n");
      eventContext->FileFlags |= DOKAN_NOCACHE;
    }

    // offset of file to read
    eventContext->Operation.Read.ByteOffset = byteOffset;

    // buffer size for read
    // user-mode file system application can return this size
    eventContext->Operation.Read.BufferLength = irpSp->Parameters.Read.Length;

    // copy the accessed file name
    eventContext->Operation.Read.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.Read.FileName, fcb->FileName.Buffer,
                  fcb->FileName.Length);

    //
    //  We now check whether we can proceed based on the state of
    //  the file oplocks.
    //
    if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                                DokanOplockComplete, DokanPrePostIrp);

      //
      //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
      //  to service an oplock break and we need to leave now.
      //
      if (status != STATUS_SUCCESS) {
        if (status == STATUS_PENDING) {
          DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
        } else {
          DokanFreeEventContext(eventContext);
        }
        __leave;
      }

      //
      // We have to check for read access according to the current
      // state of the file locks, and set FileSize from the Fcb.
      //
      // FsRtlCheckLockForReadAccess does not block.
      if (!FsRtlCheckLockForReadAccess(&fcb->FileLock, Irp)) {
        status = STATUS_FILE_LOCK_CONFLICT;
        __leave;
      }
    }

    // register this IRP to pending IPR list and make it pending status
    status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);
  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, readLength);

    DDbgPrint("<== DokanRead\n");
  }

  return status;
}
コード例 #23
0
NTSTATUS
FatCommonRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common read routine for NtReadFile, called from both
    the Fsd, or from the Fsp if a request could not be completed without
    blocking in the Fsd.  This routine has no code where it determines
    whether it is running in the Fsd or Fsp.  Instead, its actions are
    conditionalized by the Wait input parameter, which determines whether
    it is allowed to block or not.  If a blocking condition is encountered
    with Wait == FALSE, however, the request is posted to the Fsp, who
    always calls with WAIT == TRUE.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    PVCB Vcb;
    PFCB FcbOrDcb;
    PCCB Ccb;

    VBO StartingVbo;
    ULONG ByteCount;
    ULONG RequestedByteCount;

    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;
    TYPE_OF_OPEN TypeOfOpen;

    BOOLEAN PostIrp = FALSE;
    BOOLEAN OplockPostIrp = FALSE;

    BOOLEAN FcbOrDcbAcquired = FALSE;

    BOOLEAN Wait;
    BOOLEAN PagingIo;
    BOOLEAN NonCachedIo;
    BOOLEAN SynchronousIo;

    NTSTATUS Status;

    FAT_IO_CONTEXT StackFatIoContext;

    //
    // A system buffer is only used if we have to access the
    // buffer directly from the Fsp to clear a portion or to
    // do a synchronous I/O, or a cached transfer.  It is
    // possible that our caller may have already mapped a
    // system buffer, in which case we must remember this so
    // we do not unmap it on the way out.
    //

    PVOID SystemBuffer = NULL;

    LARGE_INTEGER StartingByte;

    PAGED_CODE();

    //
    // Get current Irp stack location.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    FileObject = IrpSp->FileObject;

    //
    // Initialize the appropriate local variables.
    //

    Wait          = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    PagingIo      = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
    NonCachedIo   = BooleanFlagOn(Irp->Flags,IRP_NOCACHE);
    SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

    DebugTrace(+1, Dbg, "CommonRead\n", 0);
    DebugTrace( 0, Dbg, "  Irp                   = %8lx\n", Irp);
    DebugTrace( 0, Dbg, "  ->ByteCount           = %8lx\n", IrpSp->Parameters.Read.Length);
    DebugTrace( 0, Dbg, "  ->ByteOffset.LowPart  = %8lx\n", IrpSp->Parameters.Read.ByteOffset.LowPart);
    DebugTrace( 0, Dbg, "  ->ByteOffset.HighPart = %8lx\n", IrpSp->Parameters.Read.ByteOffset.HighPart);

    //
    //  Extract starting Vbo and offset.
    //

    StartingByte = IrpSp->Parameters.Read.ByteOffset;

    StartingVbo = StartingByte.LowPart;

    ByteCount = IrpSp->Parameters.Read.Length;
    RequestedByteCount = ByteCount;

    //
    //  Check for a null request, and return immediately
    //

    if (ByteCount == 0) {

        Irp->IoStatus.Information = 0;
        FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
        return STATUS_SUCCESS;
    }

    //
    // Extract the nature of the read from the file object, and case on it
    //

    TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &FcbOrDcb, &Ccb);

    ASSERT( Vcb != NULL );

    //
    //  Save callers who try to do cached IO to the raw volume from themselves.
    //

    if (TypeOfOpen == UserVolumeOpen) {

        NonCachedIo = TRUE;
    }

    ASSERT(!(NonCachedIo == FALSE && TypeOfOpen == VirtualVolumeFile));

    //
    // Collect interesting statistics.  The FLAG_USER_IO bit will indicate
    // what type of io we're doing in the FatNonCachedIo function.
    //

    if (PagingIo) {
        CollectReadStats(Vcb, TypeOfOpen, ByteCount);

        if (TypeOfOpen == UserFileOpen) {
            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
        } else {
            ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
        }
    }

    ASSERT(!FlagOn( IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT ));

    //
    //  Allocate if necessary and initialize a FAT_IO_CONTEXT block for
    //  all non cached Io.  For synchronous Io we use stack storage,
    //  otherwise we allocate pool.
    //

    if (NonCachedIo) {

        if (IrpContext->FatIoContext == NULL) {

            if (!Wait) {

                IrpContext->FatIoContext =
                    FsRtlAllocatePoolWithTag( NonPagedPool,
                                              sizeof(FAT_IO_CONTEXT),
                                              TAG_FAT_IO_CONTEXT );

            } else {

                IrpContext->FatIoContext = &StackFatIoContext;

                SetFlag( IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT );
            }
        }

        RtlZeroMemory( IrpContext->FatIoContext, sizeof(FAT_IO_CONTEXT) );

        if (Wait) {

            KeInitializeEvent( &IrpContext->FatIoContext->Wait.SyncEvent,
                               NotificationEvent,
                               FALSE );

        } else {

            IrpContext->FatIoContext->Wait.Async.ResourceThreadId =
                ExGetCurrentResourceThread();

            IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
                ByteCount;

            IrpContext->FatIoContext->Wait.Async.FileObject = FileObject;
        }
    }


    //
    // These two cases correspond to either a general opened volume, ie.
    // open ("a:"), or a read of the volume file (boot sector + fat(s))
    //

    if ((TypeOfOpen == VirtualVolumeFile) ||
        (TypeOfOpen == UserVolumeOpen)) {

        LBO StartingLbo;

        StartingLbo = StartingByte.QuadPart;

        DebugTrace(0, Dbg, "Type of read is User Volume or virtual volume file\n", 0);

        if (TypeOfOpen == UserVolumeOpen) {

            //
            //  Verify that the volume for this handle is still valid
            //

            //
            //  Verify that the volume for this handle is still valid, permitting
            //  operations to proceed on dismounted volumes via the handle which
            //  performed the dismount.
            //

            if (!FlagOn( Ccb->Flags, CCB_FLAG_COMPLETE_DISMOUNT | CCB_FLAG_SENT_FORMAT_UNIT )) {

                FatQuickVerifyVcb( IrpContext, Vcb );
            }

            //
            //  If the caller previously sent a format unit command, then we will allow
            //  their read/write requests to ignore the verify flag on the device, since some
            //  devices send a media change event after format unit, but we don't want to 
            //  process it yet since we're probably in the process of formatting the
            //  media.
            //

            if (FlagOn( Ccb->Flags, CCB_FLAG_SENT_FORMAT_UNIT )) {

                SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY );
            }

            if (!FlagOn( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE )) {

                (VOID)ExAcquireResourceExclusiveLite( &Vcb->Resource, TRUE );

                try {

                    //
                    //  If the volume isn't locked, flush it.
                    //

                    if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED)) {

                        FatFlushVolume( IrpContext, Vcb, Flush );
                    }

                } finally {

                    ExReleaseResourceLite( &Vcb->Resource );
                }

                SetFlag( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE );
            }

            if (!FlagOn( Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO )) {

                LBO VolumeSize;

                //
                //  Make sure we don't try to read past end of volume,
                //  reducing the byte count if necessary.
                //

                VolumeSize = (LBO) Vcb->Bpb.BytesPerSector *
                             (Vcb->Bpb.Sectors != 0 ? Vcb->Bpb.Sectors :
                                                      Vcb->Bpb.LargeSectors);

                if (StartingLbo >= VolumeSize) {
                    Irp->IoStatus.Information = 0;
                    FatCompleteRequest( IrpContext, Irp, STATUS_END_OF_FILE );
                    return STATUS_END_OF_FILE;
                }

                if (ByteCount > VolumeSize - StartingLbo) {

                    ByteCount = RequestedByteCount = (ULONG) (VolumeSize - StartingLbo);

                    //
                    //  For async reads we had set the byte count in the FatIoContext
                    //  above, so fix that here.
                    //

                    if (!Wait) {

                        IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
                            ByteCount;
                    }
                }
            }

            //
            //  For DASD we have to probe and lock the user's buffer
            //

            FatLockUserBuffer( IrpContext, Irp, IoWriteAccess, ByteCount );


        } else {
コード例 #24
0
ファイル: fileinfo.c プロジェクト: Corillian/dokany
NTSTATUS
DokanDispatchSetInformation(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {

  NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  PIO_STACK_LOCATION irpSp;
  PVOID buffer;
  PFILE_OBJECT fileObject;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  ULONG eventLength;
  PFILE_OBJECT targetFileObject;
  PEVENT_CONTEXT eventContext;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN fcbLocked = FALSE;
  PFILE_END_OF_FILE_INFORMATION pInfoEoF = NULL;

  vcb = DeviceObject->DeviceExtension;

  __try {
    DDbgPrint("==> DokanSetInformationn\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    ccb = (PDokanCCB)fileObject->FsContext2;
    ASSERT(ccb != NULL);

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    buffer = Irp->AssociatedIrp.SystemBuffer;

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    switch (irpSp->Parameters.SetFile.FileInformationClass) {
    case FileAllocationInformation:
      DDbgPrint(
          "  FileAllocationInformation %lld\n",
          ((PFILE_ALLOCATION_INFORMATION)buffer)->AllocationSize.QuadPart);
      break;
    case FileBasicInformation:
      DDbgPrint("  FileBasicInformation\n");
      break;
    case FileDispositionInformation:
      DDbgPrint("  FileDispositionInformation\n");
      break;
    case FileEndOfFileInformation:
      if ((fileObject->SectionObjectPointer != NULL) &&
          (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {

        pInfoEoF = (PFILE_END_OF_FILE_INFORMATION)buffer;

        if (!MmCanFileBeTruncated(fileObject->SectionObjectPointer,
                                  &pInfoEoF->EndOfFile)) {
          status = STATUS_USER_MAPPED_FILE;
          __leave;
        }

        if (!isPagingIo) {
          ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
          CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
          CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
          ExReleaseResourceLite(&fcb->PagingIoResource);
        }
      }
      DDbgPrint("  FileEndOfFileInformation %lld\n",
                ((PFILE_END_OF_FILE_INFORMATION)buffer)->EndOfFile.QuadPart);
      break;
    case FileLinkInformation:
      DDbgPrint("  FileLinkInformation\n");
      break;
    case FilePositionInformation: {
      PFILE_POSITION_INFORMATION posInfo;

      posInfo = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
      ASSERT(posInfo != NULL);

      DDbgPrint("  FilePositionInformation %lld\n",
                posInfo->CurrentByteOffset.QuadPart);
      fileObject->CurrentByteOffset = posInfo->CurrentByteOffset;

      status = STATUS_SUCCESS;

      __leave;
    } break;
    case FileRenameInformation:
      DDbgPrint("  FileRenameInformation\n");
      break;
    case FileValidDataLengthInformation:
      DDbgPrint("  FileValidDataLengthInformation\n");
      break;
    default:
      DDbgPrint("  unknown type:%d\n",
                irpSp->Parameters.SetFile.FileInformationClass);
      break;
    }

    //
    // when this IRP is not handled in swich case
    //

    // calcurate the size of EVENT_CONTEXT
    // it is sum of file name length and size of FileInformation
    DokanFCBLockRW(fcb);
    fcbLocked = TRUE;
    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length +
                  irpSp->Parameters.SetFile.Length;

    targetFileObject = irpSp->Parameters.SetFile.FileObject;

    if (targetFileObject) {
      DDbgPrint("  FileObject Specified %wZ\n", &(targetFileObject->FileName));
      eventLength += targetFileObject->FileName.Length;
    }

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;

    eventContext->Operation.SetFile.FileInformationClass =
        irpSp->Parameters.SetFile.FileInformationClass;

    // the size of FileInformation
    eventContext->Operation.SetFile.BufferLength =
        irpSp->Parameters.SetFile.Length;

    // the offset from begining of structure to fill FileInfo
    eventContext->Operation.SetFile.BufferOffset =
        FIELD_OFFSET(EVENT_CONTEXT, Operation.SetFile.FileName[0]) +
        fcb->FileName.Length + sizeof(WCHAR); // the last null char

    BOOLEAN isRenameOrLink = irpSp->Parameters.SetFile.FileInformationClass ==
        FileRenameInformation ||
        irpSp->Parameters.SetFile.FileInformationClass == FileLinkInformation;

    if (!isRenameOrLink) {
        // copy FileInformation
        RtlCopyMemory(
            (PCHAR)eventContext + eventContext->Operation.SetFile.BufferOffset,
            Irp->AssociatedIrp.SystemBuffer, irpSp->Parameters.SetFile.Length);
    }

    if (isRenameOrLink) {
      // We need to hanle FileRenameInformation separetly because the structure
      // of FILE_RENAME_INFORMATION
      // has HANDLE type field, which size is different in 32 bit and 64 bit
      // environment.
      // This cases problems when driver is 64 bit and user mode library is 32
      // bit.
      PFILE_RENAME_INFORMATION renameInfo =
          (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
      PDOKAN_RENAME_INFORMATION renameContext = (PDOKAN_RENAME_INFORMATION)(
          (PCHAR)eventContext + eventContext->Operation.SetFile.BufferOffset);

      // This code assumes FILE_RENAME_INFORMATION and FILE_LINK_INFORMATION
      // have
      // the same typse and fields.
      ASSERT(sizeof(FILE_RENAME_INFORMATION) == sizeof(FILE_LINK_INFORMATION));

      renameContext->ReplaceIfExists = renameInfo->ReplaceIfExists;
      renameContext->FileNameLength = renameInfo->FileNameLength;
      RtlCopyMemory(renameContext->FileName, renameInfo->FileName,
                    renameInfo->FileNameLength);

      if (targetFileObject != NULL) {
        // if Parameters.SetFile.FileObject is specified, replase
        // FILE_RENAME_INFO's file name by
        // FileObject's file name. The buffer size is already adjusted.

        DDbgPrint("  renameContext->FileNameLength %d\n",
            renameContext->FileNameLength);
        DDbgPrint("  renameContext->FileName %ws\n", renameContext->FileName);
        RtlZeroMemory(renameContext->FileName, renameContext->FileNameLength);

        PFILE_OBJECT parentFileObject = targetFileObject->RelatedFileObject;
        if (parentFileObject != NULL) {
            RtlCopyMemory(renameContext->FileName,
                parentFileObject->FileName.Buffer,
                parentFileObject->FileName.Length);

            RtlStringCchCatW(renameContext->FileName, NTSTRSAFE_MAX_CCH, L"\\");
            RtlStringCchCatW(renameContext->FileName, NTSTRSAFE_MAX_CCH, targetFileObject->FileName.Buffer);
            renameContext->FileNameLength = targetFileObject->FileName.Length + 
                parentFileObject->FileName.Length + sizeof(WCHAR);
        } else {
            RtlCopyMemory(renameContext->FileName,
                targetFileObject->FileName.Buffer,
                targetFileObject->FileName.Length);
            renameContext->FileNameLength = targetFileObject->FileName.Length;
        }
      }

      if (irpSp->Parameters.SetFile.FileInformationClass ==
          FileRenameInformation) {
        DDbgPrint("   rename: %wZ => %ls, FileCount = %u\n", fcb->FileName,
                  renameContext->FileName, (ULONG)fcb->FileCount);
      }
    }

    // copy the file name
    eventContext->Operation.SetFile.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.SetFile.FileName,
                  fcb->FileName.Buffer, fcb->FileName.Length);

    // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
    status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                              DokanOplockComplete, DokanPrePostIrp);

    //
    //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
    //  to service an oplock break and we need to leave now.
    //
    if (status != STATUS_SUCCESS) {
      if (status == STATUS_PENDING) {
        DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
      } else {
        DokanFreeEventContext(eventContext);
      }
      __leave;
    }

    // register this IRP to waiting IRP list and make it pending status
    status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, 0);

    DDbgPrint("<== DokanSetInformation\n");
  }

  return status;
}
コード例 #25
0
ファイル: fsctl.c プロジェクト: HBelusca/NasuTek-Odyssey
static NTSTATUS
VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext)
{
   PIO_STACK_LOCATION Stack;
   LARGE_INTEGER Vcn;
   PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
   PFILE_OBJECT FileObject;
   ULONG MaxExtentCount;
   PVFATFCB Fcb;
   PDEVICE_EXTENSION DeviceExt;
   ULONG FirstCluster;
   ULONG CurrentCluster;
   ULONG LastCluster;
   NTSTATUS Status;

   DPRINT("VfatGetRetrievalPointers(IrpContext %p)\n", IrpContext);

   DeviceExt = IrpContext->DeviceExt;
   FileObject = IrpContext->FileObject;
   Stack = IrpContext->Stack;
   if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STARTING_VCN_INPUT_BUFFER) ||
       Stack->Parameters.DeviceIoControl.Type3InputBuffer == NULL)
   {
      return STATUS_INVALID_PARAMETER;
   }
   if (IrpContext->Irp->UserBuffer == NULL ||
       Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER))
   {
      return STATUS_BUFFER_TOO_SMALL;
   }

   Fcb = FileObject->FsContext;

   ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);

   Vcn = ((PSTARTING_VCN_INPUT_BUFFER)Stack->Parameters.DeviceIoControl.Type3InputBuffer)->StartingVcn;
   RetrievalPointers = IrpContext->Irp->UserBuffer;

   MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(RetrievalPointers->ExtentCount) - sizeof(RetrievalPointers->StartingVcn)) / sizeof(RetrievalPointers->Extents[0]));


   if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster)
   {
      Status = STATUS_INVALID_PARAMETER;
      goto ByeBye;
   }

   CurrentCluster = FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
   Status = OffsetToCluster(DeviceExt, FirstCluster,
                            Vcn.u.LowPart * DeviceExt->FatInfo.BytesPerCluster,
                            &CurrentCluster, FALSE);
   if (!NT_SUCCESS(Status))
   {
      goto ByeBye;
   }

   RetrievalPointers->StartingVcn = Vcn;
   RetrievalPointers->ExtentCount = 0;
   RetrievalPointers->Extents[0].Lcn.u.HighPart = 0;
   RetrievalPointers->Extents[0].Lcn.u.LowPart = CurrentCluster - 2;
   LastCluster = 0;
   while (CurrentCluster != 0xffffffff && RetrievalPointers->ExtentCount < MaxExtentCount)
   {

      LastCluster = CurrentCluster;
      Status = NextCluster(DeviceExt, CurrentCluster, &CurrentCluster, FALSE);
      Vcn.QuadPart++;
      if (!NT_SUCCESS(Status))
      {
         goto ByeBye;
      }

      if (LastCluster + 1 != CurrentCluster)
      {
         RetrievalPointers->Extents[RetrievalPointers->ExtentCount].NextVcn = Vcn;
         RetrievalPointers->ExtentCount++;
         if (RetrievalPointers->ExtentCount < MaxExtentCount)
         {
            RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.HighPart = 0;
            RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.LowPart = CurrentCluster - 2;
         }
      }
   }

   IrpContext->Irp->IoStatus.Information = sizeof(RETRIEVAL_POINTERS_BUFFER) + (sizeof(RetrievalPointers->Extents[0]) * (RetrievalPointers->ExtentCount - 1));
   Status = STATUS_SUCCESS;

ByeBye:
   ExReleaseResourceLite(&Fcb->MainResource);

   return Status;
}
コード例 #26
0
ファイル: X70Fsd.c プロジェクト: wyrover/X70FSD
NTSTATUS GenerateFileName(IN PFLT_INSTANCE  Instance,
    IN PFILE_OBJECT  FileObject,
    IN PFLT_CALLBACK_DATA  CallbackData,
    IN FLT_FILE_NAME_OPTIONS  NameOptions,
    OUT PBOOLEAN  CacheFileNameInformation,
    OUT PFLT_NAME_CONTROL  FileName
) //上层的minifilter过滤驱动的名字请求进行处理
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	PFILE_OBJECT StreamObject = FileObject;
	PFLT_FILE_NAME_INFORMATION FileNameInformation = NULL;
	BOOLEAN bEncryptResource = FALSE;
	PFCB Fcb = FileObject->FsContext;
	PCCB Ccb = FileObject->FsContext2;

	FsRtlEnterFileSystem();

	try
	{
		if(IsMyFakeFcb(FileObject))
		{
			

			ExAcquireResourceSharedLite(Fcb->EncryptResource,TRUE);
			bEncryptResource = TRUE;

			if(BooleanFlagOn(Fcb->FcbState,SCB_STATE_SHADOW_CLOSE) || Ccb->StreamFileInfo.StreamObject == NULL)
			{
				try_return (Status = STATUS_FILE_DELETED);
			}
			else
			{			
				StreamObject = Ccb->StreamFileInfo.StreamObject;
			}
		}

		ClearFlag(NameOptions,FLT_FILE_NAME_REQUEST_FROM_CURRENT_PROVIDER);

		if(FlagOn(NameOptions,FLT_FILE_NAME_NORMALIZED))
		{
			ClearFlag(NameOptions,FLT_FILE_NAME_NORMALIZED);
			SetFlag(NameOptions,FLT_FILE_NAME_OPENED);
		}
		
		if (CallbackData) 
		{
			PFILE_OBJECT TemFileObject = CallbackData->Iopb->TargetFileObject;
			CallbackData->Iopb->TargetFileObject = StreamObject;

			FltSetCallbackDataDirty(CallbackData);

			Status = FltGetFileNameInformation(CallbackData,NameOptions, &FileNameInformation);
			
			CallbackData->Iopb->TargetFileObject = TemFileObject;
			FltClearCallbackDataDirty(CallbackData);
		} 
		else 
		{
			Status = FltGetFileNameInformationUnsafe(StreamObject,Instance, NameOptions, &FileNameInformation);
		}
		if(!NT_SUCCESS(Status))
		{
			try_return (Status);
		}
		Status = FltCheckAndGrowNameControl(FileName, FileNameInformation->Name.Length);

		if(!NT_SUCCESS(Status))
		{
			try_return (Status);
		}

		RtlCopyUnicodeString(&FileName->Name, &FileNameInformation->Name);

		if(FileNameInformation != NULL)
		{
			FltReleaseFileNameInformation(FileNameInformation);
		}
		Status = STATUS_SUCCESS;
try_exit: NOTHING;
	}
	finally
	{
		if(bEncryptResource)
		{
			ExReleaseResourceLite( Fcb->EncryptResource );
		}
	}
	FsRtlExitFileSystem();
	return Status;
}
コード例 #27
0
ファイル: volume.c プロジェクト: Strongc/reactos
/*
 * FUNCTION: Retrieve the specified volume information
 */
NTSTATUS
VfatQueryVolumeInformation(
    PVFAT_IRP_CONTEXT IrpContext)
{
    FS_INFORMATION_CLASS FsInformationClass;
    NTSTATUS RC = STATUS_SUCCESS;
    PVOID SystemBuffer;
    ULONG BufferLength;

    /* PRECONDITION */
    ASSERT(IrpContext);

    DPRINT("VfatQueryVolumeInformation(IrpContext %p)\n", IrpContext);

    if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
                                     BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
    {
        DPRINT1("DirResource failed!\n");
        return VfatMarkIrpContextForQueue(IrpContext);
    }

    /* INITIALIZATION */
    FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass;
    BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length;
    SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;

    DPRINT("FsInformationClass %d\n", FsInformationClass);
    DPRINT("SystemBuffer %p\n", SystemBuffer);

    switch (FsInformationClass)
    {
        case FileFsVolumeInformation:
            RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject,
                                           SystemBuffer,
                                           &BufferLength);
            break;

        case FileFsAttributeInformation:
            RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension,
                                              SystemBuffer,
                                              &BufferLength);
            break;

        case FileFsSizeInformation:
            RC = FsdGetFsSizeInformation(IrpContext->DeviceObject,
                                         SystemBuffer,
                                         &BufferLength);
            break;

        case FileFsDeviceInformation:
            RC = FsdGetFsDeviceInformation(IrpContext->DeviceObject,
                                           SystemBuffer,
                                           &BufferLength);
            break;

        case FileFsFullSizeInformation:
            RC = FsdGetFsFullSizeInformation(IrpContext->DeviceObject,
                                             SystemBuffer,
                                             &BufferLength);
            break;

        default:
            RC = STATUS_NOT_SUPPORTED;
    }

    ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);

    IrpContext->Irp->IoStatus.Information =
        IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength;

    return RC;
}
コード例 #28
0
ファイル: write.c プロジェクト: bailey27/dokany
NTSTATUS
DokanDispatchWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {
  PIO_STACK_LOCATION irpSp;
  PFILE_OBJECT fileObject;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PVOID buffer;
  BOOLEAN writeToEoF = FALSE;
  BOOLEAN isPagingIo = FALSE;
  BOOLEAN isNonCached = FALSE;
  BOOLEAN isSynchronousIo = FALSE;
  BOOLEAN fcbLocked = FALSE;

  __try {

    DDbgPrint("==> DokanWrite\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    //
    //  If this is a zero length write then return SUCCESS immediately.
    //

    if (irpSp->Parameters.Write.Length == 0) {
      DDbgPrint("  Parameters.Write.Length == 0\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_DEVICE_REQUEST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);

    if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (Irp->MdlAddress) {
      DDbgPrint("  use MdlAddress\n");
      buffer = MmGetSystemAddressForMdlNormalSafe(Irp->MdlAddress);
    } else {
      DDbgPrint("  use UserBuffer\n");
      buffer = Irp->UserBuffer;
    }

    if (buffer == NULL) {
      DDbgPrint("  buffer == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    if (irpSp->Parameters.Write.ByteOffset.LowPart ==
            FILE_WRITE_TO_END_OF_FILE &&
        irpSp->Parameters.Write.ByteOffset.HighPart == -1) {
      writeToEoF = TRUE;
    }

    if (Irp->Flags & IRP_PAGING_IO) {
      isPagingIo = TRUE;
    }

    if (Irp->Flags & IRP_NOCACHE) {
      isNonCached = TRUE;
    }

    if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
      isSynchronousIo = TRUE;
    }

    if (!isPagingIo && (fileObject->SectionObjectPointer != NULL) &&
        (fileObject->SectionObjectPointer->DataSectionObject != NULL)) {
      ExAcquireResourceExclusiveLite(&fcb->PagingIoResource, TRUE);
      CcFlushCache(&fcb->SectionObjectPointers,
                   writeToEoF ? NULL : &irpSp->Parameters.Write.ByteOffset,
                   irpSp->Parameters.Write.Length, NULL);
      CcPurgeCacheSection(&fcb->SectionObjectPointers,
                          writeToEoF ? NULL
                                     : &irpSp->Parameters.Write.ByteOffset,
                          irpSp->Parameters.Write.Length, FALSE);
      ExReleaseResourceLite(&fcb->PagingIoResource);
    }

    // Cannot write at end of the file when using paging IO
    if (writeToEoF && isPagingIo) {
      DDbgPrint("  writeToEoF & isPagingIo\n");
      Irp->IoStatus.Information = 0;
      status = STATUS_SUCCESS;
      __leave;
    }

    // the length of EventContext is sum of length to write and length of file
    // name
    DokanFCBLockRO(fcb);
    fcbLocked = TRUE;
    eventLength = sizeof(EVENT_CONTEXT) + irpSp->Parameters.Write.Length +
                  fcb->FileName.Length;

    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    // no more memory!
    if (eventContext == NULL) {
      status = STATUS_INSUFFICIENT_RESOURCES;
      __leave;
    }

    eventContext->Context = ccb->UserContext;
    // DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

    // When the length is bigger than usual event notitfication buffer,
    // saves pointer in DiverContext to copy EventContext after allocating
    // more bigger memory.
    Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = eventContext;

    if (isPagingIo) {
      DDbgPrint("  Paging IO\n");
      eventContext->FileFlags |= DOKAN_PAGING_IO;
    }
    if (isSynchronousIo) {
      DDbgPrint("  Synchronous IO\n");
      eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
    }
    if (isNonCached) {
      DDbgPrint("  Nocache\n");
      eventContext->FileFlags |= DOKAN_NOCACHE;
    }

    // offset of file to write
    eventContext->Operation.Write.ByteOffset =
        irpSp->Parameters.Write.ByteOffset;

    if (writeToEoF) {
      eventContext->FileFlags |= DOKAN_WRITE_TO_END_OF_FILE;
      DDbgPrint("  WriteOffset = end of file\n");
    }

    if (isSynchronousIo &&
        ((irpSp->Parameters.Write.ByteOffset.LowPart ==
          FILE_USE_FILE_POINTER_POSITION) &&
         (irpSp->Parameters.Write.ByteOffset.HighPart == -1))) {
      // NOTE:
      // http://msdn.microsoft.com/en-us/library/ms795960.aspx
      // Do not check IrpSp->Parameters.Write.ByteOffset.QuadPart == 0
      // Probably the document is wrong.
      eventContext->Operation.Write.ByteOffset.QuadPart =
          fileObject->CurrentByteOffset.QuadPart;
    }

    // the size of buffer to write
    eventContext->Operation.Write.BufferLength = irpSp->Parameters.Write.Length;

    // the offset from the begining of structure
    // the contents to write will be copyed to this offset
    eventContext->Operation.Write.BufferOffset =
        FIELD_OFFSET(EVENT_CONTEXT, Operation.Write.FileName[0]) +
        fcb->FileName.Length + sizeof(WCHAR); // adds last null char

    // copies the content to write to EventContext
    RtlCopyMemory((PCHAR)eventContext +
                      eventContext->Operation.Write.BufferOffset,
                  buffer, irpSp->Parameters.Write.Length);

    // copies file name
    eventContext->Operation.Write.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.Write.FileName, fcb->FileName.Buffer,
                  fcb->FileName.Length);

    // When eventlength is less than event notification buffer,
    // returns it to user-mode using pending event.
    if (eventLength <= EVENT_CONTEXT_MAX_SIZE) {

      DDbgPrint("   Offset %d:%d, Length %d\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // EventContext is no longer needed, clear it
      Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;

      //
      //  We now check whether we can proceed based on the state of
      //  the file oplocks.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
        status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext,
                                  DokanOplockComplete, DokanPrePostIrp);

        //
        //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
        //  to service an oplock break and we need to leave now.
        //
        if (status != STATUS_SUCCESS) {
          if (status == STATUS_PENDING) {
            DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
          } else {
            DokanFreeEventContext(eventContext);
          }
          __leave;
        }
      }

      // register this IRP to IRP waiting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

      // Resuests bigger memory
      // eventContext will be freed later using
      // Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT]
    } else {
      // the length at lest file name can be stored
      ULONG requestContextLength = max(
          sizeof(EVENT_CONTEXT), eventContext->Operation.Write.BufferOffset);
      PEVENT_CONTEXT requestContext =
          AllocateEventContext(vcb->Dcb, Irp, requestContextLength, ccb);

      // no more memory!
      if (requestContext == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;
        DokanFreeEventContext(eventContext);
        __leave;
      }

      DDbgPrint("   Offset %d:%d, Length %d (request)\n",
                irpSp->Parameters.Write.ByteOffset.HighPart,
                irpSp->Parameters.Write.ByteOffset.LowPart,
                irpSp->Parameters.Write.Length);

      // copies from begining of EventContext to the end of file name
      RtlCopyMemory(requestContext, eventContext,
                    eventContext->Operation.Write.BufferOffset);
      // puts actual size of RequestContext
      requestContext->Length = requestContextLength;
      // requsts enough size to copy EventContext
      requestContext->Operation.Write.RequestLength = eventLength;

      //
      //  We now check whether we can proceed based on the state of
      //  the file oplocks.
      //
      // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking.
      if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
        status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, requestContext,
                                  DokanOplockComplete, DokanPrePostIrp);

        //
        //  if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
        //  to service an oplock break and we need to leave now.
        //
        if (status != STATUS_SUCCESS) {
          if (status == STATUS_PENDING) {
            DDbgPrint("   FsRtlCheckOplock returned STATUS_PENDING\n");
          } else {
            DokanFreeEventContext(requestContext);
            Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0;
            DokanFreeEventContext(eventContext);
          }
          __leave;
        }
      }

      // regiters this IRP to IRP wainting list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, requestContext, 0);
    }

  } __finally {
    if(fcbLocked)
      DokanFCBUnlock(fcb);

    DokanCompleteIrpRequest(Irp, status, 0);

    DDbgPrint("<== DokanWrite\n");
  }

  return status;
}
コード例 #29
0
ファイル: close.c プロジェクト: Realhram/wdk81
VOID
FatFspClose (
    IN PVCB Vcb OPTIONAL
    )

/*++

Routine Description:

    This routine implements the FSP part of Close.

Arguments:

    Vcb - If present, tells us to only close file objects opened on the
        specified volume.

Return Value:

    None.

--*/

{
    PCLOSE_CONTEXT CloseContext;
    PVCB CurrentVcb = NULL;
    PVCB LastVcb = NULL;
    BOOLEAN FreeContext = FALSE;
    BOOLEAN TopLevel = FALSE;

    ULONG LoopsWithVcbHeld = 0;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "FatFspClose\n", 0);

    //
    //  Set the top level IRP for the true FSP operation.
    //
    
    if (!ARGUMENT_PRESENT( Vcb )) {
        
        IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );
        TopLevel = TRUE;
    }

    while ((CloseContext = FatRemoveClose(Vcb, LastVcb)) != NULL) {

        //
        //  If we are in the FSP (i.e. Vcb == NULL), then try to keep ahead of
        //  creates by doing several closes with one acquisition of the Vcb.
        //
        //  Note that we cannot be holding the Vcb on entry to FatCommonClose
        //  if this is last close as we will try to acquire FatData, and
        //  worse the volume (and therefore the Vcb) may go away.
        //

        if (!ARGUMENT_PRESENT(Vcb)) {
             
            if (!FatData.ShutdownStarted) {

                if (CloseContext->Vcb != CurrentVcb) {

                    LoopsWithVcbHeld = 0;

                    //
                    //  Release a previously held Vcb, if any.
                    //

                    if (CurrentVcb != NULL) {

                        ExReleaseResourceLite( &CurrentVcb->Resource);
                    }

                    //
                    //  Get the new Vcb.
                    //

                    CurrentVcb = CloseContext->Vcb;
                    (VOID)ExAcquireResourceExclusiveLite( &CurrentVcb->Resource, TRUE );

                } else {

                    //
                    //  Share the resource occasionally if we seem to be finding a lot
                    //  of closes for a single volume.
                    //

                    if (++LoopsWithVcbHeld >= 20) {

                        if (ExGetSharedWaiterCount( &CurrentVcb->Resource ) +
                            ExGetExclusiveWaiterCount( &CurrentVcb->Resource )) {

                            ExReleaseResourceLite( &CurrentVcb->Resource);
                            (VOID)ExAcquireResourceExclusiveLite( &CurrentVcb->Resource, TRUE );
                        }

                        LoopsWithVcbHeld = 0;
                    }
                }

                //
                //  Now check the Open count.  We may be about to delete this volume!
                //
                //  The test below must be <= 1 because there could still be outstanding
                //  stream references on this VCB that are not counted in the OpenFileCount.
                //  For example if there are no open files OpenFileCount could be zero and we would
                //  not release the resource here.  The call to FatCommonClose() below may cause
                //  the VCB to be torn down and we will try to release memory we don't
                //  own later.
                //

                if (CurrentVcb->OpenFileCount <= 1) {
                    ExReleaseResourceLite( &CurrentVcb->Resource);
                    CurrentVcb = NULL;
                }
            //
            //  If shutdown has started while processing our list, drop the
            //  current Vcb resource.
            //

            } else if (CurrentVcb != NULL) {

                ExReleaseResourceLite( &CurrentVcb->Resource);
                CurrentVcb = NULL;
            }
        }

        LastVcb = CurrentVcb;

        //
        //  Call the common Close routine.  Protected in a try {} except {}
        //

        try {

            //
            //  The close context either is in the CCB, automatically freed,
            //  or was from pool for a metadata fileobject, CCB is NULL, and
            //  we'll need to free it.
            //

            FreeContext = CloseContext->Free;

            (VOID)FatCommonClose( CloseContext->Vcb,
                                  CloseContext->Fcb,
                                  (FreeContext ? NULL :
                                                 CONTAINING_RECORD( CloseContext, CCB, CloseContext)),
                                  CloseContext->TypeOfOpen,
                                  TRUE,
                                  TopLevel,
                                  NULL );

        } except(FatExceptionFilter( NULL, GetExceptionInformation() )) {

            //
            //  Ignore anything we expect.
            //

            NOTHING;
        }

        //
        //  Drop the context if it came from pool.
        //
        
        if (FreeContext) {

            ExFreePool( CloseContext );
        }
    }

    //
    //  Release a previously held Vcb, if any.
    //

    if (CurrentVcb != NULL) {

        ExReleaseResourceLite( &CurrentVcb->Resource);
    }

    //
    //  Clean up the top level IRP hint if we owned it.
    //
    
    if (!ARGUMENT_PRESENT( Vcb )) {
        
        IoSetTopLevelIrp( NULL );
    }
    
    //
    //  And return to our caller
    //

    DebugTrace(-1, Dbg, "FatFspClose -> NULL\n", 0);
}
コード例 #30
0
ファイル: close.c プロジェクト: JanD1943/ndas4windows
NTSTATUS
FatCommonClose (
    IN PVCB Vcb,
    IN PFCB Fcb,
    IN PCCB Ccb,
    IN TYPE_OF_OPEN TypeOfOpen,
    IN BOOLEAN Wait,
    OUT PBOOLEAN VcbDeleted OPTIONAL
    )

/*++

Routine Description:

    This is the common routine for closing a file/directory called by both
    the fsd and fsp threads.

    Close is invoked whenever the last reference to a file object is deleted.
    Cleanup is invoked when the last handle to a file object is closed, and
    is called before close.

    The function of close is to completely tear down and remove the fcb/dcb/ccb
    structures associated with the file object.

Arguments:

    Fcb - Supplies the file to process.

    Wait - If this is TRUE we are allowed to block for the Vcb, if FALSE
        then we must try to acquire the Vcb anyway.

    VcbDeleted - Returns whether the VCB was deleted by this call.

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PDCB ParentDcb;
    BOOLEAN RecursiveClose;
    BOOLEAN LocalVcbDeleted;
    IRP_CONTEXT IrpContext;

#if __NDAS_FAT_SECONDARY__

	BOOLEAN						volDoResourceAcquired = FALSE;

	BOOLEAN						send2Primary = FALSE;
	BOOLEAN						volDoCcb = FALSE;

	_U64						primaryFileHandle;
	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						volDoSessionResourceAcquired = FALSE;

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;

#endif

    PAGED_CODE();

    DebugTrace(+1, Dbg, "FatCommonClose...\n", 0);

    //
    //  Initailize the callers variable, if needed.
    //

    LocalVcbDeleted = FALSE;

    if (ARGUMENT_PRESENT( VcbDeleted )) {

        *VcbDeleted = LocalVcbDeleted;
    }

    //
    //  Special case the unopened file object
    //

    if (TypeOfOpen == UnopenedFileObject) {

        DebugTrace(0, Dbg, "Close unopened file object\n", 0);

        Status = STATUS_SUCCESS;

        DebugTrace(-1, Dbg, "FatCommonClose -> %08lx\n", Status);
        return Status;
    }

    //
    //  Set up our stack IrpContext.
    //

    RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );

    IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT;
    IrpContext.NodeByteSize = sizeof( IrpContext );
    IrpContext.MajorFunction = IRP_MJ_CLOSE;
    IrpContext.Vcb = Vcb;
    
    if (Wait) {

        SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
    }

#if __NDAS_FAT_SECONDARY__

	if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY))
		SetFlag( IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );

	if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) {

		if (!FlagOn(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT)) {

			return STATUS_PENDING;
		}

		volDoResourceAcquired = 
			SecondaryAcquireResourceSharedStarveExclusiveLite( &IrpContext, 
															   &volDo->Resource, 
															   BooleanFlagOn(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT) );

		if (volDoResourceAcquired == FALSE) {

			ASSERT( FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); // It's not always garented						continue;
			return STATUS_PENDING;							
		}
	}

	if (volDo->NetdiskEnableMode == NETDISK_SECONDARY &&
		!FlagOn(volDo->NetdiskPartitionInformation.Flags, NETDISK_PARTITION_INFORMATION_FLAG_INDIRECT)) {

		if (TypeOfOpen == VirtualVolumeFile || TypeOfOpen == DirectoryFile) {

			SetFlag( IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		}
	}

#endif

    //
    //  Acquire exclusive access to the Vcb and enqueue the irp if we didn't
    //  get access.
    //
#if __NDAS_FAT_SECONDARY__

	if (!(FlagOn(IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT) ?  
		  ExAcquireResourceExclusiveLite( &Vcb->SecondaryResource, Wait ) : ExAcquireResourceExclusiveLite( &Vcb->Resource, Wait ))) {

		if (volDoResourceAcquired) {

			ASSERT( ExIsResourceAcquiredSharedLite(&volDo->Resource) );
			SecondaryReleaseResourceLite( NULL, &volDo->Resource );
		}

        return STATUS_PENDING;
    }

#else

    if (!ExAcquireResourceExclusiveLite( &Vcb->Resource, Wait )) {

        return STATUS_PENDING;
    }

#endif

    //
    //  The following test makes sure that we don't blow away an Fcb if we
    //  are trying to do a Supersede/Overwrite open above us.  This test
    //  does not apply for the EA file.
    //

    if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS) &&
        Vcb->EaFcb != Fcb) {

#if __NDAS_FAT_SECONDARY__

	 	if (FlagOn(IrpContext.NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT))  
			ExReleaseResourceLite( &Vcb->SecondaryResource );
		else
			ExReleaseResourceLite( &Vcb->Resource );

		if (volDoResourceAcquired) {

			ASSERT( ExIsResourceAcquiredSharedLite(&volDo->Resource) );
			SecondaryReleaseResourceLite( NULL, &volDo->Resource );
		}

#else
        ExReleaseResourceLite( &Vcb->Resource );
#endif

        return STATUS_PENDING;
    }

    //
    //  Setting the following flag prevents recursive closes of directory file
    //  objects, which are handled in a special case loop.
    //

    if ( FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS) ) {

        RecursiveClose = TRUE;

    } else {

        SetFlag(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
        RecursiveClose = FALSE;

        //
        //  Since we are at the top of the close chain, we need to add
        //  a reference to the VCB.  This will keep it from going away
        //  on us until we are ready to check for a dismount below.
        //

        Vcb->OpenFileCount += 1;
    }

    try {

        //
        //  Case on the type of open that we are trying to close.
        //

        switch (TypeOfOpen) {

        case VirtualVolumeFile:

            DebugTrace(0, Dbg, "Close VirtualVolumeFile\n", 0);

            //
            //  Remove this internal, residual open from the count.
            //

            InterlockedDecrement( &(Vcb->InternalOpenCount) );
            InterlockedDecrement( &(Vcb->ResidualOpenCount) );

            try_return( Status = STATUS_SUCCESS );
            break;

        case UserVolumeOpen:

            DebugTrace(0, Dbg, "Close UserVolumeOpen\n", 0);

#if __NDAS_FAT_SECONDARY__

			if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) {

				volDoCcb = TRUE;

				if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

					if ( FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) )
						Fcb->CorruptedCcbCloseCount --;

					send2Primary = FALSE;
			
				} else
					send2Primary = TRUE;
				
				primaryFileHandle = Ccb->PrimaryFileHandle;

				ExAcquireFastMutex( &volDo->Secondary->RecoveryCcbQMutex );
				RemoveEntryList( &Ccb->ListEntry );
				ExReleaseFastMutex( &volDo->Secondary->RecoveryCcbQMutex );

				InitializeListHead( &Ccb->ListEntry );

				Ccb->FileObject = NULL;
				if (Ccb->Buffer)
					ExFreePool( Ccb->Buffer );

				Ccb->FileObject = NULL;

				InterlockedDecrement( &Vcb->SecondaryOpenFileCount );
			
			} else {

				Vcb->DirectAccessOpenCount -= 1;
				Vcb->OpenFileCount -= 1;
				if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }
			}

			if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_OPEN_BY_PRIMARY_SESSION)) {
				
				InterlockedDecrement( &Vcb->PrimaryOpenFileCount );					
			}

			FatDeleteCcb( &IrpContext, &Ccb );

			if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) {

				InterlockedDecrement( &Fcb->OpenCount );
				if (Fcb->OpenCount == 0) {

					ExAcquireFastMutex( &volDo->Secondary->FcbQMutex );
					RemoveEntryList( &Fcb->ListEntry );
					InitializeListHead( &Fcb->ListEntry );
					ExReleaseFastMutex( &volDo->Secondary->FcbQMutex );

					Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
					FatDeleteFcb( &IrpContext, &Fcb );
					Secondary_Dereference( volDo->Secondary );
				}
			
			} else {

				try_return( Status = STATUS_SUCCESS );
			}
#else
            Vcb->DirectAccessOpenCount -= 1;
            Vcb->OpenFileCount -= 1;
            if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }

            FatDeleteCcb( &IrpContext, &Ccb );

            try_return( Status = STATUS_SUCCESS );
#endif

            break;

        case EaFile:

            DebugTrace(0, Dbg, "Close EaFile\n", 0);

            //
            //  Remove this internal, residual open from the count.
            //

            InterlockedDecrement( &(Vcb->InternalOpenCount) );
            InterlockedDecrement( &(Vcb->ResidualOpenCount) );

            try_return( Status = STATUS_SUCCESS );
            break;

        case DirectoryFile:

            DebugTrace(0, Dbg, "Close DirectoryFile\n", 0);

            InterlockedDecrement( &Fcb->Specific.Dcb.DirectoryFileOpenCount );

            //
            //  Remove this internal open from the count.
            //

            InterlockedDecrement( &(Vcb->InternalOpenCount) );

            //
            //  If this is the root directory, it is a residual open
            //  as well.
            //

            if (NodeType( Fcb ) == FAT_NTC_ROOT_DCB) {

                InterlockedDecrement( &(Vcb->ResidualOpenCount) );
            }

            //
            //  If this is a recursive close, just return here.
            //

            if ( RecursiveClose ) {

                try_return( Status = STATUS_SUCCESS );

            } else {

                break;
            }

        case UserDirectoryOpen:
        case UserFileOpen:

            DebugTrace(0, Dbg, "Close UserFileOpen/UserDirectoryOpen\n", 0);

            //
            //  Uninitialize the cache map if we no longer need to use it
            //

            if ((NodeType(Fcb) == FAT_NTC_DCB) &&
                IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) &&
                (Fcb->OpenCount == 1) &&
                (Fcb->Specific.Dcb.DirectoryFile != NULL)) {

                PFILE_OBJECT DirectoryFileObject = Fcb->Specific.Dcb.DirectoryFile;

                DebugTrace(0, Dbg, "Uninitialize the stream file object\n", 0);

                CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );

                //
                //  Dereference the directory file.  This may cause a close
                //  Irp to be processed, so we need to do this before we destory
                //  the Fcb.
                //

                Fcb->Specific.Dcb.DirectoryFile = NULL;
                ObDereferenceObject( DirectoryFileObject );
            }

#if __NDAS_FAT__
			if (TypeOfOpen == UserFileOpen) {

				ExAcquireFastMutex( &Fcb->NonPaged->CcbQMutex );
				Ccb->FileObject = NULL;
				Ccb->Fcb = NULL;
				RemoveEntryList( &Ccb->FcbListEntry );
				InitializeListHead( &Ccb->FcbListEntry );
				ExReleaseFastMutex( &Fcb->NonPaged->CcbQMutex );
			}
#endif

            Fcb->OpenCount -= 1;

#if __NDAS_FAT_SECONDARY__

			if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) {

				volDoCcb = TRUE;

				if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

					if ( FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) )
						Fcb->CorruptedCcbCloseCount --;

					send2Primary = FALSE;
			
				} else
					send2Primary = TRUE;
				
				primaryFileHandle = Ccb->PrimaryFileHandle;

				ExAcquireFastMutex( &volDo->Secondary->RecoveryCcbQMutex );
				RemoveEntryList( &Ccb->ListEntry );
				ExReleaseFastMutex( &volDo->Secondary->RecoveryCcbQMutex );

				InitializeListHead( &Ccb->ListEntry );

				Ccb->FileObject = NULL;
				if (Ccb->Buffer)
					ExFreePool( Ccb->Buffer );

				InterlockedDecrement( &Vcb->SecondaryOpenFileCount );

				Ccb->FileObject = NULL;
			
			} else {

				Vcb->OpenFileCount -= 1;
				if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }
			}

			if (FlagOn(Ccb->NdasFatFlags, ND_FAT_CCB_FLAG_OPEN_BY_PRIMARY_SESSION)) {

				InterlockedDecrement( &Vcb->PrimaryOpenFileCount );					
			}

			FatDeleteCcb( &IrpContext, &Ccb );

			if (Fcb && FlagOn(Fcb->NdasFatFlags, ND_FAT_FCB_FLAG_SECONDARY)) {

				if (Fcb->OpenCount == 0) {

					ExAcquireFastMutex( &volDo->Secondary->FcbQMutex );
					RemoveEntryList( &Fcb->ListEntry );
					InitializeListHead( &Fcb->ListEntry );
					ExReleaseFastMutex( &volDo->Secondary->FcbQMutex );

					Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
					FatDeleteFcb( &IrpContext, &Fcb );
					Secondary_Dereference( volDo->Secondary );
				}			
			} 
#else
			
            Fcb->OpenCount -= 1;
            Vcb->OpenFileCount -= 1;
            if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }

            FatDeleteCcb( &IrpContext, &Ccb );

#endif

            break;

        default:

            FatBugCheck( TypeOfOpen, 0, 0 );
        }

#if __NDAS_FAT_SECONDARY__

		if (send2Primary) {
		
			Status = STATUS_SUCCESS;

			volDoSessionResourceAcquired 
				= SecondaryAcquireResourceExclusiveLite( &IrpContext, 
														 &volDo->SessionResource, 
														 BooleanFlagOn(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT) );

			if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) || 
				FlagOn(volDo->Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {

				Status = STATUS_SUCCESS;
				leave;
			}

			secondaryRequest = AllocateWinxpSecondaryRequest( volDo->Secondary, IRP_MJ_CLOSE, 0 );

			if (secondaryRequest == NULL) {
	
				ASSERT( FALSE );
				leave;
			}

			ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;

			INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_CLOSE, 0 );

			ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
			ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );
				
			//ndfsWinxpRequestHeader->IrpTag   = (_U32)Fcb;
			ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_CLOSE;
			ndfsWinxpRequestHeader->IrpMinorFunction = 0;

			ndfsWinxpRequestHeader->FileHandle = primaryFileHandle;

			ndfsWinxpRequestHeader->IrpFlags   = 0;
			ndfsWinxpRequestHeader->IrpSpFlags = 0;

			secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
			QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

			timeOut.QuadPart = -NDASFAT_TIME_OUT;
			Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
			
			KeClearEvent( &secondaryRequest->CompleteEvent );

			if (Status != STATUS_SUCCESS) {

				ASSERT( NDASFAT_BUG );
			}
		
			if (secondaryRequest->ExecuteStatus == STATUS_SUCCESS) {

				ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
				ASSERT( ndfsWinxpReplytHeader->Status == STATUS_SUCCESS );
				leave;
			}

			ASSERT( secondaryRequest->ExecuteStatus != STATUS_SUCCESS );
		}

		if (volDoCcb == TRUE) {

			Status = STATUS_SUCCESS;
			leave;
		}

#endif

        //
        //  At this point we've cleaned up any on-disk structure that needs
        //  to be done, and we can now update the in-memory structures.
        //  Now if this is an unreferenced FCB or if it is
        //  an unreferenced DCB (not the root) then we can remove
        //  the fcb and set our ParentDcb to non null.
        //

        if (((NodeType(Fcb) == FAT_NTC_FCB) &&
             (Fcb->OpenCount == 0))

                ||

             ((NodeType(Fcb) == FAT_NTC_DCB) &&
              (IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) &&
              (Fcb->OpenCount == 0) &&
              (Fcb->Specific.Dcb.DirectoryFileOpenCount == 0))) {

            ParentDcb = Fcb->ParentDcb;

            SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );

            FatDeleteFcb( &IrpContext, &Fcb );

            //
            //  Uninitialize our parent's cache map if we no longer need
            //  to use it.
            //

            while ((NodeType(ParentDcb) == FAT_NTC_DCB) &&
                   IsListEmpty(&ParentDcb->Specific.Dcb.ParentDcbQueue) &&
                   (ParentDcb->OpenCount == 0) &&
                   (ParentDcb->Specific.Dcb.DirectoryFile != NULL)) {

                PFILE_OBJECT DirectoryFileObject;

                DirectoryFileObject = ParentDcb->Specific.Dcb.DirectoryFile;

                DebugTrace(0, Dbg, "Uninitialize our parent Stream Cache Map\n", 0);

                CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );

                ParentDcb->Specific.Dcb.DirectoryFile = NULL;

                ObDereferenceObject( DirectoryFileObject );

                //
                //  Now, if the ObDereferenceObject() caused the final close
                //  to come in, then blow away the Fcb and continue up,
                //  otherwise wait for Mm to to dereference its file objects
                //  and stop here..
                //

                if ( ParentDcb->Specific.Dcb.DirectoryFileOpenCount == 0) {

                    PDCB CurrentDcb;

                    CurrentDcb = ParentDcb;
                    ParentDcb = CurrentDcb->ParentDcb;

                    SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );

                    FatDeleteFcb( &IrpContext, &CurrentDcb );

                } else {

                    break;
                }
            }
        }

        Status = STATUS_SUCCESS;

    try_exit: NOTHING;
    } finally {

        DebugUnwind( FatCommonClose );

#if __NDAS_FAT_SECONDARY__

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );

		if (volDoSessionResourceAcquired) {

			SecondaryReleaseResourceLite( &IrpContext, &volDo->SessionResource );		
		}

		if (volDoResourceAcquired) {

			ASSERT( ExIsResourceAcquiredSharedLite(&volDo->Resource) );
			SecondaryReleaseResourceLite( NULL, &volDo->Resource );
		}

#endif

        //
        //  We are done processing the close.  If we are the top of the close
        //  chain, see if the VCB can go away.  We have biased the open count by
        //  one, so we need to take that into account.
        //

        if (!RecursiveClose) {

            //
            //  See if there is only one open left.  If so, it is ours.  We only want
            //  to check for a dismount if a dismount is not already in progress.
            //  We also only do this if the caller can handle the VCB going away.
            //  This is determined by whether they passed in the VcbDeleted argument.
            //

            if (Vcb->OpenFileCount == 1 &&
                !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS )
                && ARGUMENT_PRESENT( VcbDeleted )) {

                //
                //  We need the global lock, which must be acquired before the
                //  VCB.  Since we already have the VCB, we have to drop and
                //  reaquire here.  Note that we always want to wait from this
                //  point on.  Note that the VCB cannot go away, since we have
                //  biased the open file count.
                //

                FatReleaseVcb( &IrpContext,
                               Vcb );

                SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );

                FatAcquireExclusiveGlobal( &IrpContext );

                FatAcquireExclusiveVcb( &IrpContext,
                                        Vcb );

                //
                //  We have our locks in the correct order.  Remove our
                //  extra open and check for a dismount.  Note that if
                //  something changed while we dropped the lock, it will
                //  not matter, since the dismount code does the correct
                //  checks to make sure the volume can really go away.
                //

                Vcb->OpenFileCount -= 1;

                LocalVcbDeleted = FatCheckForDismount( &IrpContext,
                                                       Vcb,
                                                       FALSE );

                FatReleaseGlobal( &IrpContext );

                //
                //  Let the caller know what happened, if they want this information.
                //

                if (ARGUMENT_PRESENT( VcbDeleted )) {

                    *VcbDeleted = LocalVcbDeleted;
                }

            } else {

                //
                //  The volume cannot go away now.  Just remove our extra reference.
                //

                Vcb->OpenFileCount -= 1;
            }

            //
            //  If the VCB is still around, clear our recursion flag.
            //

            if (!LocalVcbDeleted) {

                ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS );
            }
        }

        //
        //  Only release the VCB if it did not go away.
        //

        if (!LocalVcbDeleted) {

            FatReleaseVcb( &IrpContext, Vcb );
        }

        DebugTrace(-1, Dbg, "FatCommonClose -> %08lx\n", Status);
    }

    return Status;
}