Exemple #1
0
VOID
DokanCompleteWrite(
	__in PIRP_ENTRY			IrpEntry,
	__in PEVENT_INFORMATION	EventInfo
	)
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status     = STATUS_SUCCESS;
	ULONG				readLength = 0;
	ULONG				bufferLen  = 0;
	PVOID				buffer	   = NULL;
	PDokanCCB			ccb;
	PFILE_OBJECT		fileObject;

	fileObject = IrpEntry->FileObject;
	ASSERT(fileObject != NULL);

	DDbgPrint("==> DokanCompleteWrite %wZ\n", &fileObject->FileName);

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

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

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

	status = EventInfo->Status;

	irp->IoStatus.Status = status;
	irp->IoStatus.Information = EventInfo->BufferLength;

	if (NT_SUCCESS(status) &&
		EventInfo->BufferLength != 0 &&
		fileObject->Flags & FO_SYNCHRONOUS_IO &&
		!(irp->Flags & IRP_PAGING_IO)) {
		// update current byte offset only when synchronous IO and not paging IO
		fileObject->CurrentByteOffset.QuadPart =
			EventInfo->Write.CurrentByteOffset.QuadPart;
		DDbgPrint("  Updated CurrentByteOffset %I64d\n",
			fileObject->CurrentByteOffset.QuadPart);
	}

	IoCompleteRequest(irp, IO_NO_INCREMENT);

	DokanPrintNTStatus(status);
	DDbgPrint("<== DokanCompleteWrite");
}
Exemple #2
0
VOID DokanCompleteIrpRequest(__in PIRP Irp, __in NTSTATUS Status,
                             __in ULONG_PTR Info) {
  if (Irp == NULL) {
    DDbgPrint("  Irp is NULL, so no complete required\n");
    return;
  }
  if (Status == -1) {
    DDbgPrint("  Status is -1 which is not valid NTSTATUS\n");
    Status = STATUS_INVALID_PARAMETER;
  }
  if (Status != STATUS_PENDING) {
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = Info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
  }
  DokanPrintNTStatus(Status);
}
Exemple #3
0
VOID
DokanCompleteFlush(
	 __in PIRP_ENTRY			IrpEntry,
	 __in PEVENT_INFORMATION	EventInfo
	 )
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status   = STATUS_SUCCESS;
	ULONG				info	 = 0;
	PDokanCCB			ccb;
	PDokanFCB			fcb;
	PFILE_OBJECT		fileObject;

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

	//FsRtlEnterFileSystem();

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

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

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

	status = EventInfo->Status;

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

	DokanPrintNTStatus(status);

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

	//FsRtlExitFileSystem();

}
Exemple #4
0
VOID
DokanCompleteSetSecurity(
	__in PIRP_ENTRY		IrpEntry,
	__in PEVENT_INFORMATION EventInfo
	)
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	PFILE_OBJECT		fileObject;
	PDokanCCB			ccb;
	NTSTATUS			status;

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

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

	fileObject = IrpEntry->FileObject;
	ASSERT(fileObject != NULL);

	ccb = fileObject->FsContext2;
	if (ccb != NULL) {
		ccb->UserContext = EventInfo->Context;
	} else {
		DDbgPrint("  ccb == NULL\n");
	}

	status = EventInfo->Status;

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

	DokanPrintNTStatus(status);

	DDbgPrint("<== DokanCompleteSetSecurity\n");
}
Exemple #5
0
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;

	//PAGED_CODE();

	__try {

		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanCleanup");
	
		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");
			status = STATUS_SUCCESS;
			__leave;
		}

		vcb = DeviceObject->DeviceExtension;
		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;
		//DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

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

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

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

		DDbgPrint("<== DokanCleanup");
	
		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #6
