NTSTATUS DokanDispatchDirectoryControl(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { NTSTATUS status = STATUS_NOT_IMPLEMENTED; PFILE_OBJECT fileObject; PIO_STACK_LOCATION irpSp; PDokanVCB vcb; __try { DDbgPrint("==> DokanDirectoryControl\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject is 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); 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\n"); status = STATUS_INVALID_PARAMETER; } } __finally { DokanCompleteIrpRequest(Irp, status, 0); DDbgPrint("<== DokanDirectoryControl\n"); } return status; }
VOID SetCommonEventContext(__in PDokanDCB Dcb, __in PEVENT_CONTEXT EventContext, __in PIRP Irp, __in_opt PDokanCCB Ccb) { PIO_STACK_LOCATION irpSp; irpSp = IoGetCurrentIrpStackLocation(Irp); EventContext->MountId = Dcb->MountId; EventContext->MajorFunction = irpSp->MajorFunction; EventContext->MinorFunction = irpSp->MinorFunction; EventContext->Flags = irpSp->Flags; if (Ccb) { EventContext->FileFlags = Ccb->Flags; } EventContext->ProcessId = IoGetRequestorProcessId(Irp); }
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; }
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; }
NTSTATUS GingkoRead ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PVOID pBuff = NULL; BOOLEAN GingkoFile = FALSE; PGINGKO_OBJECT pGingkoObject = NULL; PIO_STACK_LOCATION irpsp = NULL; PFILE_OBJECT FileObject = NULL; SharedNotificationPtr snf = NULL; PGINGKO_PROCESS_LIST pProcessList = NULL; PGINGKO_DEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension; if ( IS_GINGKO_CONTROL_DEVICE_OBJECT(DeviceObject) ) { //KdPrint( ("READ: Read Gingko Control Device...") ); Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_INVALID_DEVICE_REQUEST; } REDFISH_NETWORK_DISPATCH( DeviceObject, Irp ); if( IsGingkoServerProcess() || PsIsSystemThread(KeGetCurrentThread()) ) { return GingkoPassThrough( DeviceObject, Irp ); } snf = GingkoReferenceSharedNotification(); if( gGingkoServerStarted == FALSE || snf == NULL ) { return GingkoPassThrough( DeviceObject, Irp ); } GingkoDereferenceSharedNotification( snf ); irpsp = IoGetCurrentIrpStackLocation(Irp); FileObject = irpsp->FileObject; if( FsRtlIsPagingFile( FileObject ) ) { KdPrint(("This is a Paging file: %wZ.\n", &(FileObject->FileName))); } //RtlInitUnicodeString( &TempName, L"\\GingkoDebug\\dbgview.chm" ); //if( RtlCompareUnicodeString( &TempName, &FileObject->FileName, TRUE ) == 0 ) //{ // LARGE_INTEGER OriginalOffset = irpsp->Parameters.Read.ByteOffset; // long OriginalLength = irpsp->Parameters.Read.Length; // KdPrint(("Read DbgView: %I64d (L: %08x, H: %08x) Lenght: %08x\n", OriginalOffset.QuadPart, OriginalOffset.LowPart, // OriginalOffset.HighPart, OriginalLength)); //} if( FindWriteFileObject( FileObject, IoGetRequestorProcessId(Irp), &pGingkoObject, FALSE ) ) { NTSTATUS status = 0L; if( pGingkoObject != NULL ) //&& pGingkoObject->Queue.CryptoInfo != NULL && ( pGingkoObject->Permission & 0x800F0000 | pGingkoObject->Permission & 0x8000F000 ) ) { if( irpsp->Parameters.Read.Length > 0L ) { if( !Irp->MdlAddress ) { __try{ ProbeForRead( Irp->UserBuffer, irpsp->Parameters.Read.Length, 1); IoAllocateMdl( Irp->UserBuffer, irpsp->Parameters.Read.Length, FALSE, FALSE, Irp ); if( Irp->MdlAddress ) { MmProbeAndLockPages( Irp->MdlAddress, UserMode, IoReadAccess ); } }__except(EXCEPTION_EXECUTE_HANDLER) { KdPrint(("Exception Code: %08x. PassThrough. The Write Length is %d, Offset: %I64d.\n", GetExceptionCode(), irpsp->Parameters.Read.Length, irpsp->Parameters.Read.ByteOffset )); if( Irp->MdlAddress ) { IoFreeMdl( Irp->MdlAddress ); Irp->MdlAddress = NULL; } } } } status = EncryptedIoQueueAddIrp (&pGingkoObject->Queue, Irp); if( status != STATUS_PENDING ) TCCompleteDiskIrp ( Irp, status, 0 ); return status; }
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; }
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; }
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; }
NTSTATUS DokanDispatchQueryInformation(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) { NTSTATUS status = STATUS_NOT_IMPLEMENTED; PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; PDokanCCB ccb; PDokanFCB fcb = NULL; PDokanVCB vcb; ULONG info = 0; ULONG eventLength; PEVENT_CONTEXT eventContext; BOOLEAN isNormalized = FALSE; // PAGED_CODE(); __try { 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); DokanFCBLockRO(fcb); 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 FileNormalizedNameInformation: DDbgPrint(" FileNormalizedNameInformation\n"); isNormalized = TRUE; case FileNameInformation: { PFILE_NAME_INFORMATION nameInfo; DDbgPrint(" FileNameInformation\n"); nameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(nameInfo != NULL); BOOLEAN isNetworkFileSystem = (vcb->Dcb->VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM); PUNICODE_STRING fileName = &fcb->FileName; USHORT length = fcb->FileName.Length; BOOLEAN doConcat = FALSE; if (isNetworkFileSystem) { if (fcb->FileName.Length == 0 || fcb->FileName.Buffer[0] != L'\\') { DDbgPrint(" NetworkFileSystem has no root folder. So return the full device name \n"); fileName = vcb->Dcb->DiskDeviceName; length = fileName->Length; } else { if (isNormalized) { DDbgPrint(" FullFileName should be returned \n"); fileName = vcb->Dcb->DiskDeviceName; length = fileName->Length + vcb->Dcb->DiskDeviceName->Length; doConcat = TRUE; } } } if (irpSp->Parameters.QueryFile.Length < sizeof(FILE_NAME_INFORMATION) + length) { info = irpSp->Parameters.QueryFile.Length; status = STATUS_BUFFER_OVERFLOW; } else { RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, irpSp->Parameters.QueryFile.Length); nameInfo->FileNameLength = fileName->Length; RtlCopyMemory(&nameInfo->FileName[0], fileName->Buffer, fileName->Length); if (doConcat) { DDbgPrint(" Concat the devicename with the filename to get the fullname of the file \n"); RtlStringCchCatW(nameInfo->FileName, NTSTRSAFE_MAX_CCH, fcb->FileName.Buffer); } info = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + 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_INFO_LENGTH_MISMATCH; } else { posInfo = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(posInfo != NULL); RtlZeroMemory(posInfo, sizeof(FILE_POSITION_INFORMATION)); if (fileObject->CurrentByteOffset.QuadPart < 0) { status = STATUS_INVALID_PARAMETER; } else { // 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; case FileStandardLinkInformation: DDbgPrint(" FileStandardLinkInformation\n"); break; case FileNetworkPhysicalNameInformation: DDbgPrint(" FileNetworkPhysicalNameInformation\n"); break; case FileRemoteProtocolInformation: DDbgPrint(" FileRemoteProtocolInformation\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->Operation.File.FileInformationClass = irpSp->Parameters.QueryFile.FileInformationClass; // bytes length which is able to be returned eventContext->Operation.File.BufferLength = irpSp->Parameters.QueryFile.Length; // copy file name to EventContext from FCB eventContext->Operation.File.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Operation.File.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // register this IRP to pending IPR list status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { if(fcb) DokanFCBUnlock(fcb); DokanCompleteIrpRequest(Irp, status, info); DDbgPrint("<== DokanQueryInformation\n"); } return status; }
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; ULONG RequiredLength; __try { DDbgPrint("==> DokanQueryVolumeInformation\n"); DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB) { return STATUS_INVALID_PARAMETER; } dcb = vcb->Dcb; if (!dcb->Mounted) { status = STATUS_VOLUME_DISMOUNTED; __leave; } irpSp = IoGetCurrentIrpStackLocation(Irp); buffer = Irp->AssociatedIrp.SystemBuffer; fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); 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\n"); if (vcb->HasEventWait) { break; } DDbgPrint(" Still no threads for processing available\n"); PFILE_FS_VOLUME_INFORMATION FsVolInfo; ULONG VolumeLabelLength; if (irpSp->Parameters.QueryVolume.Length < sizeof(FILE_FS_VOLUME_INFORMATION)) { status = STATUS_BUFFER_OVERFLOW; __leave; } FsVolInfo = (PFILE_FS_VOLUME_INFORMATION)buffer; FsVolInfo->VolumeCreationTime.QuadPart = 0; FsVolInfo->VolumeSerialNumber = 0x19831116; VolumeLabelLength = (USHORT)wcslen(VOLUME_LABEL) * sizeof(WCHAR); FsVolInfo->VolumeLabelLength = VolumeLabelLength; /* We don't support ObjectId */ FsVolInfo->SupportsObjects = FALSE; RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION) + VolumeLabelLength - sizeof(WCHAR); if (irpSp->Parameters.QueryVolume.Length < RequiredLength) { Irp->IoStatus.Information = sizeof(FILE_FS_VOLUME_INFORMATION); status = STATUS_BUFFER_OVERFLOW; __leave; } RtlCopyMemory(FsVolInfo->VolumeLabel, L"DOKAN", VolumeLabelLength); Irp->IoStatus.Information = RequiredLength; status = STATUS_SUCCESS; __leave; break; case FileFsLabelInformation: DDbgPrint(" FileFsLabelInformation\n"); break; case FileFsSizeInformation: DDbgPrint(" FileFsSizeInformation\n"); break; case FileFsDeviceInformation: { PFILE_FS_DEVICE_INFORMATION device; DDbgPrint(" FileFsDeviceInformation\n"); 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 = dcb->DeviceType; device->Characteristics = dcb->DeviceCharacteristics; status = STATUS_SUCCESS; info = sizeof(FILE_FS_DEVICE_INFORMATION); __leave; } break; case FileFsAttributeInformation: DDbgPrint(" FileFsAttributeInformation\n"); if (vcb->HasEventWait) { break; } DDbgPrint(" Still no threads for processing available\n"); PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo; if (irpSp->Parameters.QueryVolume.Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) { status = STATUS_BUFFER_OVERFLOW; __leave; } FsAttrInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)Irp->AssociatedIrp.SystemBuffer; FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS | FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; FsAttrInfo->MaximumComponentNameLength = 256; FsAttrInfo->FileSystemNameLength = 8; RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8 - sizeof(WCHAR); if (irpSp->Parameters.QueryVolume.Length < RequiredLength) { Irp->IoStatus.Information = sizeof(FILE_FS_ATTRIBUTE_INFORMATION); status = STATUS_BUFFER_OVERFLOW; __leave; } RtlCopyMemory(FsAttrInfo->FileSystemName, L"Dokan\0", 10); Irp->IoStatus.Information = RequiredLength; status = STATUS_SUCCESS; __leave; break; case FileFsControlInformation: DDbgPrint(" FileFsControlInformation\n"); break; case FileFsFullSizeInformation: DDbgPrint(" FileFsFullSizeInformation\n"); break; case FileFsObjectIdInformation: DDbgPrint(" FileFsObjectIdInformation\n"); break; case FileFsMaximumInformation: DDbgPrint(" FileFsMaximumInformation\n"); 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->Operation.Volume.FsInformationClass = irpSp->Parameters.QueryVolume.FsInformationClass; // the length which can be returned to user-mode eventContext->Operation.Volume.BufferLength = irpSp->Parameters.QueryVolume.Length; status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } } __finally { DokanCompleteIrpRequest(Irp, status, info); DDbgPrint("<== DokanQueryVolumeInformation\n"); } return status; }
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); FlushFcb(fcb, fileObject); DokanFCBLockRW(fcb); eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; DokanFCBUnlock(fcb); __leave; } fileObject->Flags |= FO_CLEANUP_COMPLETE; eventContext->Context = ccb->UserContext; eventContext->FileFlags |= DokanCCBFlagsGet(ccb); // 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); // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking. status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, DokanOplockComplete, DokanPrePostIrp); DokanFCBUnlock(fcb); // // 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 pending IRP list status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { DokanCompleteIrpRequest(Irp, status, 0); DDbgPrint("<== DokanCleanup\n"); } return status; }
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; }
NTSTATUS DokanDispatchLock( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { PDokanVCB vcb; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_INVALID_PARAMETER; PFILE_OBJECT fileObject; PDokanCCB ccb; PDokanFCB fcb; PEVENT_CONTEXT eventContext; ULONG eventLength; PAGED_CODE(); __try { //FsRtlEnterFileSystem(); DDbgPrint("==> DokanLock\n"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; vcb = DokanGetVcb(DeviceObject); deviceExtension = DokanGetDeviceExtension(DeviceObject); if (fileObject == NULL) { DDbgPrint(" fileObject == NULL\n"); status = STATUS_INVALID_PARAMETER; __leave; } if (!DokanCheckCCB(deviceExtension, fileObject->FsContext2)) { status = STATUS_INVALID_PARAMETER; __leave; } DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); DDbgPrint(" FileName:%wZ\n", &fileObject->FileName); 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(deviceExtension, 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->Lock.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Lock.FileName, fcb->FileName.Buffer, fcb->FileName.Length); // parameters of Lock eventContext->Lock.ByteOffset = irpSp->Parameters.LockControl.ByteOffset; eventContext->Lock.Length = *irpSp->Parameters.LockControl.Length; eventContext->Lock.Key = irpSp->Parameters.LockControl.Key; // register this IRP to waiting IRP list and make it pending status status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext); } __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; }
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; }
NTSTATUS GingkoCreateCompleteRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { PKEVENT Event = Context; ULONG CreateOptions = 0L; PIO_STACK_LOCATION pCurrStack = NULL; ULONG dwRequestProcessId = 0L; PFILE_OBJECT FileObject = NULL; ACCESS_MASK DesiredAccess = 0L; ULONG Information = 0L; NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER( DeviceObject ); UNREFERENCED_PARAMETER( Irp ); UNREFERENCED_PARAMETER( Context ); ASSERT(IS_GINGKO_DEVICE_OBJECT( DeviceObject )); ///KdPrint(("Gingko Completed Read from the physical driver.\n")); if( Irp->PendingReturned == TRUE ) { IoMarkIrpPending( Irp ); return STATUS_MORE_PROCESSING_REQUIRED; } pCurrStack = IoGetCurrentIrpStackLocation( Irp ); FileObject = pCurrStack->FileObject; dwRequestProcessId = IoGetRequestorProcessId( Irp ); IoCopyCurrentIrpStackLocationToNext( Irp ); //ShareAccess = pCurrStack->Parameters.Create.ShareAccess; //FileAttributes = pCurrStack->Parameters.Create.FileAttributes; CreateOptions = pCurrStack->Parameters.Create.Options; DesiredAccess = pCurrStack->Parameters.Create.SecurityContext ? pCurrStack->Parameters.Create.SecurityContext->DesiredAccess : 0xFFFFFFFF; Information = (ULONG)Irp->IoStatus.Information; if( Irp->IoStatus.Status == STATUS_SUCCESS //&& !(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) //&& !(FileObject->Flags & FO_STREAM_FILE) && !(CreateOptions & FILE_OPEN_REPARSE_POINT) && !(CreateOptions & FILE_DELETE_ON_CLOSE) && !(CreateOptions & FILE_DIRECTORY_FILE) && !(DesiredAccess & FILE_EXECUTE)) { PGINGKO_OBJECT pRelatedGingko = NULL; GINGKO_HEADER Header = {0}; IO_STATUS_BLOCK IoStatusBlock = {0}; LARGE_INTEGER offset = {0}; ULONG ulHeaderSize = sizeof(GINGKO_HEADER); ULONG FileFlags = FileObject->Flags; //Header = (PGINGKO_HEADER) TCalloc( 8192 ); //if( Header == NULL ) //{ // return status; //} if( Information == FILE_OPENED && FileObject->ReadAccess ) { //KdPrint(("Create FileObject->Flags: %08x, Irp->Flags: %08x.\n", FileObject->Flags, IrpFlags )); //FileObject->Flags = FO_HANDLE_CREATED | FO_CLEANUP_COMPLETE | FO_CACHE_SUPPORTED; if( TRUE ) // Header != NULL ) { //status = TCReadDeviceDirect( // status = TCReadDeviceEx( ((PGINGKO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject, FileObject, &Header, &offset, sizeof(GINGKO_HEADER), &IoStatusBlock, IRP_PAGING_IO | IRP_NOCACHE ); //IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO | IRP_NOCACHE ); }else { IoStatusBlock.Status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY; } FileObject->Flags = FileFlags; FileObject->CurrentByteOffset.QuadPart = 0L; if( NT_SUCCESS(IoStatusBlock.Status) && IoStatusBlock.Information == sizeof(GINGKO_HEADER) ) { //IoCheckShareAccess( DesiredAccess, DesiredShareAccess, FileObject, SHARE_ACCESS hs, FALSE ); if( HasGingkoIdentifier( &Header ) ) { GingkoFileFlushCache( FileObject ); if( !FindWriteFileObject( FileObject,dwRequestProcessId, NULL, FALSE ) ) { PGINGKO_OBJECT pObj = NULL; pObj = (PGINGKO_OBJECT)TCalloc(sizeof(GINGKO_OBJECT)); if( pObj != NULL ) { RtlZeroMemory( pObj, sizeof(GINGKO_OBJECT) ); RtlCopyMemory( &(pObj->GingkoHeader), &Header, sizeof(GINGKO_HEADER) ); pObj->FileObject = FileObject; pObj->Permission = GINGKO_PERMISSION_EMPTY; pObj->dwProcessId = dwRequestProcessId; pObj->Queue.LowerDeviceObject = ((PGINGKO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; pObj->Queue.DeviceObject = ((PGINGKO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; pObj->Queue.IsFilterDevice = TRUE; pObj->Queue.SecurityClientContext = NULL; //pObj->Queue.CompletionThread = NULL; pObj->Queue.CryptoInfo = NULL; pObj->Queue.StopPending = FALSE; pObj->Queue.ShouldPassthrough = FALSE; pObj->Queue.FileObject = FileObject; pObj->Queue.GingkoHeader = &(pObj->GingkoHeader); pObj->Queue.TotalBytesRead = 0; pObj->Queue.TotalBytesWritten = 0; pObj->Queue.GingkoObject = pObj; pObj->Queue.dwProcessId = dwRequestProcessId; GetFileObjectFullName( FileObject, &(pObj->FileName) ); pObj->Queue.AbstractOffset = sizeof(GINGKO_HEADER); ExInterlockedInsertTailList( &gGingkoWriteFileListEntry, &(pObj->ListEntry), &gGingkoWriteFileSpinLock ); EncryptedIoQueueStart( &pObj->Queue ); } } //KdPrint(("CREATE: Has Gingko Identifier from Create.\n")); } //reset the offset } //if( Header != NULL ) //{ // //ExFreePoolWithTag(Header, GINGKO_POOL_TAG); // TCfree( Header ); // Header = NULL; //} } } if(Event) KeSetEvent(Event, IO_NO_INCREMENT, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; }
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; }
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; }
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; //PAGED_CODE(); __try { FsRtlEnterFileSystem(); DDbgPrint("==> DokanClose"); irpSp = IoGetCurrentIrpStackLocation(Irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { DDbgPrint(" fileObject is NULL"); 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:%X\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"); DDbgPrint(" Free CCB:%X\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->Close.FileNameLength = fcb->FileName.Length; RtlCopyMemory(eventContext->Close.FileName, fcb->FileName.Buffer, fcb->FileName.Length); DDbgPrint(" Free CCB:%X\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 { if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } DDbgPrint("<== DokanClose"); FsRtlExitFileSystem(); } return status; }
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; }
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; DOKAN_INIT_LOGGER(logger, DeviceObject->DriverObject, IRP_MJ_CLEANUP); __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); if (fcb->IsKeepalive) { DokanFCBLockRW(fcb); BOOLEAN shouldUnmount = ccb->IsKeepaliveActive; if (shouldUnmount) { // Here we intentionally let the VCB-level flag stay set, because // there's no sense in having an opportunity for an "operation timeout // unmount" in this case. ccb->IsKeepaliveActive = FALSE; } DokanFCBUnlock(fcb); if (shouldUnmount) { if (IsUnmountPendingVcb(vcb)) { DokanLogInfo(&logger, L"Ignoring keepalive close because unmount is already in" L" progress."); } else { DokanLogInfo(&logger, L"Unmounting due to keepalive close."); DokanUnmount(vcb->Dcb); } } } if (fcb->BlockUserModeDispatch) { status = STATUS_SUCCESS; __leave; } FlushFcb(fcb, fileObject); DokanFCBLockRW(fcb); eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); if (eventContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; DokanFCBUnlock(fcb); __leave; } fileObject->Flags |= FO_CLEANUP_COMPLETE; eventContext->Context = ccb->UserContext; eventContext->FileFlags |= DokanCCBFlagsGet(ccb); // 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); // FsRtlCheckOpLock is called with non-NULL completion routine - not blocking. status = FsRtlCheckOplock(DokanGetFcbOplock(fcb), Irp, eventContext, DokanOplockComplete, DokanPrePostIrp); DokanFCBUnlock(fcb); // // 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 pending IRP list status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); } __finally { DokanCompleteIrpRequest(Irp, status, 0); DDbgPrint("<== DokanCleanup\n"); } return status; }
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; }
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; }
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; }
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; __try { 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 { DokanCompleteIrpRequest(Irp, status, 0); DDbgPrint("<== DokanLock\n"); } return status; }
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; }
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; }