NTSTATUS
MixPortDriverWriteDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success
PSERIAL_DEVICE_EXTENSION pExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( pIrp );
//获取用户写数据的字节数目
ULONG DataLen = irpSp->Parameters.Write.Length;
//获取用户数据的首地址
PCHAR pData = pIrp->AssociatedIrp.SystemBuffer;
ULONG i;
KIRQL OldIrql;
PIRP pOldReadIrp = NULL;
PDRIVER_CANCEL pOldCancelRoutine;
PCHAR outBuf, inBuf;
KdPrint(("%u MixPortDriverWriteDispatch", DeviceObject));
KdPrint(("%u irpSp->Parameters.Write.Length=%d\n", DeviceObject, irpSp->Parameters.Write.Length));
//#if DBG
// _asm int 3;
//#endif
pIrp->IoStatus.Information = 0;
ntStatus = STATUS_SUCCESS;
//没有数据要写,或者已经写完毕
if (DataLen == 0)
{
ntStatus = STATUS_SUCCESS;
}
else//还有数据待写
{
//获得写操作自旋锁
KeAcquireSpinLock(&pExtension->WriteSpinLock, &OldIrql);
KdPrint(("%u KeAcquireSpinLock(&pExtension->WriteSpinLock,DeviceObject,&OldIrql)"));
//将用户数据复制到缓冲区,可能存在的问题,数据覆盖?
// for (i=0; i
// {
//KdPrint(("%u pData[%d]=%c\n",DeviceObject,i, pData ));
// pExtension->Buffer[pExtension->BufHead] = pData;
// pExtension->BufHead++;
//KdPrint(("%u head=%d\n",DeviceObject,pExtension->BufHead));
// pExtension->BufHead %= COMBUFLEN;
// }
//管道另一端正等待读数据
if (pExtension->pReadIrp != NULL) // drop it out
{
pOldReadIrp = pExtension->pReadIrp;
//删除管道另一头的等待读取数据的请求
pOldCancelRoutine = IoSetCancelRoutine(pOldReadIrp, NULL);
// wurde Cancel-Routine schon aufgerufen?
//取消例行已经叫什么名字?
if (pOldCancelRoutine != NULL)
{
// Nein, also Request beenden
//没有,所以退出申请
//设置管道另一端读请求的处理结果,实际上不让读了
pOldReadIrp->IoStatus.Information = 0;
pOldReadIrp->IoStatus.Status = STATUS_SUCCESS;
//清除管道另一端的读请求
pExtension->pReadIrp = NULL;
}
else
{
// Ja, Cancel-Routine wird Request beenden 对比某处? 是的,取消例程将退出请求
pOldReadIrp = NULL;
}
}
KdPrint(("%u IoGetDeviceObjectPointer symbolicName=%ws !\n",DeviceObject, pExtension->getDeviceContext->symbolicName.Buffer));
KdPrint(("%u IoGetDeviceObjectPointer accessMask=%u !\n",DeviceObject, pExtension->getDeviceContext->accessMask));
if (pExtension->getDeviceContext->device == NULL)
{
ntStatus = IoGetDeviceObjectPointer(&pExtension->getDeviceContext->symbolicName,
pExtension->getDeviceContext->accessMask,
&pExtension->getDeviceContext->file,
&pExtension->getDeviceContext->device);
}
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("%u IoGetDeviceObjectPointer failed ! status=%l\n",DeviceObject, ntStatus));
}
//have digits to translate.
if (0 != DataLen)
{
KdPrint(("%u 0 != DataLen\n",DeviceObject));
inBuf = ExAllocatePool(NonPagedPool, DataLen);
outBuf = ExAllocatePool(NonPagedPool, DataLen*2);
if (NULL == inBuf || outBuf == NULL)
{
KdPrint(("%u STATUS_INSUFFICIENT_RESOURCES\n",DeviceObject));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
strncpy(inBuf, pData, DataLen);//copy datas to build the irp instead of send to extension buffer
KdPrint(("%u pExtension->getDeviceContext->device=%u\n",DeviceObject, pExtension->getDeviceContext->device));
ntStatus = MakeSynchronousIoctl(pExtension->getDeviceContext->device,
IOCTL_SERIAL_TRANSLATE,
inBuf,
DataLen,
outBuf,
DataLen*2);
KdPrint(("%u MakeSynchronousIoctl\n",DeviceObject));
if (NT_SUCCESS(ntStatus))
{
KdPrint(("%u NT_SUCCESS(ntStatus)\n",DeviceObject));
for (i = 0; i
{
pExtension->Buffer[pExtension->BufHead++] = outBuf;
}
KdPrint(("%u Datalen=%u\n",DeviceObject, i));
}
}
if (inBuf != NULL)
{
KdPrint(("%u inBuf != NULL\n",DeviceObject));
ExFreePool(inBuf);
inBuf = NULL;
}
if (outBuf != NULL)
{
KdPrint(("%u outBuf != NULL\n",DeviceObject));
ExFreePool(outBuf);
outBuf = NULL;
}
}
//检查管道另一端的事件状态
DriverCheckEvent(pExtension, SERIAL_EV_RXCHAR | SERIAL_EV_RX80FULL);
//检查管道本端事件状态
DriverCheckEvent(pExtension, SERIAL_EV_TXEMPTY);
//释放写操作自旋锁
KeReleaseSpinLock(&pExtension->WriteSpinLock, OldIrql);
if (pOldReadIrp != NULL)
IoCompleteRequest(pOldReadIrp, IO_NO_INCREMENT);
}
//给用户返回写操作的执行情况
pIrp->IoStatus.Status = ntStatus;
pIrp->IoStatus.Information = DataLen;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return ntStatus;
}
NTSTATUS
MakeSynchronousIoctl(
IN PDEVICE_OBJECT TopOfDeivceStack,
IN ULONG IoctlControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength)
{
KEVENT event;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
//创建设备控制IRP给其它驱动
//初始化同步事件
KeInitializeEvent(&event,NotificationEvent,FALSE);
//用IoBuildDeviceIoControlRequest创建IRP
irp = IoBuildDeviceIoControlRequest(IoctlControlCode,
TopOfDeivceStack,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
FALSE,
&event,
&ioStatus);
//判断IRP是否为零
KdPrint((" devicepointer=%u\n", TopOfDeivceStack));
KdPrint((" InputBuffer=%s\n", InputBuffer));
KdPrint((" InputBufferLength=%u\n", InputBufferLength));
KdPrint((" OutputBuffer=%s\n", OutputBuffer));
KdPrint((" OutputBufferLength=%u\n", OutputBufferLength));
if (NULL == irp)
{
KdPrint((" (NULL == irp)\n" ));
return STATUS_INSUFFICIENT_RESOURCES;
}
//调用底层驱动程序 就是这一行会引起蓝屏
status = IoCallDriver(TopOfDeivceStack,irp);
if (status == STATUS_PENDING)
{
KdPrint((" status == STATUS_PENDING\n" ));
status = KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
status = ioStatus.Status;
}
IoCompleteRequest(irp, IO_NO_INCREMENT);
KdPrint(("status=%x \n", ioStatus.Status ));
return status;
}
我写了两个虚拟串口的驱动程序A和B,其中B有一个控制码IOCTL_SERIAL_TRANSLATE能将阿拉伯数字装换为中文数字,我现在是在A的writeFile响应例程里面自己通过IoBuildDeviceIoControlRequest创建了IRP,然后获得设备B的指针,通过IoCallDriver来调用IOCTL_SERIAL_TRANSLATE实现转换,B的该控制码是没有问题的,用MFC对该控制码进行过测试,能正确转换且没有异常,但是我在A里面调用IoCallDriver的时候就会蓝屏,不知道是什么原因?各位前辈指点一下。谢谢!