#define DISK_NAME  L"\\Device\\Harddisk0\\DR0"
#pragma LOCKEDCODE
NTSTATUS
FltReadWriteSectorsCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    ) 
{
KIRQL oldirql = KeGetCurrentIrql();
if(oldirql < DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL,&oldirql); UNREFERENCED_PARAMETER(DeviceObject);  if (Irp->AssociatedIrp.SystemBuffer && (Irp->Flags & IRP_DEALLOCATE_BUFFER)) 
{
ExFreePool(Irp->AssociatedIrp.SystemBuffer);
}
else if (Irp->MdlAddress != NULL) 
{
PMDL     mdl,nextMdl;
for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl) 
{
nextMdl = mdl->Next;
MmUnlockPages( mdl ); 
IoFreeMdl( mdl );  
}
Irp->MdlAddress = NULL;
        }  if(Context) 
{
ExFreePool(Context);
} IoFreeIrp(Irp); KeLowerIrql(oldirql);
return STATUS_MORE_PROCESSING_REQUIRED;
}#pragma PAGEDCODE
NTSTATUS ReadWriteDisk(PULONG_PTR  information ,ULONG MajorFunction,
       PVOID Buffer,ULONG Length,PLARGE_INTEGER StartingOffset,BOOLEAN Wait)
{
NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING DeviceName;
PDEVICE_OBJECT DeviceObject = NULL;
PFILE_OBJECT FileObject = NULL;

KEVENT AsynEvent;
IO_STATUS_BLOCK status_block; 
PIRP pNewIrp ;
PIO_STACK_LOCATION stack;
 
RtlInitUnicodeString(&DeviceName,DISK_NAME);//L"\\Device\\Harddisk0\\DR0"
ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);
if(!NT_SUCCESS(ntStatus))
{
KdPrint(("Get Harddisk0-DR0 Failed\n"));
information = 0;
ntStatus = STATUS_UNSUCCESSFUL;
return ntStatus;
}
else
KdPrint(("Get Harddisk0-DR0 Succeed\n")); pNewIrp = IoBuildAsynchronousFsdRequest(MajorFunction, DeviceObject,
Buffer, Length, StartingOffset, &status_block);
if (NULL == pNewIrp) 
{
KdPrint(("IoBuildAsynchronousFsdRequest Failed\n"));
information = 0;
ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES;
}KdPrint(("IoBuildAsynchronousFsdRequest Succeed\n"));

PVOID  context = ExAllocatePool(NonPagedPool, sizeof(KEVENT) );
if (NULL == context) 
{
KdPrint(("ExAllocatePool Failed\n"));
ObDereferenceObject(FileObject);
IoFreeIrp(pNewIrp);   
return STATUS_INSUFFICIENT_RESOURCES;
}KdPrint(("ExAllocatePool Succeed\n"));
IoSetCompletionRoutineEx(
   DeviceObject,
   pNewIrp,
                   FltReadWriteSectorsCompletion,
                   context,
                   TRUE,
                   TRUE,
                   TRUE); IoCallDriver(DeviceObject, pNewIrp);
