设备管理器中 停用启用设备后设备上有YB 错误代码Code 31

    闲暇时写个WDM驱动:CharSample。加载驱动后,在设备管理器中显示工作正常,甚是欣喜;然而这种欣喜没有持续几分钟就被冲散了:停用/再启用设备后,设备图标上有yellow bang,显示设备状态为:"This device is not working properly because Windows cannot load the drivers required for this device. (Code 31)"。看设备管理的提示,感觉这是重启设备后驱动文件丢失似得。

初次加载时:


停用启用后:


    本想到c:\windows\inf\setupapi.dev.log中查找线索,可是任我怎么重启设备,日志文件中就是没有任何记录...

    我又猜想在设备管理器中启用设备,应该会响应_IRP_MJ_PNP/IRP_MN_START_DEVICE事件,于是又在"case IRP_MN_START_DEVICE"处下断点,重启了几次设备,windbg都没有在case IRP_MN_START_DEVICE处停下。但重启系统,又能正常工作,难道重启设备后都不会响应IRP_MJ_PNP/IRP_MN_START_DEVICE事件了,不太可能啊?各种办法都尝试了,还没有解决办法,这就很尴尬了。最后在MSDN上找到Code 31对应的链接,MS给出的解释是:

CM_PROB_FAILED_ADD

A driver's attempt to add a device failed.

Error Code

31

Display Message (Windows 2000 and later versions of Windows)

"This device is not working properly because Windows cannot load the drivers required for this device. (Code 31)"

Recommended Resolution (Windows 2000 and later versions of Windows)

Update the device driver.

Starting with Windows XP, this problem can only occur if the driver's AddDevice routine fails.
最后一行提示说,仅当AddDevice函数失败时,才会出现这样的问题。按它的提示,我在AddDevice函数入口处下断点,再次重启设备,这次如期在AddDevice处停下。单步跟踪程序的执行发现驱动在IoCreateDevice时失败,之后就退出AddDevice,再往后就没有其他PNP事件产生了:

执行IoCreateDevice失败,不得不怀疑是不是因为系统中存在同名设备导致:

kd> !drvobj SampleChar
Driver object (852be230) is for:
 \Driver\SampleChar
Driver Extension List: (id , addr)

Device Object list:
85203158 
kd> !devstack 85203158  
  !DevObj   !DrvObj            !DevExt   ObjectName
> 85203158  \Driver\SampleChar 85203210  SampleChar
  8671d9a8  \Driver\PnpManager 00000000  000000b6
!DevNode 8519c3e8 :
  DeviceInst is "ROOT\SYSTEM\0002"
  ServiceName is "SampleChar"
如windbg显示SampleChar驱动有一个设备,并且附加在ROOT\System\002上。这就奇怪了,我在IRP_MJ_PNP\IRP_MN_STOP_DEVICE中的确有处理移除设备啊,为什么会没有把设备移除?

//这是我Pnp函数的代码片
NTSTATUS SampleCharPnp(PDEVICE_OBJECT devObj, PIRP irp)
{
...
case IRP_MN_STOP_DEVICE:
		IoSetDeviceInterfaceState(&devCtx->symLinkName, FALSE);

		IoSkipCurrentIrpStackLocation(irp);
		status = IoCallDriver(devCtx->lowerDev, irp);
		IoDetachDevice(devCtx->lowerDev);
		IoDeleteDevice(devObj);
		return status;
    带着这个疑问,我安装了ddk的toaster样例,按部就班的重启设备,发现当停用设备时, 会依次响应下列事件:IRP_MN_REMOVE_DEVICE/ToasterUnload,并没有包含IRP_MN_STOP_DEVICE事件。Toaster在IRP_MN_REMOVE_DEVICE事件中将设备从设备栈中分离并移除,而我处理IRP_MN_REMOVE_DEVICE事件时采用默认的方式:将irp下发给Root总线(其实就是什么都没做),因此错失了移除设备的机会:

default:
		IoSkipCurrentIrpStackLocation(irp);
		status = IoCallDriver(devCtx->lowerDev, irp);

		return status;
		break;

    原因找到了,最后修改代码如下:

NTSTATUS SampleCharPnp(PDEVICE_OBJECT devObj, PIRP irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	SampleCharDevContext* devCtx = (SampleCharDevContext*)devObj->DeviceExtension;
	KEVENT completeEvt;
	IO_STACK_LOCATION* curStack = IoGetCurrentIrpStackLocation(irp);

	if ((devCtx == NULL) || \
		(devCtx->lowerDev == NULL))
	{
		irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
		IoCompleteRequest(irp, IO_NO_INCREMENT);
		return status;
	}

	switch (curStack->MinorFunction)
	{
	case IRP_MN_START_DEVICE:
		ForwardIrpAndWait(devCtx->lowerDev,irp);
		IoSetDeviceInterfaceState(&devCtx->symLinkName, TRUE);

		status = irp->IoStatus.Status = status;
		IoCompleteRequest(irp, IO_NO_INCREMENT);

		break;
#if 0
	case IRP_MN_STOP_DEVICE:
		IoSetDeviceInterfaceState(&devCtx->symLinkName, FALSE);

		IoSkipCurrentIrpStackLocation(irp);
		status = IoCallDriver(devCtx->lowerDev, irp);
		IoDetachDevice(devCtx->lowerDev);
		IoDeleteDevice(devObj);
		return status;
		break;
#endif		
	case IRP_MN_REMOVE_DEVICE:
		IoSetDeviceInterfaceState(&devCtx->symLinkName, FALSE);

		IoSkipCurrentIrpStackLocation(irp);
		status = IoCallDriver(devCtx->lowerDev, irp);
		IoDetachDevice(devCtx->lowerDev);
		IoDeleteDevice(devObj);
		return status;

	default:
		IoSkipCurrentIrpStackLocation(irp);
		status = IoCallDriver(devCtx->lowerDev, irp);

		return status;
		break;
	}

	return status;

}
    再次重启设备,YB终于没有了,大功告成



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值