首页
社区
课程
招聘
[求助]Rtl函数问题
发表于: 2011-3-8 14:22 9240

[求助]Rtl函数问题

2011-3-8 14:22
9240
#pragma INITCODE
VOID TestRtl()
{
#define BUFSIZE	1024
	PUCHAR	pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFSIZE);
	if ( NULL == pBuffer )
		return;
	
	KdPrint(("Allocate Memory: 0x%08x, size = %d\n", pBuffer, BUFSIZE));
	RtlFillMemory(pBuffer, BUFSIZE, 0xAA);
	PUCHAR pBuffer2 = (PUCHAR)ExAllocatePool(PagedPool, BUFSIZE);
	if ( NULL == pBuffer2 )
	{
		ExFreePool(pBuffer);
		return;
	}
	
	KdPrint(("Allocate Memory: 0x%08x, size = %d\n", pBuffer2, BUFSIZE));
	RtlCopyMemory(pBuffer2, pBuffer, BUFSIZE);
	if ( RtlCompareMemory(pBuffer, pBuffer2, BUFSIZE) == BUFSIZE )
		KdPrint(("The Memory is equal\n"));
	else
		KdPrint(("The Memory is NOT equal\n"));
		
	ExFreePool(pBuffer);
	ExFreePool(pBuffer2);
}


我写了上述代码在NT式驱动里面, 测试Rtl*系列的函数, 但是我发现, 一旦在DriverEntry里面调用TestRtl(), 当我Unload这个Driver的时候就会蓝屏, Unload函数的写法:

#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"));
}


我看了调试信息, 错误出现在pNextObj = pNextObj->NextDevice; 估计应该是pNextObj指针失效了, 但是前面的pNextObj->DeviceExtension也用了这个指针,没有问题呀。而且只要我把TestRtl()函数注释掉就没有任何问题。 请各位帮看看, 这个TestRtl()函数究竟有什么问题, 我实在看不出来

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (17)
雪    币: 1163
活跃值: (137)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
2
pDevExt->pDevice


看下是不是pDevice定义的问题。
2011-3-8 17:06
0
雪    币: 387
活跃值: (25)
能力值: ( 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的时候就有问题
2011-3-8 17:19
0
雪    币: 387
活跃值: (25)
能力值: ( 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(("\nAllocate 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(("\nGet 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));
}
2011-3-8 17:26
0
雪    币: 1163
活跃值: (137)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
5
调了下,在unload例程中pDevExt 里的数据是不可读的。
看了下,也没找到原因~~
2011-3-8 18:44
0
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
6
这代码怎么编译通过的。。。。
2011-3-8 19:33
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
楼上你没有写过驱动吗?
用ddk的build命令编译的

郁闷呀, 我始终找不到原因
2011-3-9 15:51
0
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
8
这么多局部变量都是在中间定义的,能通过么。。。
2011-3-9 15:59
0
雪    币: 2323
活跃值: (4113)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
9
LZ是学习张帆的《windows驱动开发详解》之后,练习写的吧~~我试过,可能是问题在Unload上,也可能是系统会有差别所致,有时候在XP上可以,WIN7下不行,有时都行~~也可能是DDK驱动自身的一些问题吧~~如果可以的话,学学WDF,至少在WIN7下面比较稳定~~

还有楼上的兄弟,别人用了#ifndef来编译C++的源文件(.cpp)吗?嘿嘿~~当然可以在任意地方定义了!

具体出在什么问题上,我还不清楚~~如果有高人,希望在下面继续解答~~
2011-3-9 16:08
0
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
10
如果你是cpp文件的话,我建议改成c文件,然后把所有错误修改一下,试试看。
2011-3-9 16:27
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
11
你说的很对, 这么多驱动的书, 就张帆的《windows驱动开发详解》我能看的比较懂, 其它的理论多,实战少,解释也少,看着费劲, 目前还没有到那个级别。

我是在xp sp3下测试的, 用的虚拟机

TestListEntry();
TestLookaside();
TestRtl();

这个三个函数我单独都测试过了, 只要是单独的, 都没有问题, 任意2个组合也没有问题, 但是3个放在一起就有问题了, 难道是栈空间溢出, 每个函数中如果有局部变量的话在函数退出的时候也释放了呀, 应该不存在这个问题的
2011-3-9 16:32
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
单步的时候
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;
windbg显示 pDevEx里面的内容遭到破坏。
但是实在看不出在什么地方破坏的
2011-3-9 16:54
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
13
按照你说的, 全部改成c的倒是没有问题了, 但是我又加了2个函数, 单独测试也没有问题, 加上去又是同样的问题。
2011-3-9 18:21
0
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
14
有错误,继续上代码。
2011-3-9 18:46
0
雪    币: 387
活跃值: (25)
能力值: ( 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;
}
2011-3-10 11:27
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
16
我在DriverEntry加上了TestProbe(); 和 TestTryFinally(); 之后, 又出现同样的错误
2011-3-10 11:30
0
雪    币: 412
活跃值: (30)
能力值: ( 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";
2011-3-10 17:44
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
18
非常感谢ImHolly大侠的帮助, 果然是这个问题, 我修改了之后, 就没有问题了
不过我用的不是全局变量, 而是用的ExAllocatePool在CreateDevice里面为两个字符串分配的内存,在Unload里面释放的内存, 这就完全没有问题了

写驱动还要多动手, 多思考呀, 每个变量放在什么地方, 什么时候被释放, 都要很清楚才行, 这跟操作系统之上的应用差别还挺大的
2011-3-11 09:24
0
游客
登录 | 注册 方可回帖
返回
//