1

I have created a device in kernel space and the access it in user space using CreateFile I am able to send ioctl to the driver and they are executed properly. The don't know how to trace what happens after WdfRequestComplete and upon return I end with error 1 (invalid function). Before this is flagged as dup please note there is a difference with this in that I write my driver ioctl and in that I am using synch io not asynch.

In user space:

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

and in Kernel space

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);

Update 1:

I have tried WdfRequestCompleteWithInformation(Request, status, OutputBufferLength); but same result.

Also, I notice that the address of inputBuffer and outputBuffer are the same.

Update 2: I tried doing

temp = ExAllocatePoolWithTag(
    NonPagedPool,
    PAGE_SIZE,
    MEMORY_TAG
    );

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

still get error 1

Community
  • 1
  • 1
Luis
  • 114
  • 2
  • 10
  • You need to start with some basic troubleshooting: use DbgPrint liberally to see which function is failing and with what error code. Without that information, we're unlikely to be able to help you. – Harry Johnston Apr 23 '16 at 01:06
  • I am able to access the result in user space after using `outputBuffer = irp->AssociatedIrp.SystemBuffer` instead of `WdfRequestRetrieveOutputBuffer` but i don't know why. I have used DbgPrint and traced using windbg to check why I still keep getting error 1 but all seems to execute properly in EvtIoDeviceControl. – Luis Apr 24 '16 at 07:00
  • What data transfer type does the IOCTL use, see https://msdn.microsoft.com/en-us/library/windows/hardware/ff540663(v=vs.85).aspx ? – Harry Johnston Apr 24 '16 at 23:23
  • @HarryJohnston thanks! That was it, I am using the same codes that I have for my linux driver and didn't specify the CTL_CODE macro so it defaults to METHOD_BUFFERED – Luis Apr 25 '16 at 09:11
  • You should post the details as an answer. – Harry Johnston Apr 25 '16 at 21:27

1 Answers1

1

I had defined my ioctl cmds as enums in my linux driver (which works fine) and when implementing the driver in windows I used the same enum definition.

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

In windows defining control codes take a bit more. As explained here the CTL_CODE macro should be used to define new IOCTL control codes.

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

In my case I ended up with defining this:

#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)

I know the function code less than 0x800 are reserved for MS but the device on my host requires this codes so I'm just providing what is being asked.

Luis
  • 114
  • 2
  • 10
  • 1
    For the record, the IOCTL codes don't have to correspond to the hardware codes, so it would probably be safe to use the proper numbering. – Harry Johnston Apr 26 '16 at 19:16