在驅動層,依傳輸類型的不同,輸入緩沖區的位置亦不同,見下表。
傳輸類型 位置
METHOD_IN_DIRECT irp->AssociatedIrp.SystemBuffer
METHOD_OUT_DIRECT irp->AssociatedIrp.SystemBuffer
METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer
METHOD_NEITHER irpStack->Parameters.DeviceIoControl.Type3InputBuffer
在驅動層,依傳輸類型的不同,輸出緩沖區的位置亦不同,見下表。
傳輸類型 位置
METHOD_IN_DIRECT irp->MdlAddress
METHOD_OUT_DIRECT irp->MdlAddress
METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer
METHOD_NEITHER irp->UserBuffer
所以只要確定了傳輸方式后,就可以根據各自的位置來讀取和寫入數據,從而實現應用層和驅動的通信。
下面看驅動層對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;
應用層:
驅動層:
代碼:
驅動和應用層通信.rar/Files/aurain/ioctl.rar


