能力值:
( LV7,RANK:100 )
3 楼
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName;
UNICODE_STRING ustrSymLinkName;
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
pDevice 就是 PDEVICE_OBJECT, 这个是驱动的设备对象定义, DDK带的, 应该不会有问题吧
我不调用TestRtl()这个函数的时候, 一点问题都没有, 一调用Unload的时候就有问题
能力值:
( LV7,RANK:100 )
4 楼
完整代码如下:
[i]//HelloDDK.h [/i]
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <ntddk.h>
#ifdef __cplusplus
}
#endif
#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")
#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")
#define arraysize(p) (sizeof(p)/sizeof((p)[0]))
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice ;
UNICODE_STRING ustrDeviceName ;
UNICODE_STRING ustrSymLinkName ;
} DEVICE_EXTENSION , * PDEVICE_EXTENSION ;
NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject );
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject );
NTSTATUS HelloDDKDispatchRoutinue (IN PDEVICE_OBJECT pDevObj , IN PIRP pIrp );
VOID DisplayCurProcessName (PTSTR RoutinueName ); [i]//HelloDDK.cpp [/i]
#include "HelloDDK.h"
typedef struct _MYDATA
{
LIST_ENTRY ListEntry ;
ULONG x ;
ULONG y ;
} MYDATA , * PMYDATA ;
#pragma INITCODE
VOID TestListEntry ()
{
LIST_ENTRY ListHead ;
InitializeListHead (& ListHead );
PMYDATA pData = NULL ;
ULONG i ;
KdPrint (("Start to insert elem to ListHead \n " ));
for ( i = 0 ; i < 10 ; i ++ )
{
pData = (PMYDATA )ExAllocatePool (PagedPool , sizeof (MYDATA ));
if ( pData )
{
pData -> x = i ;
pData -> y = 9 - i ;
InsertHeadList (& ListHead , & pData -> ListEntry );
}
}
KdPrint (("Start to remove elem from ListHead \n " ));
i = 0 ;
while ( ! IsListEmpty (& ListHead ) )
{
PLIST_ENTRY pEntry = RemoveTailList (& ListHead );
pData = CONTAINING_RECORD (pEntry , MYDATA , ListEntry );
KdPrint (("#%d: 0x%08x -- x: %d, y: %d \n " , i , pData , pData -> x , pData -> y ));
ExFreePool (pData );
++ i ;
}
}
#pragma INITCODE
VOID TestLookaside ()
{
PAGED_LOOKASIDE_LIST LookasideList ;
ExInitializePagedLookasideList ( & LookasideList ,
NULL ,
NULL ,
0 ,
sizeof (MYDATA ),
' YBGX ' ,
0 );
#define ARRAY_SIZE 10
PMYDATA pMyDataArray [ ARRAY_SIZE ] = { NULL };
ULONG i ;
KdPrint ((" \n Allocate Memory from PagedLookasideList \n " ));
for ( i = 0 ; i < ARRAY_SIZE ; i ++ )
{
pMyDataArray [ i ] = (PMYDATA )ExAllocateFromPagedLookasideList (& LookasideList );
pMyDataArray [ i ] -> x = i ;
pMyDataArray [ i ] -> y = 9 - i ;
}
KdPrint (("Release Memory from PagedLookasideList \n " ));
for ( i = 0 ; i < ARRAY_SIZE ; i ++ )
{
KdPrint (("#%d: 0x%08x -- x: %d, y: %d \n " , i , pMyDataArray [ i ], pMyDataArray [ i ] -> x , pMyDataArray [ i ] -> y ));
ExFreeToPagedLookasideList (& LookasideList , pMyDataArray [ i ]);
pMyDataArray [ i ] = NULL ;
}
KdPrint ((" \n Get entry from PagedLookasideList Again \n " ));
for ( i = 0 ; i < ARRAY_SIZE ; i ++ )
{
pMyDataArray [ i ] = (PMYDATA )ExAllocateFromPagedLookasideList (& LookasideList );
pMyDataArray [ i ] -> x = i ;
pMyDataArray [ i ] -> y = 9 - i ;
}
KdPrint (("Release Entry from PagedLookasideList Again \n " ));
for ( i = 0 ; i < ARRAY_SIZE ; i ++ )
{
KdPrint (("#%d: 0x%08x -- x: %d, y: %d \n " , i , pMyDataArray [ i ], pMyDataArray [ i ] -> x , pMyDataArray [ i ] -> y ));
ExFreeToPagedLookasideList (& LookasideList , pMyDataArray [ i ]);
pMyDataArray [ i ] = NULL ;
}
ExDeletePagedLookasideList (& LookasideList );
}
#pragma INITCODE
VOID TestRtl ()
{
#define BUFSIZE 1024
PUCHAR pBuffer1 = (PUCHAR )ExAllocatePool (PagedPool , BUFSIZE );
PUCHAR pBuffer2 = (PUCHAR )ExAllocatePool (PagedPool , BUFSIZE );
KdPrint (("Allocate Memory: 0x%08x, size = %d \n " , pBuffer1 , BUFSIZE ));
KdPrint (("Allocate Memory: 0x%08x, size = %d \n " , pBuffer2 , BUFSIZE ));
RtlFillMemory (pBuffer1 , BUFSIZE , 0xAA );
RtlCopyMemory (pBuffer2 , pBuffer1 , BUFSIZE );
if ( RtlCompareMemory (pBuffer1 , pBuffer2 , BUFSIZE ) == BUFSIZE )
KdPrint (("The Memory is equal \n " ));
else
KdPrint (("The Memory is NOT equal \n " ));
ExFreePool (pBuffer1 );
ExFreePool (pBuffer2 );
}
#pragma INITCODE
extern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject , IN PUNICODE_STRING pRegistryPath )
{
NTSTATUS status ;
KdPrint (("Enter DriverEntry \n " ));
KdPrint (("RegistryPath[S]: %S \n " , pRegistryPath -> Buffer ));
KdPrint (("RegistryPath[ws]: %ws \n " , pRegistryPath -> Buffer ));
pDriverObject -> DriverUnload = HelloDDKUnload ;
pDriverObject -> MajorFunction [ IRP_MJ_CREATE ] =
pDriverObject -> MajorFunction [ IRP_MJ_CLOSE ] =
pDriverObject -> MajorFunction [ IRP_MJ_READ ] =
pDriverObject -> MajorFunction [ IRP_MJ_WRITE ] = HelloDDKDispatchRoutinue ;
DisplayCurProcessName ("DriverEntry" );
status = CreateDevice (pDriverObject );
TestListEntry ();
TestLookaside ();
TestRtl (); [i]// 如果不调用这个函数Unload不会有问题, 如果调用就有问题 [/i]
KdPrint (("Leave DriverEntry \n " ));
return status ;
}
#pragma INITCODE
NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject )
{
NTSTATUS status ;
PDEVICE_OBJECT pDevObj ;
PDEVICE_EXTENSION pDevExt ;
DisplayCurProcessName ("CreateDevice" );
UNICODE_STRING devName ;
RtlInitUnicodeString (& devName , L" \\ Device \\ MyDDKDevice" );
status = IoCreateDevice (pDriverObject ,
sizeof (DEVICE_EXTENSION ),
& devName ,
FILE_DEVICE_UNKNOWN ,
0 ,
FALSE ,
& pDevObj );
if ( ! NT_SUCCESS (status ) )
return status ;
pDevObj -> Flags |= DO_BUFFERED_IO ;
pDevExt = (PDEVICE_EXTENSION )pDevObj -> DeviceExtension ;
pDevExt -> pDevice = pDevObj ;
pDevExt -> ustrDeviceName = devName ;
UNICODE_STRING symLinkName ;
RtlInitUnicodeString (& symLinkName , L" \\ ?? \\ HelloDDK" );
pDevExt -> ustrSymLinkName = symLinkName ;
status = IoCreateSymbolicLink (& symLinkName , & devName );
if ( ! NT_SUCCESS (status ) )
{
IoDeleteDevice (pDevObj );
return status ;
}
return STATUS_SUCCESS ;
}
#pragma PAGEDCODE
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject )
{
PDEVICE_OBJECT pNextObj ;
KdPrint (("Enter HelloDDKUnload \n " ));
DisplayCurProcessName ("HelloDDKUnload" );
pNextObj = pDriverObject -> DeviceObject ;
while ( pNextObj != NULL )
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION )pNextObj -> DeviceExtension ;
UNICODE_STRING pLinkName = pDevExt -> ustrSymLinkName ;
IoDeleteSymbolicLink (& pLinkName );
pNextObj = pNextObj -> NextDevice ;
IoDeleteDevice (pDevExt -> pDevice );
}
KdPrint (("Leave HelloDDKUnalod \n " ));
}
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutinue (IN PDEVICE_OBJECT pDevObj , IN PIRP pIrp )
{
NTSTATUS status = STATUS_SUCCESS ;
KdPrint (("Enter HelloDDKDispatchRoutinue \n " ));
DisplayCurProcessName ("HelloDDKDispatchRoutinue" );
pIrp -> IoStatus . Status = status ;
pIrp -> IoStatus . Information = 0 ;
IoCompleteRequest (pIrp , IO_NO_INCREMENT );
KdPrint (("Leave HelloDDKDispatchRoutinue \n " ));
return status ;
}
VOID DisplayCurProcessName (PTSTR RoutinueName )
{
PEPROCESS pEProcess = PsGetCurrentProcess ();
PTSTR ProcessName = (PTSTR )((ULONG )pEProcess + 0x174 );
KdPrint (("[%s]Current Process: %s \n " , RoutinueName , ProcessName ));
}
能力值:
( LV7,RANK:100 )
7 楼
楼上你没有写过驱动吗?
用ddk的build命令编译的
郁闷呀, 我始终找不到原因
能力值:
( LV12,RANK:530 )
9 楼
LZ是学习张帆的《windows驱动开发详解》之后,练习写的吧~~我试过,可能是问题在Unload上,也可能是系统会有差别所致,有时候在XP上可以,WIN7下不行,有时都行~~也可能是DDK驱动自身的一些问题吧~~如果可以的话,学学WDF,至少在WIN7下面比较稳定~~
还有楼上的兄弟,别人用了#ifndef来编译C++的源文件(.cpp)吗?嘿嘿~~当然可以在任意地方定义了!
具体出在什么问题上,我还不清楚~~如果有高人,希望在下面继续解答~~
能力值:
( LV7,RANK:100 )
11 楼
你说的很对, 这么多驱动的书, 就张帆的《windows驱动开发详解》我能看的比较懂, 其它的理论多,实战少,解释也少,看着费劲, 目前还没有到那个级别。
我是在xp sp3下测试的, 用的虚拟机
TestListEntry();
TestLookaside();
TestRtl();
这个三个函数我单独都测试过了, 只要是单独的, 都没有问题, 任意2个组合也没有问题, 但是3个放在一起就有问题了, 难道是栈空间溢出, 每个函数中如果有局部变量的话在函数退出的时候也释放了呀, 应该不存在这个问题的
能力值:
( LV7,RANK:100 )
12 楼
单步的时候
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;
windbg显示 pDevEx里面的内容遭到破坏。
但是实在看不出在什么地方破坏的
能力值:
( LV7,RANK:100 )
13 楼
按照你说的, 全部改成c的倒是没有问题了, 但是我又加了2个函数, 单独测试也没有问题, 加上去又是同样的问题。
能力值:
( LV7,RANK:100 )
15 楼
#pragma INITCODE
VOID TestProbe ()
{
PVOID pBadPointer = NULL ;
KdPrint (("Enter TestProbe \n " ));
__try
{
KdPrint (("Entry __try block \n " ));
ProbeForWrite (pBadPointer , 100 , 4 );
KdPrint (("Leave __try block \n " )); [i]// Never be executed [/i]
}
__except (EXCEPTION_EXECUTE_HANDLER )
{
KdPrint (("Catch the Exception \n " ));
KdPrint (("Keep going \n " ));
}
KdPrint (("Leave TestProbe \n " ));
}
#pragma INITCODE
VOID TestTryFinally ()
{
__try
{
KdPrint (("try: I will return \n " ));
return ;
}
__finally
{
KdPrint (("finally: I will be executed always. \n " ));
}
}
DriverEntry里面:
#pragma INITCODE
NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject , IN PUNICODE_STRING pRegistryPath )
{
NTSTATUS status ;
KdPrint (("Enter DriverEntry \n " ));
KdPrint (("RegistryPath[S]: %S \n " , pRegistryPath -> Buffer ));
KdPrint (("RegistryPath[ws]: %ws \n " , pRegistryPath -> Buffer ));
pDriverObject -> DriverUnload = HelloDDKUnload ;
pDriverObject -> MajorFunction [ IRP_MJ_CREATE ] =
pDriverObject -> MajorFunction [ IRP_MJ_CLOSE ] =
pDriverObject -> MajorFunction [ IRP_MJ_READ ] =
pDriverObject -> MajorFunction [ IRP_MJ_WRITE ] = HelloDDKDispatchRoutinue ;
DisplayCurProcessName ("DriverEntry" );
status = CreateDevice (pDriverObject );
[i]// 每个函数单独调用没有问题,5个放在一起就有问题 [/i]
TestListEntry ();
TestLookaside ();
TestRtl ();
TestProbe ();
TestTryFinally ();
KdPrint (("Leave DriverEntry \n " ));
return status ;
}
能力值:
( LV7,RANK:100 )
16 楼
我在DriverEntry加上了TestProbe(); 和 TestTryFinally(); 之后, 又出现同样的错误
能力值:
( LV5,RANK:70 )
17 楼
代码里面的CreateDevice,用了#pragma INITCODE,并且
RtlInitUnicodeString(&symLinkName, L"\\??\\HelloDDK");
这两个字符串是直接引用的,所以生成的代码将这两个字符串放到了INIT段里面去了,这个段在DriverEntry调用完成之后就有可能被释放,这个段这时候就无效了,而你在HelloDDKUnload里面直接取DeviceExtension里面的symLinkName,这个UNICODE_STRING.Buffer现在指向的是已经被释放的INIT段里面的字符串,所以就蓝了。
只要在代码前面加上下面这个就可以了,把直接使用的字符串换成下面两个全局变量的名字就可以了。
WCHAR *DeviceName =L"\\Device\\MyDDKDevice";
WCHAR *SymbolicName =L"\\??\\HelloDDK";
能力值:
( LV7,RANK:100 )
18 楼
非常感谢ImHolly大侠的帮助
, 果然是这个问题, 我修改了之后, 就没有问题了
不过我用的不是全局变量, 而是用的ExAllocatePool在CreateDevice里面为两个字符串分配的内存,在Unload里面释放的内存, 这就完全没有问题了
写驱动还要多动手, 多思考呀, 每个变量放在什么地方, 什么时候被释放, 都要很清楚才行, 这跟操作系统之上的应用差别还挺大的