//ObDereferenceObject(FileObject);
return STATUS_PENDING;
}以上代码是在NT式驱动的IRP_MJ_READ派遣例程中调用的(pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;)。
代码如下:
#pragma PAGEDCODE
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp) 
{
KdPrint(("Test3\n"));
PULONG_PTR  information = 0;
 

UCHAR*  bTemp = (UCHAR*)ExAllocatePool(NonPagedPool, 512 ); LARGE_INTEGER StartSector;
StartSector.QuadPart = 0x10000;
return ReadWriteDisk(information ,IRP_MJ_READ,
bTemp,512,&StartSector,TRUE); 
}我先加载了驱动程序,然后写了AP在其中用ReadFile调用此驱动程序,当我执行此AP后便会蓝屏。操作系统为WIN7 home版。dump文件内容如下:
KERNEL_MODE_EXCEPTION_NOT_HANDLED_M (1000008e)
This is a very common bugcheck.  Usually the exception address pinpoints
the driver/function that caused the problem.  Always note this address
as well as the link date of the driver/image that contains this address.
Some common problems are exception code 0x80000003.  This means a hard
coded breakpoint or assertion was hit, but this system was booted
/NODEBUG.  This is not supposed to happen as developers should never have
hardcoded breakpoints in retail code, but ...
If this happens, make sure a debugger gets connected, and the
system is booted /DEBUG.  This will let us see why this breakpoint is
happening.
Arguments:
Arg1: c0000005, The exception code that was not handled
Arg2: 836bb933, The address that the exception occurred at
Arg3: 9f132a10, Trap Frame
Arg4: 00000000FAULTING_MODULE: 8361f000 ntDEBUG_FLR_IMAGE_TIMESTAMP:  49ee8cbaEXCEPTION_CODE: (NTSTATUS) 0xc0000005 - "0x%08lx"FAULTING_IP: 
nt+9c933
836bb933 8b400c          mov     eax,dword ptr [eax+0Ch]TRAP_FRAME:  9f132a10 -- (.trap 0xffffffff9f132a10)
ErrCode = 00000000
eax=00000000 ebx=85fc4e40 ecx=85fc4e98 edx=00000000 esi=9f132b00 edi=00000001
eip=836bb933 esp=9f132a84 ebp=9f132a84 iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
nt+0x9c933:
836bb933 8b400c          mov     eax,dword ptr [eax+0Ch] ds:0023:0000000c=????????
Resetting default scopeCUSTOMER_CRASH_COUNT:  1DEFAULT_BUCKET_ID:  WRONG_SYMBOLSBUGCHECK_STR:  0x8ECURRENT_IRQL:  0LAST_CONTROL_TRANSFER:  from 843f0afb to 836bb933STACK_TEXT:  
WARNING: Stack unwind information not available. Following frames may be wrong.
9f132a84 843f0afb 00000000 85fc4e40 86018dc8 nt+0x9c933
9f132ae0 84202aeb 85fc4e40 9f132b00 9f132b2c fileinfo+0x1afb
9f132b4c 842059f0 9f132ba0 874ab6c8 00000000 fltmgr+0x2aeb
9f132b64 84205f01 9f132ba0 00000000 85fd6030 fltmgr+0x59f0
9f132b88 842063ba 03132b01 85fd6030 00000000 fltmgr+0x5f01
9f132bb8 83650ad1 85fd6030 874ab6c8 85fe1ef0 fltmgr+0x63ba
9f132bd0 9596d859 879225f8 00000000 00000208 nt+0x31ad1
9f132c10 9596d9a4 00000000 00000003 85f67d70 HelloDDK+0x859
9f132c44 83650ad1 85fe1ef0 86876ca0 86876ca0 HelloDDK+0x9a4
9f132c5c 83848177 86876ca0 86876d10 85abb830 nt+0x31ad1
9f132c7c 83853e2f 85fe1ef0 85abb830 00000001 nt+0x229177
9f132d08 836573fa 85fe1ef0 86876ca0 00000000 nt+0x234e2f
9f132d34 76ec8244 badb0d00 002ef8c8 00000000 nt+0x383fa
9f132d38 badb0d00 002ef8c8 00000000 00000000 0x76ec8244
9f132d3c 002ef8c8 00000000 00000000 00000000 0xbadb0d00
9f132d40 00000000 00000000 00000000 00000000 0x2ef8c8
STACK_COMMAND:  kbFOLLOWUP_IP: 
fileinfo+1afb
843f0afb ??              ???SYMBOL_STACK_INDEX:  1SYMBOL_NAME:  fileinfo+1afbFOLLOWUP_NAME:  MachineOwnerMODULE_NAME: fileinfoIMAGE_NAME:  fileinfo.sysBUCKET_ID:  WRONG_SYMBOLSFollowup: MachineOwner
---------

