下面看驱动层对ioctl控制码的处理代码:
//METHOD_OUT_DIREC方式 NTSTATUS COMM_DirectOutIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_DirectOutIo\r\n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = Irp->AssociatedIrp.SystemBuffer; pOutputBuffer = NULL; if(Irp->MdlAddress) pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_DirectOutIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } // METHOD_IN_DIRECT NTSTATUS COMM_DirectInIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_DirectInIo\r\n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = Irp->AssociatedIrp.SystemBuffer; pOutputBuffer = NULL; if(Irp->MdlAddress) pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_DirectInIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } // METHOD_BUFFERED NTSTATUS COMM_BufferedIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_BufferedIo\r\n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = Irp->AssociatedIrp.SystemBuffer; pOutputBuffer = Irp->AssociatedIrp.SystemBuffer; if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_BufferedIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } // METHOD_NEITHER NTSTATUS COMM_NeitherIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_NeitherIo\r\n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = pIoStackIrp->Parameters.DeviceIoControl.Type3InputBuffer; pOutputBuffer = Irp->UserBuffer; if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_NeitherIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } 代码比较简单,都是取得输入的数据,然后把数据直接拷贝到输出,传输给应用层。 应用层的代码: procedure TfrmMain.Send_Recv_Data(AInData: String; var AOutData:String; IoctlCode: DWORD); var dwReturn: DWORD; inData:array[0..1023] of char; outData:array[0..1023] of char; begin StrPCopy(inData, AInData); if m_hCommDevice <> 0 then begin DeviceIoControl(m_hCommDevice, IoctlCode, @inData, Length(inData), @outData, Length(outData), dwReturn, nil); AOutData := StrPas(@outData); end; end;
procedure TfrmMain. btnDirect_IN_IOClick (Sender: TObject); var outData:String; begin Send_Recv_Data(Trim(edtDirect_in_in.Text), outData, IOCTL_COMM_DIRECT_IN_IO); edtDirect_in_out.Text := outData; end;
驱动层: