// user assinged bigger buffer that is enough to return WriteEventContext NTSTATUS DokanEventWrite( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { KIRQL oldIrql; PLIST_ENTRY thisEntry, nextEntry, listHead; PIRP_ENTRY irpEntry; PDokanVCB vcb; PEVENT_INFORMATION eventInfo; PIRP writeIrp; eventInfo = (PEVENT_INFORMATION)Irp->AssociatedIrp.SystemBuffer; ASSERT(eventInfo != NULL); DDbgPrint("==> DokanEventWrite [EventInfo #%X]\n", eventInfo->SerialNumber); vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB) { return STATUS_INVALID_PARAMETER; } ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(&vcb->Dcb->PendingIrp.ListLock, &oldIrql); // search corresponding write IRP through pending IRP list listHead = &vcb->Dcb->PendingIrp.ListHead; for (thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = nextEntry) { PIO_STACK_LOCATION writeIrpSp, eventIrpSp; PEVENT_CONTEXT eventContext; ULONG info = 0; NTSTATUS status; nextEntry = thisEntry->Flink; irpEntry = CONTAINING_RECORD(thisEntry, IRP_ENTRY, ListEntry); // check whehter this is corresponding IRP //DDbgPrint("SerialNumber irpEntry %X eventInfo %X\n", irpEntry->SerialNumber, eventInfo->SerialNumber); if (irpEntry->SerialNumber != eventInfo->SerialNumber) { continue; } // do NOT free irpEntry here writeIrp = irpEntry->Irp; if (writeIrp == NULL) { // this IRP has already been canceled ASSERT(irpEntry->CancelRoutineFreeMemory == FALSE); DokanFreeIrpEntry(irpEntry); continue; } if (IoSetCancelRoutine(writeIrp, DokanIrpCancelRoutine) == NULL) { //if (IoSetCancelRoutine(writeIrp, NULL) != NULL) { // Cancel routine will run as soon as we release the lock InitializeListHead(&irpEntry->ListEntry); irpEntry->CancelRoutineFreeMemory = TRUE; continue; } writeIrpSp = irpEntry->IrpSp; eventIrpSp = IoGetCurrentIrpStackLocation(Irp); ASSERT(writeIrpSp != NULL); ASSERT(eventIrpSp != NULL); eventContext = (PEVENT_CONTEXT)writeIrp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT]; ASSERT(eventContext != NULL); // short of buffer length if (eventIrpSp->Parameters.DeviceIoControl.OutputBufferLength < eventContext->Length) { DDbgPrint(" EventWrite: STATUS_INSUFFICIENT_RESOURCE\n"); status = STATUS_INSUFFICIENT_RESOURCES; } else { PVOID buffer; //DDbgPrint(" EventWrite CopyMemory\n"); //DDbgPrint(" EventLength %d, BufLength %d\n", eventContext->Length, // eventIrpSp->Parameters.DeviceIoControl.OutputBufferLength); if (Irp->MdlAddress) buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); else buffer = Irp->AssociatedIrp.SystemBuffer; ASSERT(buffer != NULL); RtlCopyMemory(buffer, eventContext, eventContext->Length); info = eventContext->Length; status = STATUS_SUCCESS; } DokanFreeEventContext(eventContext); writeIrp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_EVENT] = 0; KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); Irp->IoStatus.Status = status; Irp->IoStatus.Information = info; // this IRP will be completed by caller function return Irp->IoStatus.Status; } KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); return STATUS_SUCCESS; }
NTSTATUS DriverDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION IrpSp; ULONG IOControlCode = 0; ULONG dwBytesWritten = 0; PCHAR pInBuf = NULL, pOutBuf = NULL; unsigned int _cpu_thread_id = 0; unsigned int new_cpu_thread_id = 0; ULONG _num_active_cpus = 0; KAFFINITY _kaffinity = 0; UINT32 core_id = 0; // // Get the current IRP stack location of this request // IrpSp = IoGetCurrentIrpStackLocation (Irp); IOControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; DbgPrint( "[chipsec] >>>>>>>>>> IOCTL >>>>>>>>>>\n" ); DbgPrint( "[chipsec] DeviceObject = 0x%x IOCTL = 0x%x\n", DeviceObject, IOControlCode ); DbgPrint( "[chipsec] InputBufferLength = 0x%x, OutputBufferLength = 0x%x\n", IrpSp->Parameters.DeviceIoControl.InputBufferLength, IrpSp->Parameters.DeviceIoControl.OutputBufferLength ); // // CPU thread ID // _num_active_cpus = KeQueryActiveProcessorCount( NULL ); _kaffinity = KeQueryActiveProcessors(); _cpu_thread_id = KeGetCurrentProcessorNumber(); DbgPrint( "[chipsec] Active CPU threads : %d (KeNumberProcessors = %d)\n", _num_active_cpus, KeNumberProcessors ); DbgPrint( "[chipsec] Active CPU mask (KAFFINITY): 0x%08X\n", _kaffinity ); DbgPrint( "[chipsec] Current CPU thread : %d\n", _cpu_thread_id ); // // Switch on the IOCTL code that is being requested by the user. If the // operation is a valid one for this device do the needful. // Irp -> IoStatus.Information = 0; switch( IOControlCode ) { case READ_PCI_CFG_REGISTER: { DWORD val; BYTE size = 0; WORD bdf[4]; BYTE bus = 0, dev = 0, fun = 0, off = 0; DbgPrint( "[chipsec] > READ_PCI_CFG_REGISTER\n" ); RtlCopyBytes( bdf,Irp->AssociatedIrp.SystemBuffer, 4*sizeof(WORD) ); RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 4*sizeof(WORD), sizeof(BYTE) ); bus = (UINT8)bdf[0]; dev = (UINT8)bdf[1]; fun = (UINT8)bdf[2]; off = (UINT8)bdf[3]; if( 1 != size && 2 != size && 4 != size) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } val = ReadPCICfg( bus, dev, fun, off, size ); IrpSp->Parameters.Read.Length = size; RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&val, size ); DbgPrint( "[chipsec][READ_PCI_CFG_REGISTER] B/D/F: %#04x/%#04x/%#04x, OFFSET: %#04x, value = %#010x (size = 0x%x)\n", bus, dev, fun, off, val, size ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case WRITE_PCI_CFG_REGISTER: { DWORD val = 0; WORD bdf[6]; BYTE bus = 0, dev = 0, fun = 0, off = 0; BYTE size = 0; DbgPrint( "[chipsec] > WRITE_PCI_CFG_REGISTER\n" ); RtlCopyBytes( bdf, Irp->AssociatedIrp.SystemBuffer, 6 * sizeof(WORD) ); bus = (UINT8)bdf[0]; dev = (UINT8)bdf[1]; fun = (UINT8)bdf[2]; off = (UINT8)bdf[3]; RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 6*sizeof(WORD), sizeof(BYTE) ); val = ((DWORD)bdf[5] << 16) | bdf[4]; DbgPrint( "[chipsec][WRITE_PCI_CFG_REGISTER] B/D/F: %#02x/%#02x/%#02x, OFFSET: %#02x, value = %#010x (size = %#02x)\n", bus, dev, fun, off, val, size ); WritePCICfg( bus, dev, fun, off, size, val ); Status = STATUS_SUCCESS; break; } case IOCTL_READ_PHYSMEM: { UINT32 len = 0; PVOID virt_addr; PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 }; DbgPrint( "[chipsec] > IOCTL_READ_PHYSMEM\n" ); if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32)) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; phys_addr.HighPart = ((UINT32*)pInBuf)[0]; phys_addr.LowPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; if( !len ) len = 4; if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len ) { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" ); Status = STATUS_BUFFER_TOO_SMALL; break; } Status = _read_phys_mem( phys_addr, len, pOutBuf ); if (NT_SUCCESS(Status)) { DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] Contents:\n" ); _dump_buffer( (unsigned char *)pOutBuf, min(len,0x100) ); dwBytesWritten = len; } break; } case IOCTL_WRITE_PHYSMEM: { UINT32 len = 0; PVOID virt_addr = 0; PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 }; DbgPrint( "[chipsec] > IOCTL_WRITE_PHYSMEM\n" ); if( Irp->AssociatedIrp.SystemBuffer ) { pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } phys_addr.HighPart = ((UINT32*)pInBuf)[0]; phys_addr.LowPart = ((UINT32*)pInBuf)[1]; len = ((UINT32*)pInBuf)[2]; ((UINT32*)pInBuf) += 3; if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < len + 3*sizeof(UINT32) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] Writing contents:\n" ); _dump_buffer( (unsigned char *)pInBuf, min(len,0x100) ); Status = _write_phys_mem( phys_addr, len, pInBuf ); Status = STATUS_SUCCESS; break; } } case IOCTL_ALLOC_PHYSMEM: { SIZE_T NumberOfBytes = 0; PVOID va = 0; PHYSICAL_ADDRESS HighestAcceptableAddress = { 0xFFFFFFFF, 0xFFFFFFFF }; DbgPrint( "[chipsec] > IOCTL_ALLOC_PHYSMEM\n" ); pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf || IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT64) + sizeof(UINT32)) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &HighestAcceptableAddress.QuadPart, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) ); RtlCopyBytes( &NumberOfBytes, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT64), sizeof(UINT32) ); DbgPrint( "[chipsec] Allocating: NumberOfBytes = 0x%X, PhysAddr = 0x%I64x", NumberOfBytes, HighestAcceptableAddress.QuadPart ); va = MmAllocateContiguousMemory( NumberOfBytes, HighestAcceptableAddress ); if( !va ) { DbgPrint( "[chipsec] ERROR: STATUS_UNSUCCESSFUL - could not allocate memory\n" ); Status = STATUS_UNSUCCESSFUL; } else if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 2*sizeof(UINT64) ) { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2*UINT64\n" ); Status = STATUS_BUFFER_TOO_SMALL; } else { PHYSICAL_ADDRESS pa = MmGetPhysicalAddress( va ); DbgPrint( "[chipsec] Allocated Buffer: VirtAddr = 0x%I64x, PhysAddr = 0x%I64x\n", (UINT64)va, pa.QuadPart ); ((UINT64*)pOutBuf)[0] = (UINT64)va; ((UINT64*)pOutBuf)[1] = pa.QuadPart; IrpSp->Parameters.Read.Length = 2*sizeof(UINT64); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; } break; } case IOCTL_LOAD_UCODE_PATCH: { PVOID ucode_buf = NULL; UINT64 ucode_start = 0; UINT16 ucode_size = 0; UINT32 _eax = 0, _edx = 0; int CPUInfo[4] = {-1}; DbgPrint("[chipsec] > IOCTL_LOAD_UCODE_UPDATE\n" ); if( !Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT16) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < 3)\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id > _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( &ucode_size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT16) ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Ucode update size = 0x%X\n", ucode_size ); if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < ucode_size + sizeof(BYTE) + sizeof(UINT16) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < ucode_size + 3)\n" ); Status = STATUS_INVALID_PARAMETER; break; } ucode_buf = ExAllocatePoolWithTag( NonPagedPool, ucode_size, 0x3184 ); if( !ucode_buf ) { DbgPrint( "[chipsec] ERROR: couldn't allocate pool for ucode binary\n" ); break; } RtlCopyBytes( ucode_buf, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE) + sizeof(UINT16), ucode_size ); ucode_start = (UINT64)ucode_buf; DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update address = 0x%p (eax = 0x%08X, edx = 0x%08X)\n", ucode_start, (UINT32)(ucode_start & 0xFFFFFFFF), (UINT32)((ucode_start >> 32) & 0xFFFFFFFF) ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update contents:\n" ); _dump_buffer( (unsigned char *)ucode_buf, min(ucode_size,0x100) ); // -- // -- trigger CPU ucode patch update // -- pInBuf points to the beginning of ucode update binary // -- _wrmsr( MSR_IA32_BIOS_UPDT_TRIG, (UINT32)((ucode_start >> 32) & 0xFFFFFFFF), (UINT32)(ucode_start & 0xFFFFFFFF) ); ExFreePoolWithTag( ucode_buf, 0x3184 ); // -- // -- check if patch was loaded // -- // -- need to clear IA32_BIOS_SIGN_ID MSR first // -- CPUID will deposit an update ID value in 64-bit MSR at address MSR_IA32_BIOS_SIGN_ID // -- read IA32_BIOS_SIGN_ID MSR to check patch ID != 0 // -- DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] checking ucode update was loaded..\n" ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] clear IA32_BIOS_SIGN_ID, CPUID EAX=1, read back IA32_BIOS_SIGN_ID\n" ); _wrmsr( MSR_IA32_BIOS_SIGN_ID, 0, 0 ); __cpuid(CPUInfo, 1); _rdmsr( MSR_IA32_BIOS_SIGN_ID, &_eax, &_edx ); DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] RDMSR( IA32_BIOS_SIGN_ID=0x8b ) = 0x%08x%08x\n", _edx, _eax ); if( 0 != _edx ) DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Microcode update loaded (ID != 0)\n" ); else DbgPrint( "[chipsec] ERROR: Microcode update failed\n" ); Status = STATUS_SUCCESS; break; } case IOCTL_WRMSR: { UINT32 msrData[3]; UINT32 _eax = 0, _edx = 0; unsigned int _msr_addr; DbgPrint("[chipsec] > IOCTL_WRMSR\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec] ERROR: NO data provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + 3*sizeof(UINT32) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(BYTE) + 3*sizeof(UINT32))\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id > _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][IOCTL_WRMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), 3 * sizeof(UINT32) ); _msr_addr = msrData[0]; _eax = msrData[1]; _edx = msrData[2]; DbgPrint( "[chipsec][IOCTL_WRMSR] WRMSR( 0x%x ) <-- 0x%08x%08x\n", _msr_addr, _edx, _eax ); // -- // -- write MSR // -- __try { _wrmsr( _msr_addr, _edx, _eax ); } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); break; } // -- // -- read MSR to check if it was written // -- // _rdmsr( _msr_addr, &_eax, &_edx ); // DbgPrint( "[chipsec][IOCTL_WRMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax ); Status = STATUS_SUCCESS; break; } case IOCTL_RDMSR: { UINT32 msrData[1]; UINT32 _eax = 0; UINT32 _edx = 0; UINT32 _msr_addr = 0; DbgPrint("[chipsec] > IOCTL_RDMSR\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; pOutBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec] ERROR: No input provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT32) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER - input buffer size < sizeof(BYTE) + sizeof(UINT32)\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id > _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][IOCTL_RDMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT32) ); _msr_addr = msrData[0]; __try { _rdmsr( _msr_addr, &_eax, &_edx ); } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); break; } DbgPrint( "[chipsec][IOCTL_RDMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax ); if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 2*sizeof(UINT32) ) { IrpSp->Parameters.Read.Length = 2*sizeof(UINT32); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&_eax, sizeof(UINT32) ); RtlCopyBytes( ((UINT8*)Irp->AssociatedIrp.SystemBuffer) + sizeof(UINT32), (VOID*)&_edx, sizeof(UINT32) ); dwBytesWritten = 2*sizeof(UINT32); Status = STATUS_SUCCESS; } else { DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2 UINT32\n" ); Status = STATUS_BUFFER_TOO_SMALL; } break; } case READ_IO_PORT: { DWORD value; BYTE size = 0; WORD io_port; DbgPrint( "[chipsec] > READ_IO_PORT\n" ); RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) ); RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(BYTE) ); if( 1 != size && 2 != size && 4 != size) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" ); Status = STATUS_INVALID_PARAMETER; break; } value = ReadIOPort( io_port, size ); IrpSp->Parameters.Read.Length = size; RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&value, size ); DbgPrint( "[chipsec][READ_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case WRITE_IO_PORT: { DWORD value = 0; WORD io_port = 0; BYTE size = 0; DbgPrint( "[chipsec] > WRITE_IO_PORT\n" ); RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) ); RtlCopyBytes( &value, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(DWORD) ); RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD) + sizeof(DWORD), sizeof(BYTE) ); DbgPrint( "[chipsec][WRITE_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size ); WriteIOPort( value, io_port, size ); Status = STATUS_SUCCESS; break; } case GET_CPU_DESCRIPTOR_TABLE: { BYTE dt_code = 0; DESCRIPTOR_TABLE_RECORD dtr; PDESCRIPTOR_TABLE_RECORD pdtr = &dtr; PHYSICAL_ADDRESS dt_pa; DbgPrint( "[chipsec] > GET_CPU_DESCRIPTOR_TABLE\n" ); RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) ); if( new_cpu_thread_id > _num_active_cpus ) new_cpu_thread_id = 0; KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() ); RtlCopyBytes( &dt_code, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(BYTE) ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table: %x\n", dt_code ); switch( dt_code ) { case CPU_DT_CODE_GDTR: { _store_gdtr( (void*)pdtr ); break; } case CPU_DT_CODE_LDTR: { _store_ldtr( (void*)pdtr ); break; } case CPU_DT_CODE_IDTR: default: { _store_idtr( (void*)pdtr ); break; } } DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table register contents:\n" ); _dump_buffer( (unsigned char *)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] IDTR: Limit = 0x%04x, Base = 0x%I64x\n", dtr.limit, dtr.base ); dt_pa = MmGetPhysicalAddress( (PVOID)dtr.base ); DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table PA: 0x%I64X (0x%08X_%08X)\n", dt_pa.QuadPart, dt_pa.HighPart, dt_pa.LowPart ); IrpSp->Parameters.Read.Length = sizeof(DESCRIPTOR_TABLE_RECORD) + sizeof(dt_pa.QuadPart); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) ); RtlCopyBytes( (UINT8*)Irp->AssociatedIrp.SystemBuffer + sizeof(DESCRIPTOR_TABLE_RECORD), (VOID*)&dt_pa.QuadPart, sizeof(dt_pa.QuadPart) ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } case IOCTL_SWSMI: { CPU_REG_TYPE gprs[6] = {0}; CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0; unsigned int _smi_code_data = 0; DbgPrint("[chipsec] > IOCTL_SWSMI\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec] ERROR: NO data provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT16) + sizeof(gprs) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(UINT16) + sizeof(gprs))\n" ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( &_smi_code_data, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT16) ); RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT16), sizeof(gprs) ); _rax = gprs[ 0 ]; _rbx = gprs[ 1 ]; _rcx = gprs[ 2 ]; _rdx = gprs[ 3 ]; _rsi = gprs[ 4 ]; _rdi = gprs[ 5 ]; DbgPrint( "[chipsec][IOCTL_SWSMI] SW SMI to ports 0x%X-0x%X <- 0x%04X\n", 0xB2, 0xB3, _smi_code_data ); DbgPrint( " RAX = 0x%I64x\n", _rax ); DbgPrint( " RBX = 0x%I64x\n", _rbx ); DbgPrint( " RCX = 0x%I64x\n", _rcx ); DbgPrint( " RDX = 0x%I64x\n", _rdx ); DbgPrint( " RSI = 0x%I64x\n", _rsi ); DbgPrint( " RDI = 0x%I64x\n", _rdi ); // -- // -- send SMI using port 0xB2 // -- __try { _swsmi( _smi_code_data, _rax, _rbx, _rcx, _rdx, _rsi, _rdi ); } __except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); break; } Status = STATUS_SUCCESS; break; } case IOCTL_CPUID: { DWORD CPUInfo[4] = {-1}; DWORD gprs[2] = {0}; DWORD _rax = 0, _rcx = 0; //CPU_REG_TYPE gprs[6]; //CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0; DbgPrint("[chipsec] > IOCTL_CPUID\n"); pInBuf = Irp->AssociatedIrp.SystemBuffer; if( !pInBuf ) { DbgPrint( "[chipsec] ERROR: NO data provided\n" ); Status = STATUS_INVALID_PARAMETER; break; } if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(gprs) ) { DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < %d)\n", sizeof(gprs) ); Status = STATUS_INVALID_PARAMETER; break; } RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(gprs) ); _rax = gprs[ 0 ]; _rcx = gprs[ 1 ]; DbgPrint( "[chipsec][IOCTL_CPUID] CPUID:\n" ); DbgPrint( " EAX = 0x%08X\n", _rax ); DbgPrint( " ECX = 0x%08X\n", _rcx ); __cpuidex( CPUInfo, _rax, _rcx ); DbgPrint( "[chipsec][IOCTL_CPUID] CPUID returned:\n" ); DbgPrint( " EAX = 0x%08X\n", CPUInfo[0] ); DbgPrint( " EBX = 0x%08X\n", CPUInfo[1] ); DbgPrint( " ECX = 0x%08X\n", CPUInfo[2] ); DbgPrint( " EDX = 0x%08X\n", CPUInfo[3] ); IrpSp->Parameters.Read.Length = sizeof(CPUInfo); RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)CPUInfo, sizeof(CPUInfo) ); dwBytesWritten = IrpSp->Parameters.Read.Length; Status = STATUS_SUCCESS; break; } default: DbgPrint( "[chipsec] ERROR: invalid IOCTL\n"); Status = STATUS_NOT_IMPLEMENTED; break; } // -- switch // -- restore current KAFFINITY KeSetSystemAffinityThread( _kaffinity ); DbgPrint( "[chipsec] Restored active CPU mask (KAFFINITY): 0x%08X\n", KeQueryActiveProcessors() ); DbgPrint( "[chipsec] Current CPU thread : %d\n", KeGetCurrentProcessorNumber() ); // -- // -- Complete the I/O request, Record the status of the I/O action. // -- Irp->IoStatus.Status = Status; Irp->IoStatus.Information = dwBytesWritten; DbgPrint( "[chipsec] Irp->IoStatus.Status = 0x%x, Irp->IoStatus.Information = 0x%x\n", Irp->IoStatus.Status, Irp->IoStatus.Information ); DbgPrint( "[chipsec]\n" ); IoCompleteRequest( Irp, IO_NO_INCREMENT ); return Status; }
NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { NTSTATUS status = STATUS_SUCCESS; KdPrint(("Enter HelloDDKDeviceIOControl\n")); //得到当前堆栈 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); //得到输入缓冲区大小 ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength; //得到输出缓冲区大小 ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength; //得到IOCTL码 ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; ULONG info = 0; switch (code) { // process request case READ_PORT: { KdPrint(("READ_PORT\n")); //缓冲区方式IOCTL //显示输入缓冲区数据 PULONG InputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; ULONG port = (ULONG)(*InputBuffer); InputBuffer++; UCHAR method = (UCHAR)(*InputBuffer); KdPrint(("port:%x\n",port)); KdPrint(("method:%x\n",method)); //操作输出缓冲区 PULONG OutputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; if (method==1)//8位操作 { *OutputBuffer = READ_PORT_UCHAR((PUCHAR)port); }else if(method==2)//16位操作 { *OutputBuffer = READ_PORT_USHORT((PUSHORT)port); }else if(method==4)//32位操作 { *OutputBuffer = READ_PORT_ULONG((PULONG)port); } //设置实际操作输出缓冲区长度 info = 4; break; } case WRITE_PORT: { KdPrint(("WRITE_PORT\n")); //缓冲区方式IOCTL //显示输入缓冲区数据 PULONG InputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; ULONG port = (ULONG)(*InputBuffer); InputBuffer++; UCHAR method = (UCHAR)(*InputBuffer); InputBuffer++; ULONG value = (ULONG)(*InputBuffer); KdPrint(("port:%x\n",port)); KdPrint(("method:%x\n",method)); KdPrint(("value:%x\n",value)); //操作输出缓冲区 PULONG OutputBuffer = (PULONG)pIrp->AssociatedIrp.SystemBuffer; if (method==1)//8位操作 { WRITE_PORT_UCHAR((PUCHAR)port,(UCHAR)value); }else if(method==2)//16位操作 { WRITE_PORT_USHORT((PUSHORT)port,(USHORT)value); }else if(method==4)//32位操作 { WRITE_PORT_ULONG((PULONG)port,(ULONG)value); } //设置实际操作输出缓冲区长度 info = 0; break; } default: status = STATUS_INVALID_VARIANT; } // 完成IRP pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = info; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("Leave HelloDDKDeviceIOControl\n")); return status; }
NTSTATUS HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; DEVICE_POWER_STATE deviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); deviceState = irpStack->Parameters.Power.State.DeviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Query for device power state D%X\n" "FBTUSB: HandleDeviceQueryPower: Current device power state D%X\n", deviceState - 1, deviceExtension->DevPower - 1)); if (deviceExtension->WaitWakeEnable && deviceState > deviceExtension->DeviceCapabilities.DeviceWake) { PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; } if (deviceState < deviceExtension->DevPower) { ntStatus = STATUS_SUCCESS; } else { ntStatus = HoldIoRequests(DeviceObject, Irp); if(STATUS_PENDING == ntStatus) { return ntStatus; } } // on error complete the Irp. // on success pass it to the lower layers PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; if(!NT_SUCCESS(ntStatus)) { IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { IoSkipCurrentIrpStackLocation(Irp); ntStatus=PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::")); FreeBT_IoDecrement(deviceExtension); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Leaving\n")); return ntStatus; }
NTSTATUS HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KIRQL oldIrql; NTSTATUS ntStatus; POWER_STATE newState; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; DEVICE_POWER_STATE newDevState, oldDevState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n")); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); oldDevState = deviceExtension->DevPower; newState = irpStack->Parameters.Power.State; newDevState = newState.DeviceState; FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n" "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n", newDevState - 1, deviceExtension->DevPower - 1)); if (newDevState < oldDevState) { FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n")); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } else { // newDevState >= oldDevState // hold I/O if transition from D0 -> DX (X = 1, 2, 3) // if transition from D1 or D2 to deeper sleep states, // I/O queue is already on hold. if(PowerDeviceD0 == oldDevState && newDevState > oldDevState) { // D0 -> DX transition FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Removing power from the device\n")); ntStatus = HoldIoRequests(DeviceObject, Irp); if (!NT_SUCCESS(ntStatus)) { PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; } else { goto HandleDeviceSetPower_Exit; } } else if (PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) { // D0 -> D0 // unblock the queue which may have been blocked processing // query irp FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: A SetD0 request\n")); KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql); deviceExtension->QueueState = AllowRequests; KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql); ProcessQueuedRequests(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n")); } } HandleDeviceSetPower_Exit: FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n")); return STATUS_PENDING; }
NTSTATUS NtfsCommonQueryVolumeInfo ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for query Volume Information called by both the fsd and fsp threads. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PFILE_OBJECT FileObject; TYPE_OF_OPEN TypeOfOpen; PVCB Vcb; PFCB Fcb; PSCB Scb; PCCB Ccb; ULONG Length; FS_INFORMATION_CLASS FsInformationClass; PVOID Buffer; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_IRP( Irp ); PAGED_CODE(); // // Get the current stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace( +1, Dbg, ("NtfsCommonQueryVolumeInfo...\n") ); DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) ); DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) ); DebugTrace( 0, Dbg, ("Length = %08lx\n", IrpSp->Parameters.QueryVolume.Length) ); DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass) ); DebugTrace( 0, Dbg, ("Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer) ); // // Reference our input parameters to make things easier // Length = IrpSp->Parameters.QueryVolume.Length; FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass; Buffer = Irp->AssociatedIrp.SystemBuffer; // // Extract and decode the file object to get the Vcb, we don't really // care what the type of open is. // FileObject = IrpSp->FileObject; TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE ); // // We need exclusive access to the Vcb because we are going to verify // it. After we verify the vcb we'll convert our access to shared // NtfsAcquireSharedVcb( IrpContext, Vcb, FALSE ); try { // // Based on the information class we'll do different actions. Each // of the procedures that we're calling fills up the output buffer // if possible and returns true if it successfully filled the buffer // and false if it couldn't wait for any I/O to complete. // switch (FsInformationClass) { case FileFsVolumeInformation: Status = NtfsQueryFsVolumeInfo( IrpContext, Vcb, Buffer, &Length ); break; case FileFsSizeInformation: Status = NtfsQueryFsSizeInfo( IrpContext, Vcb, Buffer, &Length ); break; case FileFsDeviceInformation: Status = NtfsQueryFsDeviceInfo( IrpContext, Vcb, Buffer, &Length ); break; case FileFsAttributeInformation: Status = NtfsQueryFsAttributeInfo( IrpContext, Vcb, Buffer, &Length ); break; #ifdef _CAIRO_ case FileFsControlInformation: Status = NtfsQueryFsControlInfo( IrpContext, Vcb, Buffer, &Length ); break; case FileFsQuotaQueryInformation: Status = NtfsFsQuotaQueryInfo( IrpContext, Vcb, Buffer, &Length ); break; #endif // _CAIRO_ default: Status = STATUS_INVALID_PARAMETER; break; } // // Set the information field to the number of bytes actually filled in // Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length; // // Abort transaction on error by raising. // NtfsCleanupTransaction( IrpContext, Status, FALSE ); } finally { DebugUnwind( NtfsCommonQueryVolumeInfo ); NtfsReleaseVcb( IrpContext, Vcb ); if (!AbnormalTermination()) { NtfsCompleteRequest( &IrpContext, &Irp, Status ); } DebugTrace( -1, Dbg, ("NtfsCommonQueryVolumeInfo -> %08lx\n", Status) ); } 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; }
__drv_mustHoldCriticalRegion NTSTATUS FFSMountVolume( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT MainDeviceObject; BOOLEAN GlobalDataResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; PDEVICE_OBJECT TargetDeviceObject; NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME; PDEVICE_OBJECT VolumeDeviceObject = NULL; PFFS_VCB Vcb; PFFS_SUPER_BLOCK FFSSb = NULL; ULONG dwBytes; DISK_GEOMETRY DiskGeometry; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); MainDeviceObject = IrpContext->DeviceObject; // // Make sure we can wait. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); // // This request is only allowed on the main device object // if (MainDeviceObject != FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &(FFSGlobal->Resource), TRUE); GlobalDataResourceAcquired = TRUE; if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING)) { Status = STATUS_UNRECOGNIZED_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); TargetDeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject; dwBytes = sizeof(DISK_GEOMETRY); Status = FFSDiskIoControl( TargetDeviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, &dwBytes); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } Status = IoCreateDevice( MainDeviceObject->DriverObject, sizeof(FFS_VCB), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &VolumeDeviceObject); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); if (TargetDeviceObject->AlignmentRequirement > VolumeDeviceObject->AlignmentRequirement) { VolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; } (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject = VolumeDeviceObject; Vcb = (PFFS_VCB)VolumeDeviceObject->DeviceExtension; RtlZeroMemory(Vcb, sizeof(FFS_VCB)); Vcb->Identifier.Type = FFSVCB; Vcb->Identifier.Size = sizeof(FFS_VCB); Vcb->TargetDeviceObject = TargetDeviceObject; Vcb->DiskGeometry = DiskGeometry; Status = FFSLoadDiskLabel(TargetDeviceObject, Vcb); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } FFSSb = Vcb->ffs_super_block; Vcb->BlockSize = FFSSb->fs_bsize; Vcb->SectorBits = FFSLog2(SECTOR_SIZE); Status = FFSInitializeVcb(IrpContext, Vcb, FFSSb, TargetDeviceObject, VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb); if (NT_SUCCESS(Status)) { if (FFSIsMediaWriteProtected(IrpContext, TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } SetFlag(Vcb->Flags, VCB_MOUNTED); FFSInsertVcb(Vcb); ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } } _SEH2_FINALLY { if (GlobalDataResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } if (!NT_SUCCESS(Status)) { if (FFSSb) { ExFreePool(FFSSb); } if (VolumeDeviceObject) { IoDeleteDevice(VolumeDeviceObject); } } if (!IrpContext->ExceptionInProgress) { if (NT_SUCCESS(Status)) { ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); } FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
static NTSTATUS CdfsMountVolume(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDEVICE_EXTENSION DeviceExt = NULL; PDEVICE_OBJECT NewDeviceObject = NULL; PDEVICE_OBJECT DeviceToMount; PIO_STACK_LOCATION Stack; PFCB Fcb = NULL; PCCB Ccb = NULL; PVPB Vpb; NTSTATUS Status; CDINFO CdInfo; DPRINT("CdfsMountVolume() called\n"); if (DeviceObject != CdfsGlobalData->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; goto ByeBye; } Stack = IoGetCurrentIrpStackLocation(Irp); DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; Vpb = Stack->Parameters.MountVolume.Vpb; Status = CdfsGetVolumeData(DeviceToMount, &CdInfo); if (!NT_SUCCESS(Status)) { goto ByeBye; } Status = IoCreateDevice(CdfsGlobalData->DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_CD_ROM_FILE_SYSTEM, DeviceToMount->Characteristics, FALSE, &NewDeviceObject); if (!NT_SUCCESS(Status)) goto ByeBye; NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO; NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME; DeviceExt = (PVOID)NewDeviceObject->DeviceExtension; RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION)); Vpb->SerialNumber = CdInfo.SerialNumber; Vpb->VolumeLabelLength = CdInfo.VolumeLabelLength; RtlCopyMemory(Vpb->VolumeLabel, CdInfo.VolumeLabel, CdInfo.VolumeLabelLength); RtlCopyMemory(&DeviceExt->CdInfo, &CdInfo, sizeof(CDINFO)); NewDeviceObject->Vpb = DeviceToMount->Vpb; DeviceExt->VolumeDevice = NewDeviceObject; DeviceExt->StorageDevice = DeviceToMount; DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject; DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; NewDeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; /* Close (and cleanup) might be called from IoCreateStreamFileObject * but we use this resource from CdfsCleanup, therefore it should be * initialized no later than this. */ ExInitializeResourceLite(&DeviceExt->DirResource); DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); Fcb = CdfsCreateFCB(NULL); if (Fcb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); if (Ccb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } RtlZeroMemory(Ccb, sizeof(CCB)); DeviceExt->StreamFileObject->ReadAccess = TRUE; DeviceExt->StreamFileObject->WriteAccess = FALSE; DeviceExt->StreamFileObject->DeleteAccess = FALSE; DeviceExt->StreamFileObject->FsContext = Fcb; DeviceExt->StreamFileObject->FsContext2 = Ccb; DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; DeviceExt->StreamFileObject->PrivateCacheMap = NULL; DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb; Ccb->PtrFileObject = DeviceExt->StreamFileObject; Fcb->FileObject = DeviceExt->StreamFileObject; Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; Fcb->Flags = FCB_IS_VOLUME_STREAM; Fcb->RFCB.FileSize.QuadPart = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE; Fcb->RFCB.ValidDataLength = Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize; Fcb->Entry.ExtentLocationL = 0; Fcb->Entry.DataLengthL = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE; CcInitializeCacheMap(DeviceExt->StreamFileObject, (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), TRUE, &(CdfsGlobalData->CacheMgrCallbacks), Fcb); ExInitializeResourceLite(&DeviceExt->VcbResource); KeInitializeSpinLock(&DeviceExt->FcbListLock); InitializeListHead(&DeviceExt->FcbListHead); FsRtlNotifyInitializeSync(&DeviceExt->NotifySync); InitializeListHead(&DeviceExt->NotifyList); Status = STATUS_SUCCESS; ByeBye: if (!NT_SUCCESS(Status)) { /* Cleanup */ if (DeviceExt && DeviceExt->StreamFileObject) ObDereferenceObject(DeviceExt->StreamFileObject); if (Fcb) ExFreePool(Fcb); if (NewDeviceObject) IoDeleteDevice(NewDeviceObject); } DPRINT("CdfsMountVolume() done (Status: %lx)\n", Status); return(Status); }
__drv_mustHoldCriticalRegion NTSTATUS FFSInvalidateVolumes( IN PFFS_IRP_CONTEXT IrpContext) { NTSTATUS Status; PIRP Irp; PIO_STACK_LOCATION IrpSp; HANDLE Handle; PLIST_ENTRY ListEntry; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; BOOLEAN GlobalResourceAcquired = FALSE; LUID Privilege = {SE_TCB_PRIVILEGE, 0}; _SEH2_TRY { Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) { Status = STATUS_PRIVILEGE_NOT_HELD; _SEH2_LEAVE; } if ( #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) IrpSp->Parameters.FileSystemControl.InputBufferLength #else ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))-> Parameters.FileSystemControl.InputBufferLength #endif != sizeof(HANDLE)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer; Status = ObReferenceObjectByHandle(Handle, 0, *IoFileObjectType, KernelMode, (void **)&FileObject, NULL); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } else { ObDereferenceObject(FileObject); DeviceObject = FileObject->DeviceObject; } FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FileObject=%xh ...\n", FileObject)); ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); GlobalResourceAcquired = TRUE; ListEntry = FFSGlobal->VcbList.Flink; while (ListEntry != &FFSGlobal->VcbList) { PFFS_VCB Vcb; Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next); ListEntry = ListEntry->Flink; FFSPrint((DBG_INFO, "FFSInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb)); if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject)) { ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSPurgeVolume...\n")); FFSPurgeVolume(Vcb, FALSE); ClearFlag(Vcb->Flags, VCB_MOUNTED); ExReleaseResourceLite(&Vcb->MainResource); // // Vcb is still attached on the list ...... // if (ListEntry->Blink == &Vcb->Next) { FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSCheckDismount...\n")); FFSCheckDismount(IrpContext, Vcb, FALSE); } } } } _SEH2_FINALLY { if (GlobalResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } FFSCompleteIrpContext(IrpContext, Status); } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSUserFsRequest( IN PFFS_IRP_CONTEXT IrpContext) { PIRP Irp; PIO_STACK_LOCATION IoStackLocation; ULONG FsControlCode; NTSTATUS Status; PAGED_CODE(); ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); #if !defined(_GNU_NTIFS_) || defined(__REACTOS__) FsControlCode = IoStackLocation->Parameters.FileSystemControl.FsControlCode; #else FsControlCode = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.FileSystemControl.FsControlCode; #endif switch (FsControlCode) { case FSCTL_LOCK_VOLUME: Status = FFSLockVolume(IrpContext); break; case FSCTL_UNLOCK_VOLUME: Status = FFSUnlockVolume(IrpContext); break; case FSCTL_DISMOUNT_VOLUME: Status = FFSDismountVolume(IrpContext); break; case FSCTL_IS_VOLUME_MOUNTED: Status = FFSIsVolumeMounted(IrpContext); break; case FSCTL_INVALIDATE_VOLUMES: Status = FFSInvalidateVolumes(IrpContext); break; #if (_WIN32_WINNT >= 0x0500) case FSCTL_ALLOW_EXTENDED_DASD_IO: Status = FFSAllowExtendedDasdIo(IrpContext); break; #endif //(_WIN32_WINNT >= 0x0500) default: FFSPrint((DBG_ERROR, "FFSUserFsRequest: Invalid User Request: %xh.\n", FsControlCode)); Status = STATUS_INVALID_DEVICE_REQUEST; FFSCompleteIrpContext(IrpContext, Status); } return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSUnlockVolume( IN PFFS_IRP_CONTEXT IrpContext) { PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT DeviceObject; NTSTATUS Status; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ASSERT(IsMounted(Vcb)); IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; Status = FFSUnlockVcb(Vcb, IrpSp->FileObject); } _SEH2_FINALLY { if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FFSVerifyVolume( IN PFFS_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFFS_SUPER_BLOCK FFSSb = NULL; PFFS_VCB Vcb = 0; BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN GlobalResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; ULONG ChangeCount; ULONG dwReturn; PAGED_CODE(); _SEH2_TRY { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == FFSICX) && (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (DeviceObject == FFSGlobal->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } ExAcquireResourceExclusiveLite( &FFSGlobal->Resource, TRUE); GlobalResourceAcquired = TRUE; Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == FFSVCB) && (Vcb->Identifier.Size == sizeof(FFS_VCB))); ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; } if (!IsMounted(Vcb)) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } dwReturn = sizeof(ULONG); Status = FFSDiskIoControl( Vcb->TargetDeviceObject, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &dwReturn); if (ChangeCount != Vcb->ChangeCount) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); if (((((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS1)) != NULL) && (FFSSb->fs_magic == FS_UFS1_MAGIC)) || (((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS2)) != NULL) && (FFSSb->fs_magic == FS_UFS2_MAGIC))) && (memcmp(FFSSb->fs_id, SUPER_BLOCK->fs_id, 8) == 0) && (memcmp(FFSSb->fs_volname, SUPER_BLOCK->fs_volname, 16) == 0)) { ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); if (FFSIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) { SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify succeeded.\n")); Status = STATUS_SUCCESS; } else { Status = STATUS_WRONG_VOLUME; FFSPurgeVolume(Vcb, FALSE); SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify failed.\n")); } } _SEH2_FINALLY { if (FFSSb) ExFreePool(FFSSb); if (VcbResourceAcquired) { ExReleaseResourceForThreadLite( &Vcb->MainResource, ExGetCurrentResourceThread()); } if (GlobalResourceAcquired) { ExReleaseResourceForThreadLite( &FFSGlobal->Resource, ExGetCurrentResourceThread()); } if (!IrpContext->ExceptionInProgress) { FFSCompleteIrpContext(IrpContext, Status); } } _SEH2_END; return Status; }
NTSTATUS RegisterPendingIrpMain( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in ULONG SerialNumber, __in PIRP_LIST IrpList, __in ULONG Flags, __in ULONG CheckMount ) { PIRP_ENTRY irpEntry; PIO_STACK_LOCATION irpSp; KIRQL oldIrql; DDbgPrint("==> DokanRegisterPendingIrpMain\n"); if (GetIdentifierType(DeviceObject->DeviceExtension) == VCB) { PDokanVCB vcb = DeviceObject->DeviceExtension; if (CheckMount && !vcb->Dcb->Mounted) { DDbgPrint(" device is not mounted\n"); return STATUS_INSUFFICIENT_RESOURCES; } } irpSp = IoGetCurrentIrpStackLocation(Irp); // Allocate a record and save all the event context. irpEntry = DokanAllocateIrpEntry(); if (NULL == irpEntry) { DDbgPrint(" can't allocate IRP_ENTRY\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(irpEntry, sizeof(IRP_ENTRY)); InitializeListHead(&irpEntry->ListEntry); irpEntry->SerialNumber = SerialNumber; irpEntry->FileObject = irpSp->FileObject; irpEntry->Irp = Irp; irpEntry->IrpSp = irpSp; irpEntry->IrpList = IrpList; irpEntry->Flags = Flags; DokanUpdateTimeout(&irpEntry->TickCount, DOKAN_IRP_PENDING_TIMEOUT); //DDbgPrint(" Lock IrpList.ListLock\n"); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); KeAcquireSpinLock(&IrpList->ListLock, &oldIrql); IoSetCancelRoutine(Irp, DokanIrpCancelRoutine); if (Irp->Cancel) { if (IoSetCancelRoutine(Irp, NULL) != NULL) { //DDbgPrint(" Release IrpList.ListLock %d\n", __LINE__); KeReleaseSpinLock(&IrpList->ListLock, oldIrql); DokanFreeIrpEntry(irpEntry); return STATUS_CANCELLED; } } IoMarkIrpPending(Irp); InsertTailList(&IrpList->ListHead, &irpEntry->ListEntry); irpEntry->CancelRoutineFreeMemory = FALSE; // save the pointer in order to be accessed by cancel routine Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_IRP_ENTRY] = irpEntry; KeSetEvent(&IrpList->NotEmpty, IO_NO_INCREMENT, FALSE); //DDbgPrint(" Release IrpList.ListLock\n"); KeReleaseSpinLock(&IrpList->ListLock, oldIrql); DDbgPrint("<== DokanRegisterPendingIrpMain\n"); return STATUS_PENDING;; }
NTSTATUS NTAPI PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PPCI_FDO_EXTENSION DeviceExtension; PIO_STACK_LOCATION IoStackLocation; PPCI_MJ_DISPATCH_TABLE IrpDispatchTable; BOOLEAN PassToPdo; NTSTATUS Status; PPCI_MN_DISPATCH_TABLE TableArray = NULL, Table; USHORT MaxMinor; PCI_DISPATCH_STYLE DispatchStyle = 0; PCI_DISPATCH_FUNCTION DispatchFunction = NULL; DPRINT1("PCI: Dispatch IRP\n"); /* Get the extension and I/O stack location for this IRP */ DeviceExtension = (PPCI_FDO_EXTENSION)DeviceObject->DeviceExtension; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); ASSERT((DeviceExtension->ExtensionType == PciPdoExtensionType) || (DeviceExtension->ExtensionType == PciFdoExtensionType)); /* Deleted extensions don't respond to IRPs */ if (DeviceExtension->DeviceState == PciDeleted) { /* Fail this IRP */ Status = STATUS_NO_SUCH_DEVICE; PassToPdo = FALSE; } else { /* Otherwise, get the dispatch table for the extension */ IrpDispatchTable = DeviceExtension->IrpDispatchTable; /* And choose which function table to use */ switch (IoStackLocation->MajorFunction) { case IRP_MJ_POWER: /* Power Manager IRPs */ TableArray = IrpDispatchTable->PowerIrpDispatchTable; MaxMinor = IrpDispatchTable->PowerIrpMaximumMinorFunction; break; case IRP_MJ_PNP: /* Plug-and-Play Manager IRPs */ TableArray = IrpDispatchTable->PnpIrpDispatchTable; MaxMinor = IrpDispatchTable->PnpIrpMaximumMinorFunction; break; case IRP_MJ_SYSTEM_CONTROL: /* WMI IRPs */ DispatchFunction = IrpDispatchTable->SystemControlIrpDispatchFunction; DispatchStyle = IrpDispatchTable->SystemControlIrpDispatchStyle; MaxMinor = 0xFFFF; break; default: /* Unrecognized IRPs */ DispatchFunction = IrpDispatchTable->OtherIrpDispatchFunction; DispatchStyle = IrpDispatchTable->OtherIrpDispatchStyle; MaxMinor = 0xFFFF; break; } /* Only deal with recognized IRPs */ if (MaxMinor != 0xFFFF) { /* Make sure the function is recognized */ if (IoStackLocation->MinorFunction > MaxMinor) { /* Pick the terminator, which should return unrecognized */ Table = &TableArray[MaxMinor + 1]; } else { /* Pick the appropriate table for this function */ Table = &TableArray[IoStackLocation->MinorFunction]; } /* From that table, get the function code and dispatch style */ DispatchStyle = Table->DispatchStyle; DispatchFunction = Table->DispatchFunction; } /* Print out debugging information, and see if we should break */ if (PciDebugIrpDispatchDisplay(IoStackLocation, DeviceExtension, MaxMinor)) { /* The developer/user wants us to break for this IRP, do it */ DbgBreakPoint(); } /* Check if this IRP should be sent up the stack first */ if (DispatchStyle == IRP_UPWARD) { /* Do it now before handling it ourselves */ PciCallDownIrpStack(DeviceExtension, Irp); } /* Call the our driver's handler for this IRP and deal with the IRP */ Status = DispatchFunction(Irp, IoStackLocation, DeviceExtension); switch (DispatchStyle) { /* Complete IRPs are completely immediately by our driver */ case IRP_COMPLETE: PassToPdo = FALSE; break; /* Downward IRPs are send to the attached FDO */ case IRP_DOWNWARD: PassToPdo = TRUE; break; /* Upward IRPs are completed immediately by our driver */ case IRP_UPWARD: PassToPdo = FALSE; break; /* Dispatch IRPs are immediately returned */ case IRP_DISPATCH: return Status; /* There aren't any other dispatch styles! */ default: ASSERT(FALSE); return Status; } } /* Pending IRPs are returned immediately */ if (Status == STATUS_PENDING) return Status; /* Handled IRPs return their status in the status block */ if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status; /* Successful, or unhandled IRPs that are "DOWNWARD" are sent to the PDO */ if ((PassToPdo) && ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))) { /* Let the PDO deal with it */ Status = PciPassIrpFromFdoToPdo(DeviceExtension, Irp); } else { /* Otherwise, the IRP is returned with its status */ Status = Irp->IoStatus.Status; /* Power IRPs need to notify the Power Manager that the next IRP can go */ if (IoStackLocation->MajorFunction == IRP_MJ_POWER) PoStartNextPowerIrp(Irp); /* And now this IRP can be completed */ IoCompleteRequest(Irp, IO_NO_INCREMENT); } /* And the status returned back to the caller */ return Status; }
static NTSTATUS CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDEVICE_EXTENSION DeviceExt; PIO_STACK_LOCATION Stack; NTSTATUS Status; CDINFO CdInfo; PLIST_ENTRY Entry; PFCB Fcb; PVPB VpbToVerify; DPRINT1 ("CdfsVerifyVolume() called\n"); DeviceExt = DeviceObject->DeviceExtension; Stack = IoGetCurrentIrpStackLocation (Irp); VpbToVerify = Stack->Parameters.VerifyVolume.Vpb; FsRtlEnterFileSystem(); ExAcquireResourceExclusiveLite (&DeviceExt->VcbResource, TRUE); if (!(VpbToVerify->RealDevice->Flags & DO_VERIFY_VOLUME)) { DPRINT1 ("Volume has been verified!\n"); ExReleaseResourceLite (&DeviceExt->VcbResource); FsRtlExitFileSystem(); return STATUS_SUCCESS; } DPRINT1("Device object %p Device to verify %p\n", DeviceObject, VpbToVerify->RealDevice); Status = CdfsGetVolumeData(VpbToVerify->RealDevice, &CdInfo); if (NT_SUCCESS(Status) && CdInfo.SerialNumber == VpbToVerify->SerialNumber && CdInfo.VolumeLabelLength == VpbToVerify->VolumeLabelLength && !wcsncmp(CdInfo.VolumeLabel, VpbToVerify->VolumeLabel, CdInfo.VolumeLabelLength)) { DPRINT1 ("Same volume!\n"); /* FIXME: Flush and purge metadata */ Status = STATUS_SUCCESS; } else { DPRINT1 ("Different volume!\n"); /* FIXME: force volume dismount */ Entry = DeviceExt->FcbListHead.Flink; while (Entry != &DeviceExt->FcbListHead) { Fcb = (PFCB)CONTAINING_RECORD(Entry, FCB, FcbListEntry); DPRINT1("OpenFile %wZ RefCount %ld\n", &Fcb->PathName, Fcb->RefCount); Entry = Entry->Flink; } Status = STATUS_WRONG_VOLUME; } VpbToVerify->RealDevice->Flags &= ~DO_VERIFY_VOLUME; ExReleaseResourceLite (&DeviceExt->VcbResource); FsRtlExitFileSystem(); return Status; }
/*! * \brief Entry point for IRP_MJ_DEVICE_CONTROL.<br> * <br> * set kernel-mode events for exchanging message with user-mode application.<br> * or <br> * pass all IOCTL requests to the SmartcardDeviceControl (WDM) driver library routine.<br> * http://msdn2.microsoft.com/en-us/library/ms801443.aspx * <br> * \param [in] pDriverObject Caller-supplied pointer to a DRIVER_OBJECT structure. This is the driver's driver object. * \param [in] pIrp Caller-supplied pointer to an IRP structure that describes the requested I/O operation. * * \retval STATUS_SUCCESS the routine successfully end. */ NTSTATUS VR_IoControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) { dbg_log("VR_IoControl start"); NTSTATUS status = STATUS_NOT_SUPPORTED; PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; PIO_STACK_LOCATION pIoStackIrp = IoGetCurrentIrpStackLocation(pIrp); if (!pIoStackIrp) { status = STATUS_INSUFFICIENT_RESOURCES; goto IOCTL_FUNC_END; } if (pIoStackIrp->Parameters.DeviceIoControl.IoControlCode == IOCTL_JCOP_PROXY_SET_EVENTS) { // set events IO control code. PJCOP_PROXY_SHARED_EVENTS pEvents; dbg_log("IOCTL_SET_EVENTS\n"); dbg_log( "pIoStackIrp->Parameters.DeviceIoControl.IoControlCode: 0x%08X", pIoStackIrp->Parameters.DeviceIoControl.IoControlCode ); if (pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength < sizeof(JCOP_PROXY_SHARED_EVENTS)) { dbg_log("pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength < sizeof(JCOP_PROXY_SHARED_EVENTS)"); status = STATUS_INVALID_PARAMETER; return status; } pEvents = (PJCOP_PROXY_SHARED_EVENTS)pIrp->AssociatedIrp.SystemBuffer; PSMARTCARD_EXTENSION pSmartcardExtension = &pDeviceExtension->smartcardExtension; PREADER_EXTENSION pReaderExtension = pSmartcardExtension->ReaderExtension; // set kernel-mode event for sending data. dbg_log("pEvents->hEventSnd: 0x%08X", pEvents->hEventSnd); status = ObReferenceObjectByHandle(pEvents->hEventSnd, SYNCHRONIZE, *ExEventObjectType, pIrp->RequestorMode, &pReaderExtension->hEventSnd, NULL ); if (status != STATUS_SUCCESS) { dbg_log("ObReferenceObjectByHandle failed! - status: 0x%08X", status); return status; } dbg_log("pReaderExtension->hEventSnd: 0x%08X", pReaderExtension->hEventSnd); // set user-mode event for reciving data. dbg_log("pEvents->hEventRcv: 0x%08X", pEvents->hEventRcv); status = ObReferenceObjectByHandle(pEvents->hEventRcv, SYNCHRONIZE, *ExEventObjectType, pIrp->RequestorMode, &pReaderExtension->hEventRcv, NULL ); if (status != STATUS_SUCCESS) { dbg_log("ObReferenceObjectByHandle failed! - status: 0x%08X", status); return status; } dbg_log("pReaderExtension->hEventRcv: 0x%08X", pReaderExtension->hEventRcv); status = STATUS_SUCCESS; pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } else { // smart card related IO control code. PSMARTCARD_EXTENSION pSmartcardExtension = &pDeviceExtension->smartcardExtension; switch (pSmartcardExtension->MajorIoControlCode) { case IOCTL_SMARTCARD_POWER : dbg_log("IOCTL_SMARTCARD_POWER"); break; case IOCTL_SMARTCARD_GET_ATTRIBUTE : dbg_log("IOCTL_SMARTCARD_GET_ATTRIBUTE"); break; case IOCTL_SMARTCARD_SET_ATTRIBUTE : dbg_log("IOCTL_SMARTCARD_SET_ATTRIBUTE"); break; case IOCTL_SMARTCARD_CONFISCATE : dbg_log("IOCTL_SMARTCARD_CONFISCATE"); break; case IOCTL_SMARTCARD_TRANSMIT : dbg_log("IOCTL_SMARTCARD_TRANSMIT"); break; case IOCTL_SMARTCARD_EJECT : dbg_log("IOCTL_SMARTCARD_EJECT"); break; case IOCTL_SMARTCARD_SWALLOW : dbg_log("IOCTL_SMARTCARD_SWALLOW"); break; case IOCTL_SMARTCARD_IS_PRESENT : dbg_log("IOCTL_SMARTCARD_IS_PRESENT"); break; case IOCTL_SMARTCARD_IS_ABSENT : dbg_log("IOCTL_SMARTCARD_IS_ABSENT"); break; case IOCTL_SMARTCARD_SET_PROTOCOL : dbg_log("IOCTL_SMARTCARD_SET_PROTOCOL"); break; case IOCTL_SMARTCARD_GET_STATE : dbg_log("IOCTL_SMARTCARD_GET_STATE"); break; case IOCTL_SMARTCARD_GET_LAST_ERROR : dbg_log("IOCTL_SMARTCARD_GET_LAST_ERROR"); break; case IOCTL_SMARTCARD_GET_PERF_CNTR : dbg_log("IOCTL_SMARTCARD_GET_PERF_CNTR"); break; default : dbg_log("IOCTL_XXXXX(unknown): 0x%08X", pSmartcardExtension->MajorIoControlCode); } // SmartcardAcquireRemoveLock should be called whenever an entry-point // routine to the driver is called (for example, whenever the device I/O // control routine is called). SmartcardAcquireRemoveLock makes sure that // the driver does not unload while other driver code is being executed. // http://msdn2.microsoft.com/en-us/library/ms801336.aspx status = STATUS_SUCCESS; status = SmartcardAcquireRemoveLock(pSmartcardExtension); if (status != STATUS_SUCCESS) { dbg_log("SmartcardAcquireRemoveLock failed! - status: 0x%08X", status); pSmartcardExtension->IoRequest.Information = 0; return status; } // pass all IOCTL requests to the SmartcardDeviceControl (WDM) driver library routine. // http://msdn2.microsoft.com/en-us/library/ms801443.aspx status = SmartcardDeviceControl(pSmartcardExtension, pIrp); dbg_log("SmartcardDeviceControl returned - status: 0x%08X", status); SmartcardReleaseRemoveLock(pSmartcardExtension); } IOCTL_FUNC_END: dbg_log("VR_IoControl end - status: 0x%08X", status); return status; }
NTSTATUS FltDevIoControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { // 假设失败 NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; // 取得此IRP(pIrp)的I/O堆栈指针 PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); // 取得I/O控制代码 ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; // 取得I/O缓冲区指针和它的长度 PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; ULONG uTransLen = 0; PADAPT pAdapt = NULL; PADAPT_FILTER_RSVD pFilterContext = NULL; POPEN_CONTEXT pOpenContext = pIrpStack->FileObject->FsContext; if(pOpenContext == NULL || (pAdapt = pOpenContext->pAdapt) == NULL) { status = STATUS_INVALID_HANDLE; goto CompleteTheIRP; } pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved; // // Fail IOCTL If Unbind Is In Progress Fail IOCTL If Adapter Is Powering Down // NdisAcquireSpinLock(&pAdapt->Lock); if( pAdapt->UnbindingInProcess || pAdapt->StandingBy == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); status = STATUS_INVALID_DEVICE_STATE; goto CompleteTheIRP; } // 当改变数据时,要拥有SpinLock // 最后,处理IO控制代码 switch(uIoControlCode) { case IOCTL_PTUSERIO_QUERY_STATISTICS: // 获取网络活动状态 { uTransLen = sizeof(PassthruStatistics); if(uOutSize < uTransLen) { status = STATUS_BUFFER_TOO_SMALL; break; } NdisMoveMemory(pIoBuffer, &pFilterContext->Statistics, uTransLen); status = STATUS_SUCCESS; } break; case IOCTL_PTUSERIO_RESET_STATISTICS: // 重设网络活动状态 { NdisZeroMemory(&pFilterContext->Statistics, sizeof(PassthruStatistics)); status = STATUS_SUCCESS; } break; case IOCTL_PTUSERIO_ADD_FILTER: // 添加一个过滤规则 { if(uInSize >= sizeof(PassthruFilter)) { DBGPRINT((" 添加一个过滤规则")); status = AddFilterToAdapter(pFilterContext, (PPassthruFilter)pIoBuffer); } else { status = STATUS_INVALID_DEVICE_REQUEST; } } break; case IOCTL_PTUSERIO_CLEAR_FILTER: // 清除过滤规则 { DBGPRINT((" 清除过滤规则")); ClearFilterList(pFilterContext); status = STATUS_SUCCESS; } break; } NdisReleaseSpinLock(&pAdapt->Lock); CompleteTheIRP: if(status == STATUS_SUCCESS) pIrp->IoStatus.Information = uTransLen; else pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; }
NTSTATUS NtfsCommonSetVolumeInfo ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for set Volume Information called by both the fsd and fsp threads. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PMyIO_STACK_LOCATION IrpSp; PFILE_OBJECT FileObject; TYPE_OF_OPEN TypeOfOpen; PVCB Vcb; PFCB Fcb; PSCB Scb; PCCB Ccb; ULONG Length; FS_INFORMATION_CLASS FsInformationClass; PVOID Buffer; ASSERT_IRP_CONTEXT( IrpContext ); ASSERT_IRP( Irp ); PAGED_CODE(); // // Get the current Irp stack location // IrpSp = (PMyIO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); DebugTrace( +1, Dbg, ("NtfsCommonSetVolumeInfo\n") ); DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) ); DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) ); DebugTrace( 0, Dbg, ("Length = %08lx\n", IrpSp->Parameters.SetVolume.Length) ); DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.SetVolume.FsInformationClass) ); DebugTrace( 0, Dbg, ("Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer) ); // // Reference our input parameters to make things easier // Length = IrpSp->Parameters.SetVolume.Length; FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass; Buffer = Irp->AssociatedIrp.SystemBuffer; // // Extract and decode the file object to get the Vcb, we don't really // care what the type of open is. // FileObject = IrpSp->FileObject; TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE ); if (TypeOfOpen != UserVolumeOpen) { NtfsCompleteRequest( &IrpContext, &Irp, STATUS_ACCESS_DENIED ); DebugTrace( -1, Dbg, ("NtfsCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n") ); return STATUS_ACCESS_DENIED; } // // Acquire exclusive access to the Vcb // NtfsAcquireExclusiveVcb( IrpContext, Vcb, TRUE ); try { // // Proceed only if the volume is mounted. // if (FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) { // // Based on the information class we'll do different actions. Each // of the procedures that we're calling performs the action if // possible and returns true if it successful and false if it couldn't // wait for any I/O to complete. // switch (FsInformationClass) { case FileFsLabelInformation: Status = NtfsSetFsLabelInfo( IrpContext, Vcb, Buffer ); break; #ifdef _CAIRO_ case FileFsQuotaSetInformation: Status = NtfsFsQuotaSetInfo( IrpContext, Vcb, Buffer, Length ); break; case FileFsControlInformation: Status = NtfsSetFsControlInfo( IrpContext, Vcb, Buffer ); break; #endif // _CAIRO_ default: Status = STATUS_INVALID_PARAMETER; break; } } else { Status = STATUS_FILE_INVALID; } // // Abort transaction on error by raising. // NtfsCleanupTransaction( IrpContext, Status, FALSE ); } finally { DebugUnwind( NtfsCommonSetVolumeInfo ); NtfsReleaseVcb( IrpContext, Vcb ); if (!AbnormalTermination()) { NtfsCompleteRequest( &IrpContext, &Irp, Status ); } DebugTrace( -1, Dbg, ("NtfsCommonSetVolumeInfo -> %08lx\n", Status) ); } return Status; }
//-------------------------------------------------------------------------------------- NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS ns = STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG InSize = 0, OutSize = 0; Irp->IoStatus.Status = ns; Irp->IoStatus.Information = 0; if (stack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { // get IOCTL parameters ULONG Code = stack->Parameters.DeviceIoControl.IoControlCode; PREQUEST_BUFFER Buff = (PREQUEST_BUFFER)Irp->AssociatedIrp.SystemBuffer; InSize = stack->Parameters.DeviceIoControl.InputBufferLength; OutSize = stack->Parameters.DeviceIoControl.OutputBufferLength; DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): IRP_MJ_DEVICE_CONTROL 0x%.8x\n", Code); // check buffer length if (InSize >= sizeof(REQUEST_BUFFER) && OutSize >= sizeof(REQUEST_BUFFER)) { switch (Code) { case IOCTL_DRV_CONTROL: { switch (Buff->Code) { case DRV_CTL_NONE: { // do nothing, just return successful status ns = STATUS_SUCCESS; break; } case DRV_CTL_VIRT_MEM_READ: { if (InSize >= sizeof(REQUEST_BUFFER) + Buff->MemRead.Size) { // read virtual memory memcpy( Buff->MemRead.Data, (PVOID)Buff->MemRead.Address, Buff->MemRead.Size ); ns = STATUS_SUCCESS; } break; } case DRV_CTL_VIRT_MEM_WRITE: { if (InSize >= sizeof(REQUEST_BUFFER) + Buff->MemWrite.Size) { // write virtual memory memcpy( (PVOID)Buff->MemWrite.Address, Buff->MemWrite.Data, Buff->MemWrite.Size ); ns = STATUS_SUCCESS; } break; } case DRV_CTL_PHYS_MEM_READ: { if (InSize >= sizeof(REQUEST_BUFFER) + Buff->MemRead.Size) { // read physical memory ns = HwPhysMemRead( Buff->MemRead.Address, Buff->MemRead.Size, Buff->MemRead.Data ); } break; } case DRV_CTL_PHYS_MEM_WRITE: { if (InSize >= sizeof(REQUEST_BUFFER) + Buff->MemWrite.Size) { // write physical memory ns = HwPhysMemWrite( Buff->MemWrite.Address, Buff->MemWrite.Size, Buff->MemWrite.Data ); } break; } case DRV_CTL_PORT_READ: { // read I/O port value ns = HwPortRead(Buff->PortRead.Port, Buff->PortRead.Size, &Buff->PortRead.Val); break; } case DRV_CTL_PORT_WRITE: { // write value to I/O port ns = HwPortWrite(Buff->PortWrite.Port, Buff->PortWrite.Size, Buff->PortWrite.Val); break; } case DRV_CTL_PCI_READ: { // read PCI config space register value ns = HwPciRead(Buff->PciRead.Address, Buff->PciRead.Size, &Buff->PciRead.Val); break; } case DRV_CTL_PCI_WRITE: { // write value to PCI config space egister ns = HwPciWrite(Buff->PciWrite.Address, Buff->PciWrite.Size, Buff->PciWrite.Val); break; } case DRV_CTL_SMI_INVOKE: { // invoke SMI via APMC I/O port ns = HwSmiInvoke(Buff->SmiInvoke.Code); break; } case DRV_CTL_MEM_ALLOC: { // allocate memory if ((ns = HwMemAlloc(&Buff->MemAlloc.Address, Buff->MemAlloc.Size)) == STATUS_SUCCESS) { // get physical address by virtual ns = HwGetPhysAddr(Buff->MemAlloc.Address, &Buff->MemAlloc.PhysicalAddress); } break; } case DRV_CTL_MEM_FREE: { // free allocated memory ns = HwMemFree(Buff->MemFree.Address); break; } case DRV_CTL_PHYS_ADDR: { // get physical address by virtual ns = HwGetPhysAddr(Buff->PhysAddr.Address, &Buff->PhysAddr.PhysicalAddress); break; } case DRV_CTL_MSR_GET: { // get MSR value ns = HwMsrGet(Buff->MsrGet.Register, &Buff->MsrGet.Value); break; } case DRV_CTL_MSR_SET: { // set MSR value ns = HwMsrSet(Buff->MsrSet.Register, Buff->MsrSet.Value); break; } #ifdef USE_DSE_BYPASS case DRV_CTL_RESTORE_CR4: { // get bitmask of active processors KAFFINITY ActiveProcessors = KeQueryActiveProcessors(); ULONG cr4_val = 0, cr4_current = 0; // enumerate active processors starting from 2-nd for (KAFFINITY i = 1; i < sizeof(KAFFINITY) * 8; i++) { KAFFINITY Mask = 1 << i; if (ActiveProcessors & Mask) { // bind thread to specific processor KeSetSystemAffinityThread(Mask); // read CR4 register of other CPU cr4_val = _cr4_get(); break; } } if (cr4_val != 0) { // bind thread to first processor KeSetSystemAffinityThread(0x00000001); if ((cr4_current = _cr4_get()) != cr4_val) { DbgMsg(__FILE__, __LINE__, "Restoring CR4 value from 0x%.8x to 0x%.8x\n", cr4_current, cr4_val); // restore CR4 register of current CPU _cr4_set(cr4_val); } else { DbgMsg(__FILE__, __LINE__, "CR4 is 0x%.8x\n", cr4_current); } ns = STATUS_SUCCESS; } else { DbgMsg(__FILE__, __LINE__, "ERROR: Unable to read CR4 value from 2-nd processor\n"); } break; } #endif // USE_DSE_BYPASS default: { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): Unknown control code 0x%x\n", Code); break; } } break; } default: { break; } } } if (ns == STATUS_SUCCESS) { Irp->IoStatus.Information = InSize; } } else if (stack->MajorFunction == IRP_MJ_CREATE) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): IRP_MJ_CREATE\n"); ns = STATUS_SUCCESS; } else if (stack->MajorFunction == IRP_MJ_CLOSE) { DbgMsg(__FILE__, __LINE__, __FUNCTION__"(): IRP_MJ_CLOSE\n"); ns = STATUS_SUCCESS; } if (ns != STATUS_PENDING) { Irp->IoStatus.Status = ns; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return ns; }
// Handle power events NTSTATUS FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; PUNICODE_STRING tagString; PDEVICE_EXTENSION deviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; // We don't queue power Irps, we'll only check if the // device was removed, otherwise we'll take appropriate // action and send it to the next lower driver. In general // drivers should not cause long delays while handling power // IRPs. If a driver cannot handle a power IRP in a brief time, // it should return STATUS_PENDING and queue all incoming // IRPs until the IRP completes. if (Removed == deviceExtension->DeviceState) { // Even if a driver fails the IRP, it must nevertheless call // PoStartNextPowerIrp to inform the Power Manager that it // is ready to handle another power IRP. PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } if (NotStarted == deviceExtension->DeviceState) { // if the device is not started yet, pass it down PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::")); FreeBT_IoIncrement(deviceExtension); switch(irpStack->MinorFunction) { case IRP_MN_SET_POWER: // The Power Manager sends this IRP for one of the // following reasons: // 1) To notify drivers of a change to the system power state. // 2) To change the power state of a device for which // the Power Manager is performing idle detection. // A driver sends IRP_MN_SET_POWER to change the power // state of its device if it's a power policy owner for the // device. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_SET_POWER\n")); IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_QUERY_POWER: // The Power Manager sends a power IRP with the minor // IRP code IRP_MN_QUERY_POWER to determine whether it // can safely change to the specified system power state // (S1-S5) and to allow drivers to prepare for such a change. // If a driver can put its device in the requested state, // it sets status to STATUS_SUCCESS and passes the IRP down. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_QUERY_POWER\n")); IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_WAIT_WAKE: // The minor power IRP code IRP_MN_WAIT_WAKE provides // for waking a device or waking the system. Drivers // of devices that can wake themselves or the system // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE // only to devices that always wake the system, such as // the power-on switch. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE\n")); IoMarkIrpPending(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); PoStartNextPowerIrp(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: Lower drivers failed the wait-wake Irp\n")); } ntStatus = STATUS_PENDING; // push back the count HERE and NOT in completion routine // a pending Wait Wake Irp should not impede stopping the device FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE::")); FreeBT_IoDecrement(deviceExtension); break; case IRP_MN_POWER_SEQUENCE: // A driver sends this IRP as an optimization to determine // whether its device actually entered a specific power state. // This IRP is optional. Power Manager cannot send this IRP. FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_POWER_SEQUENCE\n")); default: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchPower: Lower drivers failed this Irp\n")); } FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::")); FreeBT_IoDecrement(deviceExtension); break; } return ntStatus; }
NTSTATUS TiCreateFileObject( PDEVICE_OBJECT DeviceObject, PIRP Irp) { PFILE_FULL_EA_INFORMATION EaInfo; PTRANSPORT_CONTEXT Context; PIO_STACK_LOCATION IrpSp; PTA_IP_ADDRESS Address; TDI_REQUEST Request; PVOID ClientContext; NTSTATUS Status; ULONG Protocol; BOOLEAN Shared; TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp)); EaInfo = Irp->AssociatedIrp.SystemBuffer; /* Parameter check */ /* No EA information means that we're opening for SET/QUERY_INFORMATION * style calls. */ /* Allocate resources here. We release them again if something failed */ Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSPORT_CONTEXT), TRANS_CONTEXT_TAG); if (!Context) { TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); return STATUS_INSUFFICIENT_RESOURCES; } Context->CancelIrps = FALSE; IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp->FileObject->FsContext = Context; Request.RequestContext = Irp; /* Branch to the right handler */ if (EaInfo && (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) && (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) { /* This is a request to open an address */ /* XXX This should probably be done in IoCreateFile() */ /* Parameter checks */ Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term if ((EaInfo->EaValueLength < sizeof(TA_IP_ADDRESS)) || (Address->TAAddressCount != 1) || (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) || (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP)) { TI_DbgPrint(MIN_TRACE, ("Parameters are invalid:\n")); TI_DbgPrint(MIN_TRACE, ("AddressCount: %d\n", Address->TAAddressCount)); if( Address->TAAddressCount == 1 ) { TI_DbgPrint(MIN_TRACE, ("AddressLength: %u\n", Address->Address[0].AddressLength)); TI_DbgPrint(MIN_TRACE, ("AddressType: %u\n", Address->Address[0].AddressType)); } ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG); return STATUS_INVALID_PARAMETER; } /* Open address file object */ /* Protocol depends on device object so find the protocol */ if (DeviceObject == TCPDeviceObject) Protocol = IPPROTO_TCP; else if (DeviceObject == UDPDeviceObject) Protocol = IPPROTO_UDP; else if (DeviceObject == IPDeviceObject) Protocol = IPPROTO_RAW; else if (DeviceObject == RawIPDeviceObject) { Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol); if (!NT_SUCCESS(Status)) { TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n")); ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG); return STATUS_INVALID_PARAMETER; } } else { TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject)); ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG); return STATUS_INVALID_PARAMETER; } Shared = (IrpSp->Parameters.Create.ShareAccess != 0); Status = FileOpenAddress(&Request, Address, Protocol, Shared, NULL); if (NT_SUCCESS(Status)) { IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE; Context->Handle.AddressHandle = Request.Handle.AddressHandle; } } else if (EaInfo && (EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) && (RtlCompareMemory (&EaInfo->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) == TDI_CONNECTION_CONTEXT_LENGTH)) { /* This is a request to open a connection endpoint */ /* Parameter checks */ if (EaInfo->EaValueLength < sizeof(PVOID)) { TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n")); ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG); return STATUS_INVALID_PARAMETER; } /* Can only do connection oriented communication using TCP */ if (DeviceObject != TCPDeviceObject) { TI_DbgPrint(MIN_TRACE, ("Bad device object.\n")); ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG); return STATUS_INVALID_PARAMETER; } ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength)); /* Open connection endpoint file object */ Status = FileOpenConnection(&Request, ClientContext); if (NT_SUCCESS(Status)) { IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE; Context->Handle.ConnectionContext = Request.Handle.ConnectionContext; } } else { /* This is a request to open a control connection */ Status = FileOpenControlChannel(&Request); if (NT_SUCCESS(Status)) { IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE; Context->Handle.ControlChannel = Request.Handle.ControlChannel; } } if (!NT_SUCCESS(Status)) ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status)); Irp->IoStatus.Status = Status; return Status; }
VOID SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp ) { NTSTATUS ntStatus; POWER_STATE powState; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; SYSTEM_POWER_STATE systemState; DEVICE_POWER_STATE devState; PPOWER_COMPLETION_CONTEXT powerContext; irpStack = IoGetCurrentIrpStackLocation(SIrp); systemState = irpStack->Parameters.Power.State.SystemState; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\n")); // Read out the D-IRP out of the S->D mapping array captured in QueryCap's. // we can choose deeper sleep states than our mapping but never choose // lighter ones. devState = deviceExtension->DeviceCapabilities.DeviceState[systemState]; powState.DeviceState = devState; powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT)); if (!powerContext) { FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: Failed to alloc memory for powerContext\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } else { powerContext->DeviceObject = DeviceObject; powerContext->SIrp = SIrp; // in win2k PoRequestPowerIrp can take fdo or pdo. ntStatus = PoRequestPowerIrp( deviceExtension->PhysicalDeviceObject, irpStack->MinorFunction, powState, (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine, powerContext, NULL); } if (!NT_SUCCESS(ntStatus)) { if (powerContext) { ExFreePool(powerContext); } PoStartNextPowerIrp(SIrp); SIrp->IoStatus.Status = ntStatus; SIrp->IoStatus.Information = 0; IoCompleteRequest(SIrp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::")); FreeBT_IoDecrement(deviceExtension); } FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n")); }
NTSTATUS NTAPI TiDispatchInternal( PDEVICE_OBJECT DeviceObject, PIRP Irp) /* * FUNCTION: Internal IOCTL dispatch routine * ARGUMENTS: * DeviceObject = Pointer to a device object for this driver * Irp = Pointer to a I/O request packet * RETURNS: * Status of the operation */ { NTSTATUS Status; BOOLEAN Complete = TRUE; PIO_STACK_LOCATION IrpSp; IrpSp = IoGetCurrentIrpStackLocation(Irp); TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n", DeviceObject, Irp, IrpSp->MinorFunction)); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; switch (IrpSp->MinorFunction) { case TDI_RECEIVE: Status = DispTdiReceive(Irp); Complete = FALSE; break; case TDI_RECEIVE_DATAGRAM: Status = DispTdiReceiveDatagram(Irp); Complete = FALSE; break; case TDI_SEND: Status = DispTdiSend(Irp); Complete = FALSE; /* Completed in DispTdiSend */ break; case TDI_SEND_DATAGRAM: Status = DispTdiSendDatagram(Irp); Complete = FALSE; break; case TDI_ACCEPT: Status = DispTdiAccept(Irp); break; case TDI_LISTEN: Status = DispTdiListen(Irp); Complete = FALSE; break; case TDI_CONNECT: Status = DispTdiConnect(Irp); Complete = FALSE; /* Completed by the TCP event handler */ break; case TDI_DISCONNECT: Status = DispTdiDisconnect(Irp); Complete = FALSE; break; case TDI_ASSOCIATE_ADDRESS: Status = DispTdiAssociateAddress(Irp); break; case TDI_DISASSOCIATE_ADDRESS: Status = DispTdiDisassociateAddress(Irp); break; case TDI_QUERY_INFORMATION: Status = DispTdiQueryInformation(DeviceObject, Irp); break; case TDI_SET_INFORMATION: Status = DispTdiSetInformation(Irp); break; case TDI_SET_EVENT_HANDLER: Status = DispTdiSetEventHandler(Irp); break; case TDI_ACTION: Status = STATUS_SUCCESS; break; /* An unsupported IOCTL code was submitted */ default: Status = STATUS_INVALID_DEVICE_REQUEST; } TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status)); if( Complete ) IRPFinish( Irp, Status ); return Status; }
NTSTATUS TapeReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine builds SRBs and CDBs for read and write requests to 4MM DAT devices. Arguments: DeviceObject Irp Return Value: Returns STATUS_PENDING. --*/ { PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); PSCSI_REQUEST_BLOCK srb; PCDB cdb; ULONG transferBlocks; LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; // // Allocate an Srb. // if (deviceExtension->SrbZone != NULL && (srb = ExInterlockedAllocateFromZone( deviceExtension->SrbZone, deviceExtension->SrbZoneSpinLock)) != NULL) { srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE; } else { // // Allocate Srb from non-paged pool. // This call must succeed. // srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE); srb->SrbFlags = 0; } // // Write length to SRB. // srb->Length = SCSI_REQUEST_BLOCK_SIZE; // // Set up IRP Address. // srb->OriginalRequest = Irp; // // Set up target id and logical unit number. // srb->PathId = deviceExtension->PathId; srb->TargetId = deviceExtension->TargetId; srb->Lun = deviceExtension->Lun; srb->Function = SRB_FUNCTION_EXECUTE_SCSI; srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); // // Save byte count of transfer in SRB Extension. // srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; // // Indicate auto request sense by specifying buffer and size. // srb->SenseInfoBuffer = deviceExtension->SenseData; srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; // // Initialize the queue actions field. // srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; // // Indicate auto request sense by specifying buffer and size. // srb->SenseInfoBuffer = deviceExtension->SenseData; srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; // // Set timeout value in seconds. // srb->TimeOutValue = deviceExtension->TimeOutValue; // // Zero statuses. // srb->SrbStatus = srb->ScsiStatus = 0; srb->NextSrb = 0; // // Indicate that 6-byte CDB's will be used. // srb->CdbLength = CDB6GENERIC_LENGTH; // // Fill in CDB fields. // cdb = (PCDB)srb->Cdb; // // Zero CDB in SRB. // RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); if (deviceExtension->DiskGeometry->BytesPerSector) { // // Since we are writing fixed block mode, normalize transfer count // to number of blocks. // transferBlocks = currentIrpStack->Parameters.Read.Length / deviceExtension->DiskGeometry->BytesPerSector; // // Tell the device that we are in fixed block mode. // cdb->CDB6READWRITETAPE.VendorSpecific = 1; } else { // // Variable block mode transfer. // transferBlocks = currentIrpStack->Parameters.Read.Length; cdb->CDB6READWRITETAPE.VendorSpecific = 0; } // // Set up transfer length // cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff); cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff); cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff); // // Set transfer direction flag and Cdb command. // if (currentIrpStack->MajorFunction == IRP_MJ_READ) { DebugPrint((3, "TapeReadWrite: Read Command\n")); srb->SrbFlags = SRB_FLAGS_DATA_IN; cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6; } else { DebugPrint((3, "TapeReadWrite: Write Command\n")); srb->SrbFlags = SRB_FLAGS_DATA_OUT; cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6; } // // Or in the default flags from the device object. // srb->SrbFlags |= deviceExtension->SrbFlags; // // Set up major SCSI function. // nextIrpStack->MajorFunction = IRP_MJ_SCSI; // // Save SRB address in next stack for port driver. // nextIrpStack->Parameters.Scsi.Srb = srb; // // Save retry count in current IRP stack. // currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; // // Set up IoCompletion routine address. // IoSetCompletionRoutine(Irp, ScsiClassIoComplete, srb, TRUE, TRUE, FALSE); return STATUS_PENDING; } // end TapeReadWrite()
NTSTATUS NTAPI TiDispatch( PDEVICE_OBJECT DeviceObject, PIRP Irp) /* * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests * ARGUMENTS: * DeviceObject = Pointer to a device object for this driver * Irp = Pointer to a I/O request packet * RETURNS: * Status of the operation */ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; IrpSp = IoGetCurrentIrpStackLocation(Irp); TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp)); Irp->IoStatus.Information = 0; #if 0 Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp); if (NT_SUCCESS(Status)) { TiDispatchInternal(DeviceObject, Irp); Status = STATUS_PENDING; } else { #else if (TRUE) { #endif /* See if this request is TCP/IP specific */ switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_TCP_QUERY_INFORMATION_EX: TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n")); Status = DispTdiQueryInformationEx(Irp, IrpSp); break; case IOCTL_TCP_SET_INFORMATION_EX: TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n")); Status = DispTdiSetInformationEx(Irp, IrpSp); break; case IOCTL_SET_IP_ADDRESS: TI_DbgPrint(MIN_TRACE, ("SET_IP_ADDRESS\n")); Status = DispTdiSetIPAddress(Irp, IrpSp); break; case IOCTL_DELETE_IP_ADDRESS: TI_DbgPrint(MIN_TRACE, ("DELETE_IP_ADDRESS\n")); Status = DispTdiDeleteIPAddress(Irp, IrpSp); break; case IOCTL_QUERY_IP_HW_ADDRESS: TI_DbgPrint(MIN_TRACE, ("QUERY_IP_HW_ADDRESS\n")); Status = DispTdiQueryIpHwAddress(DeviceObject, Irp, IrpSp); break; default: TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode)); Status = STATUS_NOT_IMPLEMENTED; break; } } TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status)); return IRPFinish( Irp, Status ); } VOID NTAPI TiUnload( PDRIVER_OBJECT DriverObject) /* * FUNCTION: Unloads the driver * ARGUMENTS: * DriverObject = Pointer to driver object created by the system */ { #if DBG KIRQL OldIrql; TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql); if (!IsListEmpty(&AddressFileListHead)) { TI_DbgPrint(MIN_TRACE, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n")); } TcpipReleaseSpinLock(&AddressFileListLock, OldIrql); #endif /* Cancel timer */ KeCancelTimer(&IPTimer); /* Unregister loopback adapter */ LoopUnregisterAdapter(NULL); /* Unregister protocol with NDIS */ LANUnregisterProtocol(); /* Shutdown transport level protocol subsystems */ TCPShutdown(); UDPShutdown(); RawIPShutdown(); ICMPShutdown(); /* Shutdown network level protocol subsystem */ IPShutdown(); /* Free NDIS buffer descriptors */ if (GlobalBufferPool) NdisFreeBufferPool(GlobalBufferPool); /* Free NDIS packet descriptors */ if (GlobalPacketPool) NdisFreePacketPool(GlobalPacketPool); /* Release all device objects */ if (TCPDeviceObject) IoDeleteDevice(TCPDeviceObject); if (UDPDeviceObject) IoDeleteDevice(UDPDeviceObject); if (RawIPDeviceObject) IoDeleteDevice(RawIPDeviceObject); if (IPDeviceObject) { ChewShutdown(); IoDeleteDevice(IPDeviceObject); } if (EntityList) ExFreePoolWithTag(EntityList, TDI_ENTITY_TAG); TI_DbgPrint(MAX_TRACE, ("[TCPIP, TiUnload] Leaving.\n")); }
/* * FUNCTION: Retrieve the specified file information */ NTSTATUS NTAPI CdfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) { FILE_INFORMATION_CLASS FileInformationClass; PIO_STACK_LOCATION Stack; PFILE_OBJECT FileObject; PFCB Fcb; PVOID SystemBuffer; ULONG BufferLength; NTSTATUS Status = STATUS_SUCCESS; DPRINT("CdfsQueryInformation() called\n"); Stack = IoGetCurrentIrpStackLocation(Irp); FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; FileObject = Stack->FileObject; Fcb = FileObject->FsContext; SystemBuffer = Irp->AssociatedIrp.SystemBuffer; BufferLength = Stack->Parameters.QueryFile.Length; switch (FileInformationClass) { case FileStandardInformation: Status = CdfsGetStandardInformation(Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FilePositionInformation: Status = CdfsGetPositionInformation(FileObject, SystemBuffer, &BufferLength); break; case FileBasicInformation: Status = CdfsGetBasicInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileNameInformation: Status = CdfsGetNameInformation(FileObject, Fcb, DeviceObject, SystemBuffer, &BufferLength); break; case FileInternalInformation: Status = CdfsGetInternalInformation(Fcb, SystemBuffer, &BufferLength); break; case FileNetworkOpenInformation: Status = CdfsGetNetworkOpenInformation(Fcb, SystemBuffer, &BufferLength); break; case FileAllInformation: Status = CdfsGetAllInformation(FileObject, Fcb, SystemBuffer, &BufferLength); break; case FileAlternateNameInformation: Status = STATUS_NOT_IMPLEMENTED; break; default: DPRINT("Unimplemented information class %x\n", FileInformationClass); Status = STATUS_INVALID_PARAMETER; break; } Irp->IoStatus.Status = Status; if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) Irp->IoStatus.Information = Stack->Parameters.QueryFile.Length - BufferLength; else Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); }
static NTSTATUS NTAPI BlasterDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) /* * FUNCTION: Handles user mode requests * ARGUMENTS: * DeviceObject = Device for request * Irp = I/O request packet describing request * RETURNS: Success or failure */ { PIO_STACK_LOCATION Stack; PDEVICE_EXTENSION DeviceExtension; DPRINT("BlasterDeviceControl() called!\n"); DeviceExtension = DeviceObject->DeviceExtension; Stack = IoGetCurrentIrpStackLocation(Irp); switch(Stack->Parameters.DeviceIoControl.IoControlCode) { /* case IOCTL_MIDI_PLAY : { DPRINT("Received IOCTL_MIDI_PLAY\n"); Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer; DPRINT("Sending %d bytes of MIDI data to 0x%d:\n", Stack->Parameters.DeviceIoControl.InputBufferLength, DeviceExtension->Port); for (ByteCount = 0; ByteCount < Stack->Parameters.DeviceIoControl.InputBufferLength; ByteCount ++) { DPRINT("0x%x ", Data[ByteCount]); MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]); // if (WaitToSend(MPU401_PORT)) // MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]); } Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_SUCCESS); } */ } return(STATUS_SUCCESS); /* DeviceExtension = DeviceObject->DeviceExtension; Stack = IoGetCurrentIrpStackLocation(Irp); BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; Irp->IoStatus.Information = 0; if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET) { Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_NOT_IMPLEMENTED); } if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS)) || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM) || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM)) { Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_INVALID_PARAMETER); } DueTime.QuadPart = 0; */ /* do the beep!! */ /* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n", pbsp->Frequency, pbsp->Duration); if (BeepParam->Duration >= 0) { DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000; KeSetTimer(&DeviceExtension->Timer, DueTime, &DeviceExtension->Dpc); HalMakeBeep(BeepParam->Frequency); DeviceExtension->BeepOn = TRUE; KeWaitForSingleObject(&DeviceExtension->Event, Executive, KernelMode, FALSE, NULL); } else if (BeepParam->Duration == (DWORD)-1) { if (DeviceExtension->BeepOn == TRUE) { HalMakeBeep(0); DeviceExtension->BeepOn = FALSE; } else { HalMakeBeep(BeepParam->Frequency); DeviceExtension->BeepOn = TRUE; } } DPRINT("Did the beep!\n"); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(STATUS_SUCCESS); */ }
NTSTATUS DF_DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS status; PDF_DEVICE_EXTENSION DevExt; PIO_STACK_LOCATION IrpSp; // For handling paging requests. BOOLEAN setPageable; BOOLEAN bAddPageFile; PAGED_CODE(); IrpSp = IoGetCurrentIrpStackLocation(Irp); DevExt = (PDF_DEVICE_EXTENSION)DeviceObject->DeviceExtension; switch(IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: DBG_PRINT(DBG_TRACE_OPS, ("%s: Start Device...\n", __FUNCTION__)); status = Irp->IoStatus.Status; DevExt->CurrentPnpState = IRP_MN_START_DEVICE; break; case IRP_MN_DEVICE_USAGE_NOTIFICATION : setPageable = FALSE; bAddPageFile = IrpSp->Parameters.UsageNotification.InPath; DBG_PRINT(DBG_TRACE_OPS, ("%s: Paging file request...\n", __FUNCTION__)); if (IrpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) // Indicated it will create or delete a paging file. { if(bAddPageFile && !DevExt->CurrentPnpState) { status = STATUS_DEVICE_NOT_READY; break; } // Waiting other paging requests. KeWaitForSingleObject(&DevExt->PagingCountEvent, Executive, KernelMode, FALSE, NULL); // Removing last paging device. if (!bAddPageFile && DevExt->PagingCount == 1 ) { // The last paging file is no longer active. // Set the DO_POWER_PAGABLE bit before // forwarding the paging request down the // stack. if (!(DeviceObject->Flags & DO_POWER_INRUSH)) { DeviceObject->Flags |= DO_POWER_PAGABLE; setPageable = TRUE; } } // Waiting lower device complete. IoForwardIrpSynchronously(DevExt->LowerDeviceObject, Irp); if (NT_SUCCESS(Irp->IoStatus.Status)) { IoAdjustPagingPathCount(&DevExt->PagingCount, bAddPageFile); if (bAddPageFile && DevExt->PagingCount == 1) { // Once the lower device objects have succeeded the addition of the paging // file, it is illegal to fail the request. It is also the time to clear // the Filter DO's DO_POWER_PAGABLE flag. DeviceObject->Flags &= ~DO_POWER_PAGABLE; } } else { if (setPageable == TRUE) { DeviceObject->Flags &= ~DO_POWER_PAGABLE; setPageable = FALSE; } } KeSetEvent(&DevExt->PagingCountEvent, IO_NO_INCREMENT, FALSE); status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } break; case IRP_MN_REMOVE_DEVICE: DBG_PRINT(DBG_TRACE_OPS, ("%s: Removing Device...\n", __FUNCTION__)); IoForwardIrpSynchronously(DevExt->LowerDeviceObject, Irp); status = Irp->IoStatus.Status; if (NT_SUCCESS(status)) { DBG_PRINT(DBG_TRACE_OPS, ("%d-%d: Stopping Device...\n", DevExt->DiskNumber, DevExt->PartitionNumber)); StopDevice(DeviceObject); DBG_PRINT(DBG_TRACE_OPS, ("%d-%d: Device Stopped.\n", DevExt->DiskNumber, DevExt->PartitionNumber)); } IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->LowerDeviceObject, Irp); }
// start event dispatching NTSTATUS DokanEventStart( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { ULONG outBufferLen; ULONG inBufferLen; PIO_STACK_LOCATION irpSp; EVENT_START eventStart; PEVENT_DRIVER_INFO driverInfo; PDOKAN_GLOBAL dokanGlobal; PDokanDCB dcb; NTSTATUS status; DEVICE_TYPE deviceType; ULONG deviceCharacteristics; WCHAR baseGuidString[64]; GUID baseGuid = DOKAN_BASE_GUID; UNICODE_STRING unicodeGuid; ULONG deviceNamePos; DDbgPrint("==> DokanEventStart\n"); dokanGlobal = DeviceObject->DeviceExtension; if (GetIdentifierType(dokanGlobal) != DGL) { return STATUS_INVALID_PARAMETER; } irpSp = IoGetCurrentIrpStackLocation(Irp); outBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength; inBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength; if (outBufferLen != sizeof(EVENT_DRIVER_INFO) || inBufferLen != sizeof(EVENT_START)) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(&eventStart, Irp->AssociatedIrp.SystemBuffer, sizeof(EVENT_START)); driverInfo = Irp->AssociatedIrp.SystemBuffer; if (eventStart.UserVersion != DOKAN_DRIVER_VERSION) { driverInfo->DriverVersion = DOKAN_DRIVER_VERSION; driverInfo->Status = DOKAN_START_FAILED; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO); return STATUS_SUCCESS; } deviceCharacteristics = FILE_DEVICE_IS_MOUNTED; switch (eventStart.DeviceType) { case DOKAN_DISK_FILE_SYSTEM: deviceType = FILE_DEVICE_DISK_FILE_SYSTEM; break; case DOKAN_NETWORK_FILE_SYSTEM: deviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM; deviceCharacteristics |= FILE_REMOTE_DEVICE; break; default: DDbgPrint(" Unknown device type: %d\n", eventStart.DeviceType); deviceType = FILE_DEVICE_DISK_FILE_SYSTEM; } if (eventStart.Flags & DOKAN_EVENT_REMOVABLE) { DDbgPrint(" DeviceCharacteristics |= FILE_REMOVABLE_MEDIA\n"); deviceCharacteristics |= FILE_REMOVABLE_MEDIA; } baseGuid.Data2 = (USHORT)(dokanGlobal->MountId & 0xFFFF) ^ baseGuid.Data2; baseGuid.Data3 = (USHORT)(dokanGlobal->MountId >> 16) ^ baseGuid.Data3; status = RtlStringFromGUID(&baseGuid, &unicodeGuid); if (!NT_SUCCESS(status)) { return status; } RtlZeroMemory(baseGuidString, sizeof(baseGuidString)); RtlStringCchCopyW(baseGuidString, sizeof(baseGuidString) / sizeof(WCHAR), unicodeGuid.Buffer); RtlFreeUnicodeString(&unicodeGuid); InterlockedIncrement((LONG*)&dokanGlobal->MountId); KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&dokanGlobal->Resource, TRUE); status = DokanCreateDiskDevice( DeviceObject->DriverObject, dokanGlobal->MountId, baseGuidString, dokanGlobal, deviceType, deviceCharacteristics, &dcb); if (!NT_SUCCESS(status)) { ExReleaseResourceLite(&dokanGlobal->Resource); KeLeaveCriticalRegion(); return status; } DDbgPrint(" MountId:%d\n", dcb->MountId); driverInfo->DeviceNumber = dokanGlobal->MountId; driverInfo->MountId = dokanGlobal->MountId; driverInfo->Status = DOKAN_MOUNTED; driverInfo->DriverVersion = DOKAN_DRIVER_VERSION; // SymbolicName is \\DosDevices\\Global\\Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9} // Finds the last '\' and copy into DeviceName. // DeviceName is \Volume{D6CC17C5-1734-4085-BCE7-964F1E9F5DE9} deviceNamePos = dcb->SymbolicLinkName->Length / sizeof(WCHAR) - 1; for (; dcb->SymbolicLinkName->Buffer[deviceNamePos] != L'\\'; --deviceNamePos) ; RtlStringCchCopyW(driverInfo->DeviceName, sizeof(driverInfo->DeviceName) / sizeof(WCHAR), &(dcb->SymbolicLinkName->Buffer[deviceNamePos])); DDbgPrint(" DeviceName:%ws\n", driverInfo->DeviceName); DokanUpdateTimeout(&dcb->TickCount, DOKAN_KEEPALIVE_TIMEOUT); dcb->UseAltStream = 0; if (eventStart.Flags & DOKAN_EVENT_ALTERNATIVE_STREAM_ON) { DDbgPrint(" ALT_STREAM_ON\n"); dcb->UseAltStream = 1; } dcb->UseKeepAlive = 0; if (eventStart.Flags & DOKAN_EVENT_KEEP_ALIVE_ON) { DDbgPrint(" KEEP_ALIVE_ON\n"); dcb->UseKeepAlive = 1; } dcb->Mounted = 1; DokanStartEventNotificationThread(dcb); DokanStartCheckThread(dcb); ExReleaseResourceLite(&dokanGlobal->Resource); KeLeaveCriticalRegion(); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(EVENT_DRIVER_INFO); DDbgPrint("<== DokanEventStart\n"); return Irp->IoStatus.Status; }