解决方案 »

  1.   

    DeviceObject必须是DR0设备, 而不是DR0的过滤设备...
    另外 需要在irpSp->Flags 加SL_FORCE_DIRECT_WRITE标志位.
    自己GOOGLE MS的文档.
      

  2.   

     
    DeviceObject必须是DR0设备, 而不是DR0的过滤设备...是DR0设备,用winobj看到PhysicalDrive0的符号链接为:\Device\Harddisk0\DR0。
    另外 需要在irpSp->Flags 加SL_FORCE_DIRECT_WRITE标志位.自己GOOGLE MS的文档.
    没看明白……
     
      

  3.   

    ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);
    !devobj DeviceObject
    你自己看看是不是DR0设备.你创建完IRP后有IRP堆栈, irpSp->Flags |= SL_FORCE_DIRECT_WRITE; 一下就好.
      

  4.   

    ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);
    !devobj DeviceObject
    你自己看看是不是DR0设备.

    那这个应该咋整呢?下面代码是我再XP下在驱动中读取磁盘的代码,它是ok的。在win7下不行,然后改着改着就成了上面的破样子……
    #define DISK_NAME  L"\\Device\\Harddisk0\\DR0"
    NTSTATUS ReadWriteDisk(PULONG_PTR  information ,ULONG MajorFunction,
           PVOID Buffer,ULONG Length,PLARGE_INTEGER StartingOffset,BOOLEAN Wait)
    {
    NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING DeviceName;
    PDEVICE_OBJECT DeviceObject = NULL;
    PFILE_OBJECT FileObject = NULL;

    KEVENT AsynEvent;
    IO_STATUS_BLOCK status_block;
    //LARGE_INTEGER offset ;//= RtlConvertLongToLargeInteger(0);
    PIRP pNewIrp ;
    PIO_STACK_LOCATION stack;
    PAGED_CODE();
    RtlInitUnicodeString(&DeviceName,DISK_NAME);//L"\\Device\\Harddisk0\\DR0"
    ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);
    if(!NT_SUCCESS(ntStatus))
    {
    KdPrint(("ReadWriteDisk Failed\n"));
    information = 0;
    ntStatus = STATUS_UNSUCCESSFUL;
    return ntStatus;
    } pNewIrp = IoBuildAsynchronousFsdRequest(MajorFunction, DeviceObject,
    Buffer, Length, StartingOffset, &status_block);
    if (!pNewIrp) 
    {
    information = 0;
    return STATUS_INSUFFICIENT_RESOURCES;
    } if (Wait) 
    {
    KeInitializeEvent(&AsynEvent, NotificationEvent, FALSE);
    IoSetCompletionRoutine(pNewIrp, FltReadWriteSectorsCompletion,
    &AsynEvent, TRUE, TRUE, TRUE); ntStatus = IoCallDriver(DeviceObject, pNewIrp);
    if (STATUS_PENDING == ntStatus) 
    {
    KeWaitForSingleObject(&AsynEvent, Executive, KernelMode, FALSE, NULL);
    ntStatus = status_block.Status;
    }

    else
    {
    IoSetCompletionRoutine(pNewIrp, FltReadWriteSectorsCompletion,
    NULL, TRUE, TRUE, TRUE);
    pNewIrp->UserIosb = NULL;
    ntStatus = IoCallDriver(DeviceObject, pNewIrp);
    } ObDereferenceObject(FileObject);
    KdPrint(("ReadWriteDisk OK\n"));
    return ntStatus; 
    }
    NTSTATUS
    FltReadWriteSectorsCompletion(
        IN PDEVICE_OBJECT DeviceObject,
        IN PIRP Irp,
        IN PVOID Context
        ) 
    {
    PMDL     mdl; UNREFERENCED_PARAMETER(DeviceObject);  if (Irp->AssociatedIrp.SystemBuffer && (Irp->Flags & IRP_DEALLOCATE_BUFFER)) 
    {
    ExFreePool(Irp->AssociatedIrp.SystemBuffer);
    } while (Irp->MdlAddress) 
    {
    mdl = Irp->MdlAddress;
    Irp->MdlAddress = mdl->Next;
    MmUnlockPages(mdl);
    IoFreeMdl(mdl);
    } if (Irp->PendingReturned && (Context != NULL)) 
    {
    *Irp->UserIosb = Irp->IoStatus;
    KeSetEvent((PKEVENT) Context, IO_DISK_INCREMENT, FALSE);
    } IoFreeIrp(Irp); 
    return STATUS_MORE_PROCESSING_REQUIRED;
    }
      

  5.   

    楼主貌似有ExAllocate的内存没有释放哦
      

  6.   

    没机会看到,我一执行AP就蓝掉了。
    是我读写磁盘的问题,只要我不
    IoSetCompletionRoutineEx;
    IoCallDriver(DeviceObject, pNewIrp);
    就没有问题。是不是用Try/Catch就能截下出错的地方
      

  7.   

    在NT5下肯定没问题啊.
    枚举\Driver\Disk驱动对象的所有设备.
    找出DR0设备.
    IRP对着DR0设备直接发. 不然会BSOD.
    IoGetDeviceObjectPointer 没用, 看文档.
    The IoGetDeviceObjectPointer routine returns a pointer to the top object in the named device object's stack.
      

  8.   

    真扯,什么DeviceTree,IrpTrace等在win7下都不能用……
      

  9.   

    有,虚拟串口。RamDisk,FileDisk等等,网上都有源代码
      

  10.   

    设置断点单步调试啊~
    看看DeviceObject和IRP是否正确。
    大概扫了一眼代码,感觉问题不少。
    函数调用要判断返回值,根据返回值决定接下来如何处理。
    磁盘驱动最好不要用PAGEDCODE。
    如果要返回STATUS_PENDING,应先调用IoMarkIrpPending。
    提升IRQL的目的是什么?这个应该很少用到。
      

  11.   

    这段代码在调试时被我改成了这样。非常感谢前辈给我指出的错误。
    本来完成例程函数中是没有提升IRQL和设置PAGEDCODE的,只是蓝屏找不到错误就加上去看看了。MSDN中有说完成例程应该设计成DISPATCH_LEVEL等级,所以就整成这样了。前辈所说的设置断点单步调试,是说用WinDbg吧?
    如果我本机是XP,要调试的驱动是在Win7下,那么这样连接的话本机的windbg是要用win7版本的吗……
      

  12.   

    可以用WinDbg,也可以用其它工具。WinDbg没有Win7的版本,我现在用的版本是6.6.0007.5,XP、Vista、Win7都可以调。