示例#1
0
文件: close.c 项目: MaMic/dokany
NTSTATUS
DokanDispatchClose(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

/*++

Routine Description:

        This device control dispatcher handles create & close IRPs.

Arguments:

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

Return Value:

        NTSTATUS

--*/
{
  PDokanVCB vcb;
  PIO_STACK_LOCATION irpSp;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  PFILE_OBJECT fileObject;
  PDokanCCB ccb;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;
  PDokanFCB fcb;

  __try {

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

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

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

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

    vcb = DeviceObject->DeviceExtension;

    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {

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

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

        DDbgPrint("   Free CCB:%p\n", ccb);
        DokanFreeCCB(ccb);

        DokanFreeFCB(fcb);
      }

      status = STATUS_SUCCESS;
      __leave;
    }

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

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

    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;
    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

    if (eventContext == NULL) {
      // status = STATUS_INSUFFICIENT_RESOURCES;
      DDbgPrint("   eventContext == NULL\n");
      DDbgPrint("   Free CCB:%p\n", ccb);
      DokanFreeCCB(ccb);
      DokanFreeFCB(fcb);
      status = STATUS_SUCCESS;
      __leave;
    }

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

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

    DDbgPrint("   Free CCB:%p\n", ccb);
    DokanFreeCCB(ccb);

    DokanFreeFCB(fcb);

    // Close can not be pending status
    // don't register this IRP
    // status = DokanRegisterPendingIrp(DeviceObject, Irp,
    // eventContext->SerialNumber, 0);

    // inform it to user-mode
    DokanEventNotification(&vcb->Dcb->NotifyEvent, eventContext);

    status = STATUS_SUCCESS;

  } __finally {

    DokanCompleteIrpRequest(Irp, status, 0);

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

  return status;
}
示例#2
0
文件: cleanup.c 项目: brillywu/dokany
NTSTATUS
DokanDispatchCleanup(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

/*++

Routine Description:

        This device control dispatcher handles Cleanup IRP.

Arguments:

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

Return Value:

        NTSTATUS

--*/
{
  PDokanVCB vcb;
  PIO_STACK_LOCATION irpSp;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  PFILE_OBJECT fileObject;
  PDokanCCB ccb = NULL;
  PDokanFCB fcb = NULL;
  PEVENT_CONTEXT eventContext;
  ULONG eventLength;

  __try {

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

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

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

    // Cleanup must be success in any case
    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_SUCCESS;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;
    if (vcb == NULL) {
      DDbgPrint("  No device extension\n");
      status = STATUS_SUCCESS;
      __leave;
    }

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

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

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

    eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;
    eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

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

    if (fileObject->SectionObjectPointer != NULL &&
        fileObject->SectionObjectPointer->DataSectionObject != NULL) {
      CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL);
      CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE);
      CcUninitializeCacheMap(fileObject, NULL, NULL);
    }
    fileObject->Flags |= FO_CLEANUP_COMPLETE;

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

    // copy the filename to EventContext from ccb
    eventContext->Operation.Cleanup.FileNameLength = fcb->FileName.Length;
    RtlCopyMemory(eventContext->Operation.Cleanup.FileName,
                  fcb->FileName.Buffer, fcb->FileName.Length);

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

  } __finally {

    DokanCompleteIrpRequest(Irp, status, 0);

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

  return status;
}
示例#3
0
文件: create.c 项目: kino-chen/dokany
NTSTATUS
DokanDispatchCreate(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)

/*++

Routine Description:

	This device control dispatcher handles create & close IRPs.

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_INVALID_PARAMETER;
	PFILE_OBJECT		fileObject;
	ULONG				info = 0;
	PEVENT_CONTEXT		eventContext;
	PFILE_OBJECT		relatedFileObject;
	PUNICODE_STRING		relatedFileName = NULL;
	ULONG				fileNameLength = 0;
	ULONG				eventLength;
	PDokanFCB			fcb;
	PDokanCCB			ccb;
	PWCHAR				fileName;
	BOOLEAN				needBackSlashAfterRelatedFile = FALSE;

	PAGED_CODE();

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

		irpSp = IoGetCurrentIrpStackLocation(Irp);

		if (irpSp->FileObject == NULL) {
			DDbgPrint("  irpSp->FileObject == NULL\n");
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		fileObject = irpSp->FileObject;
		relatedFileObject = fileObject->RelatedFileObject;

		DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
		DDbgPrint("  FileName:%wZ\n", &fileObject->FileName);

		vcb = DeviceObject->DeviceExtension;
		PrintIdType(vcb);
		if (GetIdentifierType(vcb) != VCB) {
            DDbgPrint("  IdentifierType is not vcb\n");
			status = STATUS_SUCCESS;
			__leave;
		}
		dcb = vcb->Dcb;

		DDbgPrint("  IrpSp->Flags = %d\n", irpSp->Flags);
		if (irpSp->Flags & SL_CASE_SENSITIVE) {
			DDbgPrint("  IrpSp->Flags SL_CASE_SENSITIVE\n");
		}
		if (irpSp->Flags & SL_FORCE_ACCESS_CHECK) {
			DDbgPrint("  IrpSp->Flags SL_FORCE_ACCESS_CHECK\n");
		}
		if (irpSp->Flags & SL_OPEN_PAGING_FILE) {
			DDbgPrint("  IrpSp->Flags SL_OPEN_PAGING_FILE\n");
		}
		if (irpSp->Flags & SL_OPEN_TARGET_DIRECTORY) {
			DDbgPrint("  IrpSp->Flags SL_OPEN_TARGET_DIRECTORY\n");
		}

	   if ((fileObject->FileName.Length > sizeof(WCHAR)) &&
			(fileObject->FileName.Buffer[1] == L'\\') &&
			(fileObject->FileName.Buffer[0] == L'\\')) {

			fileObject->FileName.Length -= sizeof(WCHAR);

			RtlMoveMemory(&fileObject->FileName.Buffer[0],
						&fileObject->FileName.Buffer[1],
						fileObject->FileName.Length);
	   }

		if (relatedFileObject != NULL) {
			fileObject->Vpb = relatedFileObject->Vpb;
		} else {
			fileObject->Vpb = dcb->DeviceObject->Vpb;
		}

		// Get RelatedFileObject filename.
		if (relatedFileObject != NULL) {
			// Using relatedFileObject->FileName is not safe here, use cached filename from context.
			if (relatedFileObject->FsContext2) {
				PDokanCCB relatedCcb = (PDokanCCB)relatedFileObject->FsContext2;
				if (relatedCcb->Fcb) {
					if (relatedCcb->Fcb->FileName.Length > 0 && relatedCcb->Fcb->FileName.Buffer != NULL) {
						relatedFileName = &relatedCcb->Fcb->FileName;
					}
				}
			}
		}

		if (relatedFileName == NULL && fileObject->FileName.Length == 0) {

			DDbgPrint("   request for FS device\n");

			if (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) {
				status = STATUS_NOT_A_DIRECTORY;
			} else {
				SetFileObjectForVCB(fileObject, vcb);
				info = FILE_OPENED;
				status = STATUS_SUCCESS;
			}
			__leave;
		}

	   if (fileObject->FileName.Length > sizeof(WCHAR) &&
		   fileObject->FileName.Buffer[fileObject->FileName.Length/sizeof(WCHAR)-1] == L'\\') {
			fileObject->FileName.Length -= sizeof(WCHAR);
	   }

   		fileNameLength = fileObject->FileName.Length;
		if (relatedFileName != NULL) {
			fileNameLength += relatedFileName->Length;

			if (fileObject->FileName.Length > 0 &&
				fileObject->FileName.Buffer[0] == '\\') {
				DDbgPrint("  when RelatedFileObject is specified, the file name should be relative path\n");
				status = STATUS_OBJECT_NAME_INVALID;
				__leave;
			}
			if (relatedFileName->Length > 0 &&
				relatedFileName->Buffer[relatedFileName->Length/sizeof(WCHAR)-1] != '\\') {
				needBackSlashAfterRelatedFile = TRUE;
				fileNameLength += sizeof(WCHAR);
			}
		}

		// don't open file like stream
		if (!dcb->UseAltStream &&
			DokanUnicodeStringChar(&fileObject->FileName, L':') != -1) {
			DDbgPrint("    alternate stream\n");
			status = STATUS_INVALID_PARAMETER;
			info = 0;
			__leave;
		}
			
		// this memory is freed by DokanGetFCB if needed
		// "+ sizeof(WCHAR)" is for the last NULL character
		fileName = ExAllocatePool(fileNameLength + sizeof(WCHAR));
		if (fileName == NULL) {
            DDbgPrint("    Can't allocatePool for fileName\n");
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		RtlZeroMemory(fileName, fileNameLength + sizeof(WCHAR));

		if (relatedFileName != NULL) {
			DDbgPrint("  RelatedFileName:%wZ\n", relatedFileName);

			// copy the file name of related file object
			RtlCopyMemory(fileName,
				relatedFileName->Buffer,
				relatedFileName->Length);

			if (needBackSlashAfterRelatedFile) {
				((PWCHAR)fileName)[relatedFileName->Length/sizeof(WCHAR)] = '\\';
			}
			// copy the file name of fileObject
			RtlCopyMemory((PCHAR)fileName +
				relatedFileName->Length +
							(needBackSlashAfterRelatedFile? sizeof(WCHAR) : 0),
							fileObject->FileName.Buffer,
							fileObject->FileName.Length);

		} else {
			// if related file object is not specifed, copy the file name of file object
			RtlCopyMemory(fileName,
							fileObject->FileName.Buffer,
							fileObject->FileName.Length);
		}

		fcb = DokanGetFCB(vcb, fileName, fileNameLength);
		if (fcb == NULL) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		if (irpSp->Flags & SL_OPEN_PAGING_FILE) {
			fcb->AdvancedFCBHeader.Flags2 |= FSRTL_FLAG2_IS_PAGING_FILE;
			fcb->AdvancedFCBHeader.Flags2 &= ~FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS;
		}

		ccb = DokanAllocateCCB(dcb, fcb);
		if (ccb == NULL) {
            DDbgPrint("    Was not able to allocate CCB\n");
			DokanFreeFCB(fcb); // FileName is freed here
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		//remember FILE_DELETE_ON_CLOSE so than the file can be deleted in close for windows 8
		if (irpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE) {
			fcb->Flags |= DOKAN_DELETE_ON_CLOSE;
			DDbgPrint("  FILE_DELETE_ON_CLOSE is set so remember for delete in cleanup\n");
		} else {
			fcb->Flags &= ~DOKAN_DELETE_ON_CLOSE;
		}

		fileObject->FsContext = &fcb->AdvancedFCBHeader;
		fileObject->FsContext2 = ccb;
		fileObject->PrivateCacheMap = NULL;
		fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
		//fileObject->Flags |= FILE_NO_INTERMEDIATE_BUFFERING;

		eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;
		eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);
				
		if (eventContext == NULL) {
            DDbgPrint("    Was not able to allocate eventContext\n");
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		eventContext->Context = 0;
		eventContext->FileFlags |= fcb->Flags;

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

		eventContext->Operation.Create.FileAttributes = irpSp->Parameters.Create.FileAttributes;
		eventContext->Operation.Create.CreateOptions = irpSp->Parameters.Create.Options;
		eventContext->Operation.Create.DesiredAccess = irpSp->Parameters.Create.SecurityContext->DesiredAccess;
		eventContext->Operation.Create.ShareAccess = irpSp->Parameters.Create.ShareAccess;

		// register this IRP to waiting IPR list
		status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

	} __finally {

        DokanCompleteIrpRequest(Irp, status, info);

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

	return status;
}
示例#4
0
文件: fscontrol.c 项目: nmlgc/dokany
NTSTATUS
DokanDispatchFileSystemControl(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)
{
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PIO_STACK_LOCATION	irpSp;
	PDokanVCB			vcb;

	__try {
		DDbgPrint("==> DokanFileSystemControl\n");
		DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));

		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB) {
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		irpSp = IoGetCurrentIrpStackLocation(Irp);

		switch(irpSp->MinorFunction) {
		case IRP_MN_KERNEL_CALL:
			DDbgPrint("	 IRP_MN_KERNEL_CALL\n");
			break;

		case IRP_MN_LOAD_FILE_SYSTEM:
			DDbgPrint("	 IRP_MN_LOAD_FILE_SYSTEM\n");
			break;

		case IRP_MN_MOUNT_VOLUME:
			{
				PVPB vpb;
				DDbgPrint("	 IRP_MN_MOUNT_VOLUME\n");
				if (irpSp->Parameters.MountVolume.DeviceObject != vcb->Dcb->DeviceObject) {
					DDbgPrint("   Not DokanDiskDevice\n");
					status = STATUS_INVALID_PARAMETER;
                    break;
				}
				vpb = irpSp->Parameters.MountVolume.Vpb;
				vpb->DeviceObject = vcb->DeviceObject;
				vpb->RealDevice = vcb->DeviceObject;
				vpb->Flags |= VPB_MOUNTED;
				vpb->VolumeLabelLength = (USHORT)wcslen(VOLUME_LABEL) * sizeof(WCHAR);
				RtlStringCchCopyW(vpb->VolumeLabel, sizeof(vpb->VolumeLabel) / sizeof(WCHAR), VOLUME_LABEL);
				vpb->SerialNumber = 0x19831116;
				status = STATUS_SUCCESS;
			}
			break;

		case IRP_MN_USER_FS_REQUEST:
			DDbgPrint("	 IRP_MN_USER_FS_REQUEST\n");
			status = DokanUserFsRequest(DeviceObject, Irp);
			break;

		case IRP_MN_VERIFY_VOLUME:
			DDbgPrint("	 IRP_MN_VERIFY_VOLUME\n");
			break;

		default:
			DDbgPrint("  unknown %d\n", irpSp->MinorFunction);
			status = STATUS_INVALID_PARAMETER;
			break;

		}

	} __finally {
		
        DokanCompleteIrpRequest(Irp, status, 0);

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

	return status;
}