摘要:NT式驅動中,在DriverUnload()中嘗試刪除之前創建的符號鏈接失敗,最後發現原因是變量作用域和RtlInitUnicodeString的問題
原始存在問題的簡化代碼如下:
[cpp]
typedef struct _DEVICE_EXTENSION {
UINT32 magicNum;
PDEVICE_OBJECT pDevice;
UNICODE_STRING symLinkName;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
PDEVICE_OBJECT gControlDeviceObject;
DriverEntry()
{
PDEVICE_EXTENSION pDevExt;
WCHAR linkNameBuffer[] = L"\\DosDevices\\diskFilter";
UNICODE_STRING LinkName;
IoCreateDevice(..., &gControlDeviceObject);
RtlInitUnicodeString (&LinkName, linkNameBuffer );
pDevExt->magicNum = 0x4c44;
pDevExt->symLinkName = LinkName;
DriverObject->DriverUnload = DiskFilterUnload;
}
DiskFilterUnload (IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_EXTENSION pDevExt;
pDevExt = (PDEVICE_EXTENSION)gControlDeviceObject->DeviceExtension;
KdPrint((" devObj(0x%x), magicNum(0x%x), SymLinkName(%wZ)\n", gControlDeviceObject, pDevExt->magicNum, &pDevExt->symLinkName));
status = IoDeleteSymbolicLink( &pDevExt->ustrSymLinkName );
}
上述代碼中,從IoDeleteSymbolicLink返回的status是路徑不正確,但KdPrint中打印的magicNum是正確的,windbg調試裡發現在DiskFilterUnload()中的pDevExt->symLinkName沒有包含正確的值,當時真有點百思不得其解啊。
後來看到linkNameBuffer是局部變量,想到了變量作用域的問題,把WCHAR linkNameBuffer[] = L"\\DosDevices\\diskFilter";拿到DriverEntry外做全局變量,
問題就消失了。當然,更一般的做法應該是在頭文件中#define SymbolicLinkName L"\\DosDevices\\diskFilter"。
現在來看,要產生這個問題,還有一個原因是RtlInitUnicodeString(),它應該沒有做內存拷貝(它沒有為smLinkName分配內存然後把值拷貝過去,但我認為它這樣做了)
看來下次使用RtlInitUnicodeString()的時候得要注意了。