2016-04-22 194 views
1

我已經在內核空間中創建了一個設備,並在用戶空間中使用它來訪問它CreateFile我能夠將ioctl發送給驅動程序,並且它們被正確執行。不知道如何跟蹤WdfRequestComplete後發生的情況,並在返回時以錯誤1結束(無效函數)。在此標記爲dup之前,請注意與this有區別,因爲我編寫的驅動程序ioctl和我使用的同步io不是異步。DeviceIoControl錯誤1錯誤的功能

在用戶空間:

fd = CreateFile(dev_path, 
    (FILE_GENERIC_READ | FILE_GENERIC_WRITE), 
    (FILE_SHARE_READ | FILE_SHARE_WRITE), 
    NULL, OPEN_EXISTING, 0, NULL); 
// ... error checking code here 
DeviceIoControl(fd, // device handler 
    VIRTQC_CMD_MMAP, // command to send 
    &inputBuffer, 
    inputBufferLength, 
    &outputBuffer, 
    outputBufferLength, 
    &returnLength, 
    (LPOVERLAPPED)NULL); // overlapped structure not needed using sync io 

,並在內核空間

status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &inputBuffer, NULL); 
if (!NT_SUCCESS(status)) 
{ 
    WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); 
    return; 
} 
inputVirtArg = (VirtioQCArg*)inputBuffer; 

status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &outputBuffer, NULL); 
if (!NT_SUCCESS(status)) 
{ 
    WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); 
    return; 
} 
outputVirtArg = (VirtioQCArg*)outputBuffer; 

switch (IoControlCode) 
{ 
case VIRTQC_CMD_MMAP: 
    if (PsGetCurrentThread() == irp->Tail.Overlay.Thread) 
    { 
     status = CreateAndMapMemory(device, &(inputVirtArg), &(outputVirtArg)); 
     outputVirtArg->flag = (!NT_SUCCESS(status)) ? 0 : 1; 
    } 
    else 
     status = STATUS_UNSUCCESSFUL; 
    break; 
default: 
    status = STATUS_INVALID_DEVICE_REQUEST; 
    break; 
} 
WdfRequestComplete(Request, status); 

更新1:

我已經試過WdfRequestCompleteWithInformation(Request, status, OutputBufferLength);但同樣的結果。

此外,我注意到inputBuffer和outputBuffer的地址是相同的。

更新2: 我試圖做

temp = ExAllocatePoolWithTag(
    NonPagedPool, 
    PAGE_SIZE, 
    MEMORY_TAG 
    ); 

// other code to 
RtlCopyMemory((VirtioQCArg*)outputBuffer, temp, OutputBufferLength); 

仍然得到錯誤1

+0

您需要從一些基本的故障排除開始:使用DbgPrint自由查看哪個函數失敗並使用哪些錯誤代碼。沒有這些信息,我們不可能幫助你。 –

+0

我能夠在使用'outputBuffer = irp-> AssociatedIrp.SystemBuffer'而不是'WdfRequestRetrieveOutputBuffer'後在用戶空間訪問結果,但我不知道爲什麼。我使用DbgPrint並使用windbg進行跟蹤,以檢查爲什麼我仍然收到錯誤1,但似乎都在EvtIoDeviceControl中正確執行。 – Luis

+0

IOCTL使用哪種數據傳輸類型,請參閱https://msdn.microsoft.com/en-us/library/windows/hardware/ff540663(v=vs.85).aspx? –

回答

1

我定義我的ioctl CMDS在我的Linux驅動程序枚舉(工作正常),並實現在Windows驅動程序時我使用了相同的枚舉定義。

enum 
{ 
    // Module & Execution control (driver API) 
    VIRTIQC_SET = 200, 
    VIRTIQC_UNSET, 
    // more cmds..... 
} 

在定義控制代碼的窗口中需要多一點。如解釋here,應該使用CTL_CODE宏來定義新的IOCTL控制代碼。

#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)

在我來說,我結束了與定義的:

#define VIRTQC_MAP CTL_CODE(FILE_DEVICE_NETWORK, 0xC8, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) 
#define VIRTQC_UNMAP CTL_CODE(FILE_DEVICE_NETWORK, 0xC9, METHOD_OUT_DIRECT, FILE_READ_DATA) 

我知道該功能的代碼小於爲0x800保留給MS,但我的主機上的設備需要這個代碼,所以我」只是提供了被問到的內容。

+1

爲了記錄,IOCTL代碼不必與硬件代碼相對應,因此使用正確的編號可能是安全的。 –