title: DeviceIoControl error 1 incorrect function
body: <p>I have created a device in kernel space and the access it in user space using <code>CreateFile</code> I am able to send ioctl to the driver and they are executed properly. The don't know how to trace what happens after <code>WdfRequestComplete</code> and upon return I end with error 1 (invalid function). Before this is flagged as dup please note there is a difference with <a href="https://stackoverflow.com/questions/11919165/why-does-deviceiocontrol-fail-with-incorrect-function">this</a> in that I write my driver ioctl and in that I am using synch io not asynch.</p>
  
  <p>In user space:</p>
  
  <pre><code>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
      &amp;inputBuffer,
      inputBufferLength,
      &amp;outputBuffer,
      outputBufferLength,
      &amp;returnLength,
      (LPOVERLAPPED)NULL); // overlapped structure not needed using sync io
  </code></pre>
  
  <p>and in Kernel space</p>
  
  <pre><code>status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &amp;inputBuffer, NULL);
  if (!NT_SUCCESS(status)) 
  {
      WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
      return;
  }
  inputVirtArg = (VirtioQCArg*)inputBuffer;
  
  status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &amp;outputBuffer, NULL);
  if (!NT_SUCCESS(status))
  {
      WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
      return;
  }
  outputVirtArg = (VirtioQCArg*)outputBuffer;
  
  switch (IoControlCode)
  {
  case VIRTQC_CMD_MMAP:
      if (PsGetCurrentThread() == irp-&gt;Tail.Overlay.Thread)
      {
          status = CreateAndMapMemory(device, &amp;(inputVirtArg), &amp;(outputVirtArg));
          outputVirtArg-&gt;flag = (!NT_SUCCESS(status)) ? 0 : 1;
      } 
      else 
          status = STATUS_UNSUCCESSFUL;
      break;
  default:
      status = STATUS_INVALID_DEVICE_REQUEST;
      break;
  }
  WdfRequestComplete(Request, status);
  </code></pre>
  
  <p>Update 1:</p>
  
  <p>I have tried <code>WdfRequestCompleteWithInformation(Request, status, OutputBufferLength);</code> but same result.</p>
  
  <p>Also, I notice that the address of inputBuffer and outputBuffer are the same.</p>
  
  <p>Update 2:
  I tried doing </p>
  
  <pre><code>temp = ExAllocatePoolWithTag(
      NonPagedPool,
      PAGE_SIZE,
      MEMORY_TAG
      );
  
  // other code to
  RtlCopyMemory((VirtioQCArg*)outputBuffer, temp, OutputBufferLength);
  </code></pre>
  
  <p>still get error 1</p>