0
NTSTATUS
DokanDispatchSetSecurity(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)
{
	PIO_STACK_LOCATION	irpSp;
	PDokanVCB			vcb;
	PDokanDCB			dcb;
	PDokanCCB			ccb;
	PDokanFCB			fcb;
	NTSTATUS			status = STATUS_NOT_IMPLEMENTED;
	PFILE_OBJECT		fileObject;
	ULONG				info = 0;
	PSECURITY_INFORMATION	securityInfo;
	PSECURITY_DESCRIPTOR	securityDescriptor;
	PSECURITY_DESCRIPTOR	selfRelativesScurityDescriptor = NULL;
	ULONG				securityDescLength;
	ULONG				eventLength;
	PEVENT_CONTEXT		eventContext;

	__try {
		FsRtlEnterFileSystem();

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

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

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

		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB) {
			DbgPrint("    DeviceExtension != VCB\n");
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		dcb = vcb->Dcb;

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

		ccb = fileObject->FsContext2;
		if (ccb == NULL) {
			DDbgPrint("    ccb == NULL\n");
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		fcb = ccb->Fcb;

		securityInfo = &irpSp->Parameters.SetSecurity.SecurityInformation;

		if (*securityInfo & OWNER_SECURITY_INFORMATION) {
			DDbgPrint("    OWNER_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & GROUP_SECURITY_INFORMATION) {
			DDbgPrint("    GROUP_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & DACL_SECURITY_INFORMATION) {
			DDbgPrint("    DACL_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & SACL_SECURITY_INFORMATION) {
			DDbgPrint("    SACL_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & LABEL_SECURITY_INFORMATION) {
			DDbgPrint("    LABEL_SECURITY_INFORMATION\n");
		}

		securityDescriptor = irpSp->Parameters.SetSecurity.SecurityDescriptor;

		// Assumes the parameter is self relative SD.
		securityDescLength = RtlLengthSecurityDescriptor(securityDescriptor);

		eventLength = sizeof(EVENT_CONTEXT) + securityDescLength + fcb->FileName.Length;

		if (EVENT_CONTEXT_MAX_SIZE < eventLength) {
			// TODO: Handle this case like DispatchWrite.
			DDbgPrint("    SecurityDescriptor is too big: %d (limit %d)\n",
					eventLength, EVENT_CONTEXT_MAX_SIZE);
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

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

		if (eventContext == NULL) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}
		eventContext->Context = ccb->UserContext;
		eventContext->SetSecurity.SecurityInformation = *securityInfo;
		eventContext->SetSecurity.BufferLength = securityDescLength;
		eventContext->SetSecurity.BufferOffset = FIELD_OFFSET(EVENT_CONTEXT, SetSecurity.FileName[0]) +
													fcb->FileName.Length + sizeof(WCHAR);
		RtlCopyMemory((PCHAR)eventContext + eventContext->SetSecurity.BufferOffset,
				securityDescriptor, securityDescLength);


		eventContext->SetSecurity.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->SetSecurity.FileName, fcb->FileName.Buffer, fcb->FileName.Length);

		status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = info;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

		DDbgPrint("<== DokanSetSecurity\n");
		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #7
0
NTSTATUS
DokanDispatchQuerySecurity(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)
{
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status = STATUS_NOT_IMPLEMENTED;
	PFILE_OBJECT		fileObject;
	ULONG				info = 0;
	ULONG				bufferLength;
	SECURITY_DESCRIPTOR dummySecurityDesc;
	ULONG				descLength;
	PSECURITY_DESCRIPTOR securityDesc;
	PSECURITY_INFORMATION securityInfo;
	PDokanFCB			fcb;
	PDokanDCB			dcb;
	PDokanVCB			vcb;
	PDokanCCB			ccb;
	ULONG				eventLength;
	PEVENT_CONTEXT		eventContext;
	ULONG				flags = 0;

	__try {
		FsRtlEnterFileSystem();

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

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

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

		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB) {
			DbgPrint("    DeviceExtension != VCB\n");
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		dcb = vcb->Dcb;

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

		ccb = fileObject->FsContext2;
		if (ccb == NULL) {
			DDbgPrint("    ccb == NULL\n");
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		fcb = ccb->Fcb;

		bufferLength = irpSp->Parameters.QuerySecurity.Length;
		securityInfo = &irpSp->Parameters.QuerySecurity.SecurityInformation;

		if (*securityInfo & OWNER_SECURITY_INFORMATION) {
			DDbgPrint("    OWNER_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & GROUP_SECURITY_INFORMATION) {
			DDbgPrint("    GROUP_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & DACL_SECURITY_INFORMATION) {
			DDbgPrint("    DACL_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & SACL_SECURITY_INFORMATION) {
			DDbgPrint("    SACL_SECURITY_INFORMATION\n");
		}
		if (*securityInfo & LABEL_SECURITY_INFORMATION) {
			DDbgPrint("    LABEL_SECURITY_INFORMATION\n");
		}

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

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

		if (Irp->UserBuffer != NULL && bufferLength > 0) {
			// make a MDL for UserBuffer that can be used later on another thread context	
			if (Irp->MdlAddress == NULL) {
				status = DokanAllocateMdl(Irp, bufferLength);
				if (!NT_SUCCESS(status)) {
					ExFreePool(eventContext);
					__leave;
				}
				flags = DOKAN_MDL_ALLOCATED;
			}
		}

		eventContext->Context = ccb->UserContext;
		eventContext->Security.SecurityInformation = *securityInfo;
		eventContext->Security.BufferLength = bufferLength;
	
		eventContext->Security.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->Security.FileName,
				fcb->FileName.Buffer, fcb->FileName.Length);

		status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, flags);

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = info;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

		DDbgPrint("<== DokanQuerySecurity\n");
		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #8
0
NTSTATUS
DokanDispatchQueryVolumeInformation(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
   )
{
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PIO_STACK_LOCATION  irpSp;
	PVOID				buffer;
	PFILE_OBJECT		fileObject;
	PDokanVCB			vcb;
	PDokanDCB			dcb;
	PDokanCCB			ccb;
	ULONG               info = 0;

	//PAGED_CODE();

	__try {

		FsRtlEnterFileSystem();

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

		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB) {
			return STATUS_INVALID_PARAMETER;
		}
		dcb = vcb->Dcb;

		irpSp			= IoGetCurrentIrpStackLocation(Irp);
		buffer			= Irp->AssociatedIrp.SystemBuffer;

		fileObject		= irpSp->FileObject;

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


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

		ccb = fileObject->FsContext2;

		//	ASSERT(ccb != NULL);

		switch(irpSp->Parameters.QueryVolume.FsInformationClass) {
		case FileFsVolumeInformation:
			DDbgPrint("  FileFsVolumeInformation");
			break;

		case FileFsLabelInformation:
			DDbgPrint("  FileFsLabelInformation");
			break;
	        
		case FileFsSizeInformation:
			DDbgPrint("  FileFsSizeInformation");
			break;
	    
		case FileFsDeviceInformation:
			{
				PFILE_FS_DEVICE_INFORMATION device;
				DDbgPrint("  FileFsDeviceInformation");
				device = (PFILE_FS_DEVICE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
				if (irpSp->Parameters.QueryVolume.Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
					status = STATUS_BUFFER_TOO_SMALL;
					info = sizeof(FILE_FS_DEVICE_INFORMATION);
					__leave;
				}
				device->DeviceType = FILE_DEVICE_DISK;//dcb->DeviceType;
				device->Characteristics = dcb->DeviceCharacteristics;
				status = STATUS_SUCCESS;
				info = sizeof(FILE_FS_DEVICE_INFORMATION);
				__leave;
			}
			break;
	    
		case FileFsAttributeInformation:
			DDbgPrint("  FileFsAttributeInformation");
			break;
	    
		case FileFsControlInformation:
			DDbgPrint("  FileFsControlInformation");
			break;
	    
		case FileFsFullSizeInformation:
			DDbgPrint("  FileFsFullSizeInformation");
			break;
		case FileFsObjectIdInformation:
			DDbgPrint("  FileFsObjectIdInformation");
			break;
	    
		case FileFsMaximumInformation:
			DDbgPrint("  FileFsMaximumInformation");
			break;
	    
		default:
			break;
		}


		if (irpSp->Parameters.QueryVolume.FsInformationClass == FileFsVolumeInformation
			|| irpSp->Parameters.QueryVolume.FsInformationClass == FileFsSizeInformation
			|| irpSp->Parameters.QueryVolume.FsInformationClass == FileFsAttributeInformation
			|| irpSp->Parameters.QueryVolume.FsInformationClass == FileFsFullSizeInformation) {


			ULONG			eventLength = sizeof(EVENT_CONTEXT);
			PEVENT_CONTEXT	eventContext;

			if (ccb && !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
				status = STATUS_INVALID_PARAMETER;
				__leave;
			}

			// this memory must be freed in this {}
			eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, NULL);

			if (eventContext == NULL) {
				status = STATUS_INSUFFICIENT_RESOURCES;
				__leave;
			}
		
			if (ccb) {
				eventContext->Context = ccb->UserContext;
				eventContext->FileFlags = ccb->Flags;
				//DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);
			}

			eventContext->Volume.FsInformationClass =
				irpSp->Parameters.QueryVolume.FsInformationClass;

			// the length which can be returned to user-mode
			eventContext->Volume.BufferLength = irpSp->Parameters.QueryVolume.Length;


			status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);
		}

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = info;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

		DDbgPrint("<== DokanQueryVolumeInformation");

		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #9
0
VOID
DokanCompleteQuerySecurity(
	__in PIRP_ENTRY		IrpEntry,
	__in PEVENT_INFORMATION EventInfo
	)
{
	PIRP		irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS	status;
	PVOID		buffer = NULL;
	ULONG		bufferLength;
	ULONG		info = 0;
	PFILE_OBJECT	fileObject;
	PDokanCCB		ccb;

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

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

	if (irp->MdlAddress) {
		buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
	}

	bufferLength = irpSp->Parameters.QuerySecurity.Length;

	if (EventInfo->Status == STATUS_SUCCESS &&
		EventInfo->BufferLength <= bufferLength &&
		buffer != NULL) {
		RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength);
		info = EventInfo->BufferLength;
		status = STATUS_SUCCESS;

	} else if (EventInfo->Status == STATUS_BUFFER_OVERFLOW ||
			(EventInfo->Status == STATUS_SUCCESS && bufferLength < EventInfo->BufferLength)) {
		info = EventInfo->BufferLength;
		status = STATUS_BUFFER_OVERFLOW;

	} else {
		info = 0;
		status = EventInfo->Status;
	}

	if (IrpEntry->Flags & DOKAN_MDL_ALLOCATED) {
		DokanFreeMdl(irp);
		IrpEntry->Flags &= ~DOKAN_MDL_ALLOCATED;
	}

	fileObject = IrpEntry->FileObject;
	ASSERT(fileObject != NULL);

	ccb = fileObject->FsContext2;
	if (ccb != NULL) {
		ccb->UserContext = EventInfo->Context;
	} else {
		DDbgPrint("  ccb == NULL\n");
	}

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

	DokanPrintNTStatus(status);

	DDbgPrint("<== DokanCompleteQuerySecurity\n");
}
Exemple #10
0
VOID
DokanCompleteQueryInformation(
	__in PIRP_ENTRY		IrpEntry,
	__in PEVENT_INFORMATION EventInfo
	)
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status   = STATUS_SUCCESS;
	ULONG				info	 = 0;
	ULONG				bufferLen= 0;
	PVOID				buffer	 = NULL;
	PDokanCCB			ccb;

	//FsRtlEnterFileSystem();

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

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

	ccb = IrpEntry->FileObject->FsContext2;

	ASSERT(ccb != NULL);

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

	// where we shold copy FileInfo to
	buffer = irp->AssociatedIrp.SystemBuffer;

	// available buffer size
	bufferLen = irpSp->Parameters.QueryFile.Length;

	// buffer is not specifed or short of size
	if (bufferLen == 0 || buffer == NULL || bufferLen < EventInfo->BufferLength) {
		info   = 0;
		status = STATUS_INSUFFICIENT_RESOURCES;

	} else {

		//
		// we write FileInfo from user mode
		//
		ASSERT(buffer != NULL);
		
		RtlZeroMemory(buffer, bufferLen);
		RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength);

		// written bytes
		info = EventInfo->BufferLength;
		status = EventInfo->Status;

		if (NT_SUCCESS(status)
			&& irpSp->Parameters.QueryFile.FileInformationClass == FileAllInformation) {

			PFILE_ALL_INFORMATION allInfo = (PFILE_ALL_INFORMATION)buffer;
			allInfo->PositionInformation.CurrentByteOffset = IrpEntry->FileObject->CurrentByteOffset;
		}
	}


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

	DokanPrintNTStatus(status);
	DDbgPrint("<== DokanCompleteQueryInformation\n");

	//FsRtlExitFileSystem();

}
Exemple #11
0
NTSTATUS
DokanDispatchFileSystemControl(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)
{
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PIO_STACK_LOCATION	irpSp;
	PDokanVCB			vcb;

	PAGED_CODE();

	__try {
		FsRtlEnterFileSystem();

		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;
				}
				vpb = irpSp->Parameters.MountVolume.Vpb;
				vpb->DeviceObject = vcb->DeviceObject;
				vpb->RealDevice = vcb->DeviceObject;
				vpb->Flags |= VPB_MOUNTED;
				vpb->VolumeLabelLength = 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 {
		
		Irp->IoStatus.Status = status;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

		DokanPrintNTStatus(status);
		DDbgPrint("<== DokanFileSystemControl\n");

		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #12
0
VOID
DokanCompleteDirectoryControl(
	__in PIRP_ENTRY			IrpEntry,
	__in PEVENT_INFORMATION	EventInfo
	)
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status   = STATUS_SUCCESS;
	ULONG				info	 = 0;
	ULONG				bufferLen= 0;
	PVOID				buffer	 = NULL;

	//FsRtlEnterFileSystem();

	DDbgPrint("==> DokanCompleteDirectoryControl");

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


	// buffer pointer which points DirecotryInfo
	if (irp->MdlAddress) {
		//DDbgPrint("   use MDL Address");
		buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
	} else {
		//DDbgPrint("   use UserBuffer");
		buffer	= irp->UserBuffer;
	}
	// usable buffer size
	bufferLen = irpSp->Parameters.QueryDirectory.Length;



	//DDbgPrint("  !!Returning DirecotyInfo!!");

	// buffer is not specified or short of length
	if (bufferLen == 0 || buffer == NULL || bufferLen < EventInfo->BufferLength) {
		info   = 0;
		status = STATUS_INSUFFICIENT_RESOURCES;

	} else {

		PDokanCCB ccb	= IrpEntry->FileObject->FsContext2;
		ULONG	 orgLen = irpSp->Parameters.QueryDirectory.Length;

		//
		// set the information recieved from user mode
		//
		ASSERT(buffer != NULL);
		
		RtlZeroMemory(buffer, bufferLen);
		
		//DDbgPrint("   copy DirectoryInfo");
		RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength);

		DDbgPrint("    eventInfo->Directory.Index = %d\n", EventInfo->Directory.Index);
		DDbgPrint("    eventInfo->BufferLength    = %d\n", EventInfo->BufferLength);
		DDbgPrint("    eventInfo->Status = %x (%d)\n",	  EventInfo->Status, EventInfo->Status);

		// update index which specified n-th directory entry is returned
		// this should be locked before writing?
		ccb->Context = EventInfo->Directory.Index;

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

		// written bytes
		//irpSp->Parameters.QueryDirectory.Length = EventInfo->BufferLength;

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


	if (IrpEntry->Flags & DOKAN_MDL_ALLOCATED) {
		DokanFreeMdl(irp);
		IrpEntry->Flags &= ~DOKAN_MDL_ALLOCATED;
	}

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

	DokanPrintNTStatus(status);

	DDbgPrint("<== DokanCompleteDirectoryControl");

	//FsRtlExitFileSystem();
}
Exemple #13
0
NTSTATUS
DokanDispatchDirectoryControl(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
   )
{
	NTSTATUS			status		= STATUS_NOT_IMPLEMENTED;
	PFILE_OBJECT		fileObject;
	PIO_STACK_LOCATION	irpSp;
	PDokanCCB			ccb;
	PDokanVCB			vcb;

	//PAGED_CODE();

	__try {
		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanDirectoryControl");

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

		if (fileObject == NULL) {
			DDbgPrint(" failed  fileObject is NULL");
			status = STATUS_INVALID_PARAMETER;
			__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);

		if (irpSp->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
			status = DokanQueryDirectory(DeviceObject, Irp);
	
		} else if( irpSp->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY) {
			status = DokanNotifyChangeDirectory(DeviceObject, Irp);
		} else {
			DDbgPrint("  invalid minor function");
			status = STATUS_INVALID_PARAMETER;
		}
	
	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
		}

		DokanPrintNTStatus(status);
		DDbgPrint("<== DokanDirectoryControl");

		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #14
0
VOID
DokanCompleteCreate(
	 __in PIRP_ENTRY			IrpEntry,
	 __in PEVENT_INFORMATION	EventInfo
	 )
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status;
	ULONG				info;
	PDokanCCB			ccb;
	PDokanFCB			fcb;

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

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

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

	DDbgPrint("  FileName:%wZ\n", &fcb->FileName);

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

	status = EventInfo->Status;

	info = EventInfo->Create.Information;

	switch (info) {
	case FILE_OPENED:
		DDbgPrint("  FILE_OPENED\n");
		break;
	case FILE_CREATED:
		DDbgPrint("  FILE_CREATED\n");
		break;
	case FILE_OVERWRITTEN:
		DDbgPrint("  FILE_OVERWRITTEN\n");
		break;
	case FILE_DOES_NOT_EXIST:
		DDbgPrint("  FILE_DOES_NOT_EXIST\n");
		break;
	case FILE_EXISTS:
		DDbgPrint("  FILE_EXISTS\n");
		break;
	default:
		DDbgPrint("  info = %d\n", info);
		break;
	}

	ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE);
	if (NT_SUCCESS(status) &&
		(irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE ||
		EventInfo->Create.Flags & DOKAN_FILE_DIRECTORY)) {
		if (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) {
			DDbgPrint("  FILE_DIRECTORY_FILE %p\n", fcb);
		} else {
			DDbgPrint("  DOKAN_FILE_DIRECTORY %p\n", fcb);
		}
		fcb->Flags |= DOKAN_FILE_DIRECTORY;
	}
	ExReleaseResourceLite(&fcb->Resource);

	ExAcquireResourceExclusiveLite(&ccb->Resource, TRUE);
	if (NT_SUCCESS(status)) {
		ccb->Flags |= DOKAN_FILE_OPENED;
	}
	ExReleaseResourceLite(&ccb->Resource);


	if (NT_SUCCESS(status)) {
		if (info == FILE_CREATED) {
			if (fcb->Flags & DOKAN_FILE_DIRECTORY) {
				DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_ADDED);
			} else {
				DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED);
			}
		}
	} else {
		DDbgPrint("   IRP_MJ_CREATE failed. Free CCB:%X\n", ccb);
        DokanFreeCCB(ccb);
		DokanFreeFCB(fcb);
	}

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

	DokanPrintNTStatus(status);
	DDbgPrint("<== DokanCompleteCreate\n");
}
Exemple #15
0
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;
	PEPROCESS			process;
	PUNICODE_STRING		processImageName;
	PEVENT_CONTEXT		eventContext;
	PFILE_OBJECT		relatedFileObject;
	ULONG				fileNameLength = 0;
	ULONG				eventLength;
	PDokanFCB			fcb;
	PDokanCCB			ccb;
	PWCHAR				fileName;
	BOOLEAN				needBackSlashAfterRelatedFile = FALSE;

	PAGED_CODE();

	__try {
		FsRtlEnterFileSystem();

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

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

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

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

		vcb = DeviceObject->DeviceExtension;
		PrintIdType(vcb);
		if (GetIdentifierType(vcb) != VCB) {
			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;
		}

		if (relatedFileObject == 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 (relatedFileObject) {
			fileNameLength += relatedFileObject->FileName.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 (relatedFileObject->FileName.Length > 0 &&
				relatedFileObject->FileName.Buffer[relatedFileObject->FileName.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) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

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

		if (relatedFileObject != NULL) {
			DDbgPrint("  RelatedFileName:%wZ\n", &relatedFileObject->FileName);

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

			if (needBackSlashAfterRelatedFile) {
				((PWCHAR)fileName)[relatedFileObject->FileName.Length/sizeof(WCHAR)] = '\\';
			}
			// copy the file name of fileObject
			RtlCopyMemory((PCHAR)fileName +
							relatedFileObject->FileName.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) {
			DokanFreeFCB(fcb); // FileName is freed here
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		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) {
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

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

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

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

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

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = info;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

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

	return status;
}
Exemple #16
0
NTSTATUS
DokanDispatchLock(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)
{
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PFILE_OBJECT		fileObject;
	PDokanCCB			ccb;
	PDokanFCB			fcb;
	PDokanVCB			vcb;
	PEVENT_CONTEXT		eventContext;
	ULONG				eventLength;

	//PAGED_CODE();

	__try {
		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanLock\n");
	
		irpSp = IoGetCurrentIrpStackLocation(Irp);
		fileObject = irpSp->FileObject;

		if (fileObject == NULL) {
			DDbgPrint("  fileObject == NULL\n");
			status = STATUS_INVALID_PARAMETER;
			__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);

		switch(irpSp->MinorFunction) {
		case IRP_MN_LOCK:
			DDbgPrint("  IRP_MN_LOCK\n");
			break;
		case IRP_MN_UNLOCK_ALL:
			DDbgPrint("  IRP_MN_UNLOCK_ALL\n");
			break;
		case IRP_MN_UNLOCK_ALL_BY_KEY:
			DDbgPrint("  IRP_MN_UNLOCK_ALL_BY_KEY\n");
			break;
		case IRP_MN_UNLOCK_SINGLE:
			DDbgPrint("  IRP_MN_UNLOCK_SINGLE\n");
			break;
		default:
			DDbgPrint("  unknown function : %d\n", irpSp->MinorFunction);
			break;
		}

		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;
		}

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

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

		// parameters of Lock
		eventContext->Operation.Lock.ByteOffset = irpSp->Parameters.LockControl.ByteOffset;
		if (irpSp->Parameters.LockControl.Length != NULL) {
			eventContext->Operation.Lock.Length.QuadPart = irpSp->Parameters.LockControl.Length->QuadPart;
		} else {
			DDbgPrint("  LockControl.Length = NULL\n");
		}
		eventContext->Operation.Lock.Key = irpSp->Parameters.LockControl.Key;

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

	} __finally {

		if (status != STATUS_PENDING) {
			//
			// complete the Irp
			//
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

		DDbgPrint("<== DokanLock\n");
		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #17
0
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;
//	PVOID				buffer;
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	ULONG				readLength = 0;
	PDokanCCB			ccb;
	PDokanFCB			fcb;
	PDokanVCB			vcb;
	PEVENT_CONTEXT		eventContext;
	ULONG				eventLength;

	//PAGED_CODE();

	__try {

		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanRead");

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

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

		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB ||
			!DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
			status = STATUS_INVALID_PARAMETER;
			__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");
			
			byteOffset = fileObject->CurrentByteOffset;
		
		} else {
			byteOffset	 = irpSp->Parameters.Read.ByteOffset;
		}

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

		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 (fcb->Flags & DOKAN_FILE_DIRECTORY) {
			DDbgPrint("   DOKAN_FILE_DIRECTORY %p\n", fcb);
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		// 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 (Irp->Flags & IRP_PAGING_IO) {
			DDbgPrint("  Paging IO");
			eventContext->FileFlags |= DOKAN_PAGING_IO;
		}
		if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
			DDbgPrint("  Synchronous IO");
			eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
		}

		if (Irp->Flags & IRP_NOCACHE) {
			DDbgPrint("  Nocache");
			eventContext->FileFlags |= DOKAN_NOCACHE;
		}

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

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

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


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

		// if IRP status is not pending, must complete current IRP
		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = readLength;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		} else {
			DDbgPrint("  STATUS_PENDING");
		}

		DDbgPrint("<== DokanRead");
		
		FsRtlExitFileSystem();

	}

	return status;
}
Exemple #18
0
NTSTATUS
DokanDispatchSetInformation(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
   )
{

	NTSTATUS			status = STATUS_NOT_IMPLEMENTED;
	PIO_STACK_LOCATION  irpSp;
	PVOID				buffer;
	ULONG				remainingLength;
	PFILE_OBJECT		fileObject;
	FILE_INFORMATION_CLASS fileInfo;
	PDokanCCB			ccb;
	PDokanFCB			fcb;
	PDokanVCB			vcb;
	ULONG				eventLength;
	PFILE_OBJECT		targetFileObject;
	PEVENT_CONTEXT		eventContext;

	PAGED_CODE();

	__try {
		FsRtlEnterFileSystem();

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

		irpSp			= IoGetCurrentIrpStackLocation(Irp);
		fileObject		= irpSp->FileObject;
		
		if (fileObject == NULL) {
			DDbgPrint("  fileObject == NULL\n");
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		
		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB ||
			!DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		
		ccb	= (PDokanCCB)fileObject->FsContext2;
		ASSERT(ccb != NULL);

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

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

		buffer = Irp->AssociatedIrp.SystemBuffer;

		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:
			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
		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->SetFile.FileInformationClass =
			irpSp->Parameters.SetFile.FileInformationClass;

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

		// the offset from begining of structure to fill FileInfo
		eventContext->SetFile.BufferOffset = FIELD_OFFSET(EVENT_CONTEXT, SetFile.FileName[0]) +
												fcb->FileName.Length + sizeof(WCHAR); // the last null char
	
		// copy FileInformation
		RtlCopyMemory((PCHAR)eventContext + eventContext->SetFile.BufferOffset,
						Irp->AssociatedIrp.SystemBuffer,
						irpSp->Parameters.SetFile.Length);

		if (irpSp->Parameters.SetFile.FileInformationClass == FileRenameInformation ||
			irpSp->Parameters.SetFile.FileInformationClass == FileLinkInformation) {
			// 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->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);
				RtlCopyMemory(renameContext->FileName, targetFileObject->FileName.Buffer, targetFileObject->FileName.Length);
				renameContext->FileNameLength = targetFileObject->FileName.Length;
			}
		}

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

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

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}


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

		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #19
0
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));
    }

    if (DeviceObject->DriverObject == NULL ||
        DeviceObject->ReferenceCount < 0) {
      status = STATUS_DEVICE_DOES_NOT_EXIST;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;
    PrintIdType(vcb);
    if (GetIdentifierType(vcb) == DGL) {
      status = GlobalDeviceControl(DeviceObject, Irp);
      __leave;
    } else if (GetIdentifierType(vcb) == DCB) {
      status = DiskDeviceControlWithLock(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, Irp);
      break;

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

    case IOCTL_KEEPALIVE:
      DDbgPrint("  IOCTL_KEEPALIVE\n");
      if (IsFlagOn(vcb->Flags, VCB_MOUNTED)) {
        ExEnterCriticalRegionAndAcquireResourceExclusive(&dcb->Resource);
        DokanUpdateTimeout(&dcb->TickCount, DOKAN_KEEPALIVE_TIMEOUT);
        ExReleaseResourceAndLeaveCriticalRegion(&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 = DiskDeviceControlWithLock(dcb->DeviceObject, Irp);
      }

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

  } __finally {

    if (status != STATUS_PENDING) {
      if (IsDeletePending(DeviceObject)) {
        DDbgPrint("  DeviceObject is invalid, so prevent BSOD");
        status = STATUS_DEVICE_REMOVED;
      }
      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;
}
Exemple #20
0
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;
	PDokanVCB			vcb;
	PVOID				buffer;
	ULONG				bufferLength;

	//PAGED_CODE();

	__try {

		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanWrite");

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

		if (fileObject == NULL) {
			DDbgPrint("  fileObject == NULL");
			status = STATUS_INVALID_PARAMETER;
			__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 (fcb->Flags & DOKAN_FILE_DIRECTORY) {
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		if (irpSp->Parameters.Write.Length == 0) {
			status = STATUS_SUCCESS;
			__leave;
		}

		if (Irp->MdlAddress) {
			DDbgPrint("  use MdlAddress");
			buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
		} else {
			DDbgPrint("  use UserBuffer");
			buffer = Irp->UserBuffer;
		}

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

		// the length of EventContext is sum of length to write and length of file name
		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 (Irp->Flags & IRP_PAGING_IO) {
			DDbgPrint("  Paging IO");
			eventContext->FileFlags |= DOKAN_PAGING_IO;
		}
		if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
			DDbgPrint("  Synchronous IO");
			eventContext->FileFlags |= DOKAN_SYNCHRONOUS_IO;
		}

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

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

			eventContext->FileFlags |= DOKAN_WRITE_TO_END_OF_FILE;
			DDbgPrint("  WriteOffset = end of file");
		}

		if ((fileObject->Flags & FO_SYNCHRONOUS_IO) &&
			((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->Write.ByteOffset.QuadPart = fileObject->CurrentByteOffset.QuadPart;
		}

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

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

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

		// copies file name
		eventContext->Write.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->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;

			// 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->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->Write.BufferOffset);
			// puts actual size of RequestContext
			requestContext->Length = requestContextLength;
			// requsts enough size to copy EventContext
			requestContext->Write.RequestLength = eventLength;

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

	} __finally {

		// if status of IRP is not pending, must complete current IRP
		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		} else {
			DDbgPrint("  STATUS_PENDING");
		}

		DDbgPrint("<== DokanWrite");

		FsRtlExitFileSystem();

	}

	return status;
}
Exemple #21
0
NTSTATUS
DokanDispatchQueryInformation(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
   )
{
	NTSTATUS				status = STATUS_NOT_IMPLEMENTED;
	PIO_STACK_LOCATION		irpSp;
	PVOID					buffer;
	ULONG					remainingLength;
	PFILE_OBJECT			fileObject;
	FILE_INFORMATION_CLASS	fileInfo;
	PDokanCCB				ccb;
	PDokanFCB				fcb;
	PDokanVCB				vcb;
	ULONG					info = 0;
	ULONG					eventLength;
	PEVENT_CONTEXT			eventContext;


	PAGED_CODE();
	
	__try {
		FsRtlEnterFileSystem();

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

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

		DDbgPrint("  FileInfoClass %d\n", irpSp->Parameters.QueryFile.FileInformationClass);
		DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));

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

		DokanPrintFileName(fileObject);

		/*
		if (fileObject->FsContext2 == NULL &&
			fileObject->FileName.Length == 0) {
			// volume open?
			status = STATUS_SUCCESS;
			__leave;
		}*/
		vcb = DeviceObject->DeviceExtension;
		if (GetIdentifierType(vcb) != VCB ||
			!DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}

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

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

		switch (irpSp->Parameters.QueryFile.FileInformationClass) {
		case FileBasicInformation:
			DDbgPrint("  FileBasicInformation\n");
			break;  
		case FileInternalInformation:
			DDbgPrint("  FileInternalInformation\n");
			break;
		case FileEaInformation:
			DDbgPrint("  FileEaInformation\n");
			break;          
		case FileStandardInformation:
			DDbgPrint("  FileStandardInformation\n");
			break;
		case FileAllInformation:
			DDbgPrint("  FileAllInformation\n");
			break;
		case FileAlternateNameInformation:
			DDbgPrint("  FileAlternateNameInformation\n");
			break;
		case FileAttributeTagInformation:
			DDbgPrint("  FileAttributeTagInformation\n");
			break;
		case FileCompressionInformation:
			DDbgPrint("  FileCompressionInformation\n");
			break;
		case FileNameInformation:
			{
				PFILE_NAME_INFORMATION nameInfo;

				DDbgPrint("  FileNameInformation\n");
	
				if (irpSp->Parameters.QueryFile.Length < sizeof(FILE_NAME_INFORMATION)
					+ fcb->FileName.Length) {

					status = STATUS_INSUFFICIENT_RESOURCES;
				
				} else {
					
					nameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
					ASSERT(nameInfo != NULL);

					nameInfo->FileNameLength = fcb->FileName.Length;
					RtlCopyMemory(nameInfo->FileName, fcb->FileName.Buffer, fcb->FileName.Length);
					info = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + fcb->FileName.Length;
					status = STATUS_SUCCESS;
				}
				__leave;
			}
			break;
		case FileNetworkOpenInformation:
			DDbgPrint("  FileNetworkOpenInformation\n");
			break;
		case FilePositionInformation:
			{
				PFILE_POSITION_INFORMATION posInfo;
			
				DDbgPrint("  FilePositionInformation\n");

				if (irpSp->Parameters.QueryFile.Length < sizeof(FILE_POSITION_INFORMATION)) {
					status = STATUS_INSUFFICIENT_RESOURCES;
			
				} else {
					posInfo = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
					ASSERT(posInfo != NULL);

					RtlZeroMemory(posInfo, sizeof(FILE_POSITION_INFORMATION));
				
					// set the current file offset
					posInfo->CurrentByteOffset = fileObject->CurrentByteOffset;
				
					info = sizeof(FILE_POSITION_INFORMATION);
					status = STATUS_SUCCESS;
				}
				__leave;
			}
			break;
		case FileStreamInformation:
			DDbgPrint("  FileStreamInformation\n");
			break;
		default:
			DDbgPrint("  unknown type:%d\n", irpSp->Parameters.QueryFile.FileInformationClass);
			break;
		}


		// if it is not treadted in swich case

		// calculate the length of EVENT_CONTEXT
		// sum of it's size and file name length
		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);

		eventContext->File.FileInformationClass =
			irpSp->Parameters.QueryFile.FileInformationClass;

		// bytes length which is able to be returned
		eventContext->File.BufferLength = irpSp->Parameters.QueryFile.Length;

		// copy file name to EventContext from FCB
		eventContext->File.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->File.FileName,
						fcb->FileName.Buffer,
						fcb->FileName.Length);

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

	} __finally {

		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = info;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		}

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

		FsRtlExitFileSystem();

	}

	return status;
}
Exemple #22
0
NTSTATUS
DokanDispatchFlush(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)
{
	PIO_STACK_LOCATION	irpSp;
	PFILE_OBJECT		fileObject;
	PVOID				buffer;
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PDokanFCB			fcb;
	PDokanCCB			ccb;
	PDokanVCB			vcb;
	PEVENT_CONTEXT		eventContext;
	ULONG				eventLength;

	PAGED_CODE();
	
	__try {
		FsRtlEnterFileSystem();

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

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

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

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


		DokanPrintFileName(fileObject);

		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;
		}

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

		// copy file name to be flushed
		eventContext->Flush.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->Flush.FileName, fcb->FileName.Buffer, fcb->FileName.Length);

		CcUninitializeCacheMap(fileObject, NULL, NULL);
		//fileObject->Flags &= FO_CLEANUP_COMPLETE;

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

	} __finally {

		// if status is not pending, must complete current IRPs
		if (status != STATUS_PENDING) {
			Irp->IoStatus.Status = status;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			DokanPrintNTStatus(status);
		} else {
			DDbgPrint("  STATUS_PENDING\n");
		}

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

		FsRtlExitFileSystem();
	}

	return status;
}
Exemple #23
0
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");
	}
}
Exemple #24
0
VOID
DokanCompleteQueryVolumeInformation(
	__in PIRP_ENTRY			IrpEntry,
	__in PEVENT_INFORMATION	EventInfo
	)
{
	PIRP				irp;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status   = STATUS_SUCCESS;
	ULONG				info	 = 0;
	ULONG				bufferLen= 0;
	PVOID				buffer	 = NULL;
	PDokanCCB			ccb;

	//FsRtlEnterFileSystem();

	DDbgPrint("==> DokanCompleteQueryVolumeInformation");

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

	ccb = IrpEntry->FileObject->FsContext2;

	//ASSERT(ccb != NULL);

	// does not save Context!!
	// ccb->UserContext = EventInfo->Context;

	// buffer which is used to copy VolumeInfo
	buffer = irp->AssociatedIrp.SystemBuffer;

	// available buffer size to inform
	bufferLen = irpSp->Parameters.QueryVolume.Length;

	// if buffer is invalid or short of length
	if (bufferLen == 0 || buffer == NULL || bufferLen < EventInfo->BufferLength) {

		info   = 0;
		status = STATUS_INSUFFICIENT_RESOURCES;

	} else {

		// copy the information from user-mode to specified buffer
		ASSERT(buffer != NULL);
		
		RtlZeroMemory(buffer, bufferLen);
		RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength);

		// the written length
		info = EventInfo->BufferLength;

		status = EventInfo->Status;
	}


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

	DokanPrintNTStatus(status);
	DDbgPrint("<== DokanCompleteQueryVolumeInformation");

	//FsRtlExitFileSystem();
}