Пример #1
0
/*++
Routine Description:

Called by the framework when it receives Write requests.

Arguments:

Queue - Default queue handle
Request - Handle to the read/write request
Length - Length of the data buffer associated with the request.
The default property of the queue is to not dispatch
zero length read & write requests to the driver and
complete is with status success. So we will never get
a zero length request.
--*/
VOID PSDrv_EvtIoWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
    PFILE_CONTEXT				fileContext = NULL;
    WDFUSBPIPE					pipe;
    WDF_USB_PIPE_INFORMATION	pipeInfo;

    PAGED_CODE();

    // Get the pipe associate with this request.
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));

    pipe = fileContext->Pipe;
    if (pipe == NULL) 
	{
   		PSDrv_DbgPrint(1, ("PSDrv_EvtIoWrite: Invalid pipe!\n"));
        WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0);
        return;
    }

    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

    if((WdfUsbPipeTypeBulk == pipeInfo.PipeType) || (WdfUsbPipeTypeInterrupt == pipeInfo.PipeType))
	{
        ReadWriteBulkEndPoints(Queue, Request, (ULONG)Length, WdfRequestTypeWrite);
        return;
    }
	else if(WdfUsbPipeTypeIsochronous == pipeInfo.PipeType)
	{
        ReadWriteIsochEndPoints(Queue, Request, (ULONG)Length, WdfRequestTypeWrite);
        return;
    }

    return;
}
Пример #2
0
// Exstact the device id of the current device from the request
// Return id
// Returns 0xFFFF if error or id out of range
USHORT GetIdFromRawPdoRequest(
	WDFREQUEST    Request,
	PVOID pExt
	)
{
	WDFFILEOBJECT FileObj = NULL;
	PFILEOBJECT_EXTENSION pExtension = (PFILEOBJECT_EXTENSION)pExt;
	USHORT id = 0xFFFF;

	// Get the context, id and the status
	FileObj = WdfRequestGetFileObject(Request);
	if (FileObj)
	{
		pExtension = GetFileObjectContext(FileObj);
		if (pExtension)
			id = (UCHAR)pExtension->id;
		//else
		//	id = 0;
	}
	//else
	//	id = 0;

	//if (id > MAX_N_DEVICES)
	//	id = 0;

	return id;
}
VOID
NfcCxSCPresentAbsentDispatcherRequestCanceled(
    _In_ WDFREQUEST Request
    )
/*++

Routine Description:

    Called when a pending request has been canceled.

Arguments:

    Request - The request

Return Value:

    NTSTATUS

--*/
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request);
    WDFDEVICE device = WdfFileObjectGetDevice(fileObject);

    PNFCCX_FILE_CONTEXT fileContext = NfcCxFileGetContext(fileObject);
    PNFCCX_FDO_CONTEXT fdoContext = NfcCxFdoGetContext(device);
    PNFCCX_SC_REQUEST_CONTEXT requestContext = NfcCxSCGetRequestContext(Request);
    PNFCCX_SC_PRESENT_ABSENT_DISPATCHER dispatcher = requestContext->Dispatcher;

    // Remove this request from the dispatcher
    void* previousRequest = InterlockedCompareExchangePointer((void**)&dispatcher->CurrentRequest, /*exchange*/ nullptr, /*compare*/ Request);

    // Check if another thread has already completed the request.
    if (previousRequest != Request)
    {
        // Request already completed by a different thread.
        // Nothing to do.
        goto Done;
    }

    // Release power reference (if required).
    if (dispatcher->PowerManaged)
    {
        NfcCxPowerFileRemoveReference(fdoContext->Power, fileContext, NfcCxPowerReferenceType_Proximity);
    }

    // Complete the request.
    TRACE_LINE(LEVEL_ERROR, "Smartcard Present/Absent request canceled. %!STATUS!", STATUS_CANCELLED);
    WdfRequestComplete(Request, STATUS_CANCELLED);

Done:
    // Release the cancel callback's extra ref-count
    WdfObjectDereference(Request);

    TRACE_FUNCTION_EXIT(LEVEL_VERBOSE);
}
void AndroidUsbFileObject::OnEvtIoDeviceControl(WDFREQUEST request,
                                                size_t output_buf_len,
                                                size_t input_buf_len,
                                                ULONG ioctl_code) {
  ASSERT_IRQL_LOW_OR_DISPATCH();
  ASSERT(WdfRequestGetFileObject(request) == wdf_file());

  WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
}
void AndroidUsbFileObject::OnEvtIoWrite(WDFREQUEST request,
                                        size_t length) {
  ASSERT_IRQL_LOW_OR_DISPATCH();
  ASSERT(WdfRequestGetFileObject(request) == wdf_file());
  // Complete zero writes with success
  if (0 == length) {
    WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0);
    return;
  }

  WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
}
static VOID
XenBus_ProcessReadRequest(WDFQUEUE queue, WDFREQUEST request, size_t length)
{
  NTSTATUS status;
  WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  ULONG dst_length = (ULONG)length;
  ULONG dst_offset = 0;
  ULONG copy_length;
  xenbus_read_queue_item_t *list_entry;
  PVOID buffer;

  UNREFERENCED_PARAMETER(queue);
  
  status = WdfRequestRetrieveOutputBuffer(request, length, &buffer, NULL);
  if (!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME, "     WdfRequestRetrieveOutputBuffer failed status = %08x\n", status));
    WdfRequestSetInformation(request, 0);
    return;
  }
  ASSERT(NT_SUCCESS(status)); // lazy?

  while(dst_offset < dst_length && (list_entry = (xenbus_read_queue_item_t *)RemoveHeadList(&xpdid->xenbus.read_list_head)) != (xenbus_read_queue_item_t *)&xpdid->xenbus.read_list_head)
  {
    copy_length = min(list_entry->length - list_entry->offset, dst_length - dst_offset);
    memcpy((PUCHAR)buffer + dst_offset, (PUCHAR)list_entry->data + list_entry->offset, copy_length);
    list_entry->offset += copy_length;
    dst_offset += copy_length;
    if (list_entry->offset == list_entry->length)
    {
      ExFreePoolWithTag(list_entry->data, XENPCI_POOL_TAG);
      ExFreePoolWithTag(list_entry, XENPCI_POOL_TAG);
    }
    else
    {
      InsertHeadList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry);
    }      
  }
  WdfRequestSetInformation(request, dst_offset);
  
  FUNCTION_EXIT();
}
static VOID
XenBus_EvtIoRead(WDFQUEUE queue, WDFREQUEST request, size_t length)
{
  NTSTATUS status;
  WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;

  UNREFERENCED_PARAMETER(queue);
  
  FUNCTION_ENTER();
  status = WdfRequestForwardToIoQueue(request, xpdid->xenbus.io_queue);
  if (!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME "     could not forward request (%08x)\n", status));
  }
  KeAcquireSpinLock(&xpdid->lock, &old_irql);
  if (!IsListEmpty(&xpdid->xenbus.read_list_head))
  {
    status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &request);
    if (NT_SUCCESS(status))
    {
      KdPrint((__DRIVER_NAME "     found pending read\n"));
      XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, request, length);
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      WdfRequestComplete(request, STATUS_SUCCESS);
    }
    else
    {
      KdPrint((__DRIVER_NAME "     no pending read (%08x)\n", status));
      KeReleaseSpinLock(&xpdid->lock, old_irql);
    }
  }
  else
  {
    KdPrint((__DRIVER_NAME "     no data to read\n"));
    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  
  FUNCTION_EXIT();
  return;
}
Пример #8
0
static VOID UsbChief_EvtIoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
	PFILE_CONTEXT           fileContext = NULL;
	WDFUSBPIPE              pipe;
	WDF_USB_PIPE_INFORMATION   pipeInfo;

	UNREFERENCED_PARAMETER(Queue);

	PAGED_CODE();

	UsbChief_DbgPrint(DEBUG_RW, ("EvtIoRead %d\n", Length));

	fileContext = GetFileContext(WdfRequestGetFileObject(Request));
	pipe = fileContext->Pipe;
	if (pipe == NULL) {
		UsbChief_DbgPrint(0, ("pipe handle is NULL\n"));
		WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0);
		return;
	}
	WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
	WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

	UsbChief_ReadEndPoint(Queue, Request, (ULONG) Length);
}
Пример #9
0
/*++
Routine Description:

This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
requests from the system.

Arguments:

Queue - Handle to the framework queue object that is associated
with the I/O request.
Request - Handle to a framework request object.

OutputBufferLength - length of the request's output buffer,
if an output buffer is available.
InputBufferLength - length of the request's input buffer,
if an input buffer is available.

IoControlCode - the driver-defined or system-defined I/O control code
(IOCTL) that is associated with the request.
Return Value:

VOID
--*/
VOID PSDrv_EvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode)
{
    WDFDEVICE					 device;
    PVOID						 ioBuffer;
    size_t						 bufLength;
    NTSTATUS					 status;
    PDEVICE_CONTEXT				 pDevContext;
    PFILE_CONTEXT				 pFileContext;
    ULONG						 length = 0;
	PSUSBDRV_PIPE_PROPERTY*		 pPipeProp;
	PSUSBDRV_CONTROL_TRANSFER*	 pControlTransfer;
	PSUSBDRV_DRIVER_VERSION*	 pDriverVersion;
	PSUSBDRV_INTERFACE_PROPERTY* pInterfaceProperty;
	unsigned int*				 pnDeviceSpeed;
	WDFMEMORY					 WdfMem = NULL; 
	PUCHAR                       pControlBuffer;
	WDFMEMORY					 WdfMemOut = NULL;

	
	WDF_USB_INTERFACE_SELECT_SETTING_PARAMS  selectSettingParams;

    UNREFERENCED_PARAMETER(InputBufferLength);

    PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - begins\n"));

    PAGED_CODE();

    // initialize variables
    device = WdfIoQueueGetDevice(Queue);
    pDevContext = GetDeviceContext(device);

    switch(IoControlCode)
	{
		case IOCTL_PSDRV_RESET_PIPE:
			PSDrv_DbgPrint(3, ("IOControl: ResetPipe\n"));

			pFileContext = GetFileContext(WdfRequestGetFileObject(Request));

			if (pFileContext->Pipe == NULL)
			{
				PSDrv_DbgPrint(3, ("Invalid pipe!\n"));
				status = STATUS_INVALID_PARAMETER;
			}
			else
			{
				status = ResetPipe(pFileContext->Pipe);
			}

			break;

		case IOCTL_PSDRV_ABORT_PIPE:
			PSDrv_DbgPrint(3, ("IOControl: AbortPipe\n"));

			pFileContext = GetFileContext(WdfRequestGetFileObject(Request));

			if (pFileContext->Pipe == NULL)
			{
				PSDrv_DbgPrint(3, ("Invalid pipe!\n"));
				status = STATUS_INVALID_PARAMETER;
			}
			else
			{
				status = AbortPipe(pFileContext->Pipe);
			}

			break;

		case IOCTL_PSDRV_GET_CONFIG_DESCRIPTOR:
			PSDrv_DbgPrint(3, ("IOControl: GetConfigDescriptor\n"));

			if (pDevContext->UsbConfigurationDescriptor)
			{
				length = pDevContext->UsbConfigurationDescriptor->wTotalLength;

				status = WdfRequestRetrieveOutputBuffer(Request, length, &ioBuffer, &bufLength);
				if(!NT_SUCCESS(status))
				{
					PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status));
					status = STATUS_INVALID_PARAMETER;
					break;
				}

				RtlCopyMemory(ioBuffer, pDevContext->UsbConfigurationDescriptor, length);

				status = STATUS_SUCCESS;
			}
			else
			{
				PSDrv_DbgPrint(3, ("UsbConfigurationDescriptor is NULL!\n"));
				status = STATUS_INVALID_DEVICE_STATE;
			}

			break;

		case IOCTL_PSDRV_RESET_DEVICE:
			PSDrv_DbgPrint(3, ("IOControl: ResetDevice\n"));

			status = ResetDevice(device);

			break;

		case IOCTL_PSDRV_CONTROL_TRANSFER:
			PSDrv_DbgPrint(3, ("IOControl: ControlTransfer\n"));

			//Get a pointer to the input buffer
			status = WdfRequestRetrieveInputMemory(Request, &WdfMem);
			if(!NT_SUCCESS(status))
			{
				PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			if (WdfMem == NULL)
			{
				PSDrv_DbgPrint(1, ("WdfMem is NULL!\n"));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			pControlTransfer = WdfMemoryGetBuffer(WdfMem, NULL);
			if (pControlTransfer == NULL)
			{
				PSDrv_DbgPrint(1, ("pControlTransfer is NULL!\n"));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			//Get a pointer to the output buffer
			if (OutputBufferLength != 0)
			{
				status = WdfRequestRetrieveOutputMemory(Request, &WdfMemOut);
				if(!NT_SUCCESS(status))
				{
					PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputMemory failed! (Status = %x)\n", status));
					status = STATUS_INVALID_PARAMETER;
					break;
				}

				if (WdfMemOut == NULL)
				{
					PSDrv_DbgPrint(1, ("WdfMemOut is NULL!\n"));
					status = STATUS_INVALID_PARAMETER;
					break;
				}

				pControlBuffer = WdfMemoryGetBuffer(WdfMemOut, NULL);
				if (pControlBuffer == NULL)
				{
					PSDrv_DbgPrint(1, ("pControlBuffer is NULL!\n"));
					status = STATUS_INVALID_PARAMETER;
					break;
				}
			}
			else
			{
				PSDrv_DbgPrint(1, ("This control request has no buffer...\n"));
				pControlBuffer = NULL;
			}

			// Call the control transfer function
			status = ControlTransfer(pDevContext, pControlTransfer, pControlBuffer, OutputBufferLength, &length);

			break;

		case IOCTL_PSDRV_SET_PIPE_PROPERTY:
			PSDrv_DbgPrint(3, ("IOControl: SetPipeProperty\n"));

			status = WdfRequestRetrieveInputMemory(Request, &WdfMem); 
			if(!NT_SUCCESS(status))
			{
				PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			if (WdfMem == NULL)
			{
				PSDrv_DbgPrint(1, ("WdfMem is NULL!\n"));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			pPipeProp = WdfMemoryGetBuffer(WdfMem, NULL);
			if (pPipeProp == NULL)
			{
				PSDrv_DbgPrint(1, ("pPipeProp is NULL!\n"));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			pFileContext = GetFileContext(WdfRequestGetFileObject(Request));
			if (pFileContext->Pipe == NULL)
			{
				PSDrv_DbgPrint(3, ("Invalid pipe!\n"));
				status = STATUS_INVALID_PARAMETER;
			}
			else
			{
				status = SetPipeProperty(pFileContext, pPipeProp);
			}

			break;

		case IOCTL_PSDRV_SET_INTERFACE:
			PSDrv_DbgPrint(3, ("IOControl: SetInterface\n"));

			status = WdfRequestRetrieveInputMemory(Request, &WdfMem); 
			if(!NT_SUCCESS(status))
			{
				PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			if (WdfMem == NULL)
			{
				PSDrv_DbgPrint(1, ("WdfMem is NULL!\n"));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			pInterfaceProperty = WdfMemoryGetBuffer(WdfMem, NULL);
			if (pInterfaceProperty == NULL)
			{
				PSDrv_DbgPrint(1, ("pInterfaceProperty is NULL!\n"));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			PSDrv_DbgPrint(3, ("SetInterface: Going to change AltIF to %d...\n", pInterfaceProperty->nAltIF));

			WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&selectSettingParams, pInterfaceProperty->nAltIF);

			status = WdfUsbInterfaceSelectSetting(pDevContext->UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &selectSettingParams);

			if (status == STATUS_SUCCESS)
			{
				pDevContext->nCurrIf = 0;
				pDevContext->nCurrAltIf = pInterfaceProperty->nAltIF;

				PSDrv_DbgPrint(3, ("SetInterface: AltIF is now %d...\n", pInterfaceProperty->nAltIF));
			}

			break;

		case IOCTL_PSDRV_GET_INTERFACE:
			PSDrv_DbgPrint(3, ("IOControl: GetInterface\n"));

			length = sizeof(PSUSBDRV_INTERFACE_PROPERTY);

			status = WdfRequestRetrieveOutputBuffer(Request, length, &pInterfaceProperty, &bufLength);
			if(!NT_SUCCESS(status))
			{
				PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			pInterfaceProperty->nIF = pDevContext->nCurrIf;
			pInterfaceProperty->nAltIF = pDevContext->nCurrAltIf;

			status = STATUS_SUCCESS;

			break;

		case IOCTL_PSDRV_GET_DRIVER_VERSION:
			PSDrv_DbgPrint(3, ("IOControl: GetDriverVersion\n"));

			length = sizeof(PSUSBDRV_DRIVER_VERSION);

			status = WdfRequestRetrieveOutputBuffer(Request, length, &pDriverVersion, &bufLength);
			if(!NT_SUCCESS(status))
			{
				PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			pDriverVersion->nMajor = PSUSBDRV_MAJOR_VERSION;
			pDriverVersion->nMinor = PSUSBDRV_MINOR_VERSION;
			pDriverVersion->nMaintenance = PSUSBDRV_MAINTENANCE_VERSION;
			pDriverVersion->nBuild = PSUSBDRV_BUILD_VERSION;
			
			status = STATUS_SUCCESS;

			break;

		case IOCTL_PSDRV_GET_DEVICE_SPEED:
			PSDrv_DbgPrint(3, ("IOControl: GetDeviceSpeed\n"));

			length = sizeof(unsigned int);

			status = WdfRequestRetrieveOutputBuffer(Request, length, &pnDeviceSpeed, &bufLength);
			if(!NT_SUCCESS(status))
			{
				PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status));
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			if (pDevContext->IsDeviceHighSpeed == TRUE)
			{
				*pnDeviceSpeed = PSUSBDRV_DEVICE_HIGH_SPEED;
			}
			else
			{
				*pnDeviceSpeed = PSUSBDRV_DEVICE_FULL_SPEED;
			}

			break;

		default:
			PSDrv_DbgPrint(3, ("Unknown IOControl! (ControlCode = %x)\n", IoControlCode));

			status = STATUS_INVALID_DEVICE_REQUEST;

			break;
    }

    WdfRequestCompleteWithInformation(Request, status, length);

	PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - ends\n"));

    return;
}
Пример #10
0
/*++
Routine Description:

This callback is invoked when the framework received  WdfRequestTypeRead or
WdfRequestTypeWrite request. This read/write is performed in stages of
MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the
request is circulated again, until the requested length of transfer is
performed.

Arguments:

Queue - Handle to the framework queue object that is associated
with the I/O request.

Request - Handle to a framework request object. This one represents
the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework.

Length - Length of the input/output buffer.

Return Value:

VOID
--*/
VOID ReadWriteBulkEndPoints(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType)
{
    PMDL						newMdl = NULL;
	PMDL						requestMdl = NULL;
    PURB						urb = NULL;
    WDFMEMORY					urbMemory;
    ULONG						totalLength = Length;
    ULONG						stageLength = 0;
    ULONG						urbFlags = 0;
    NTSTATUS					status;
    ULONG_PTR					virtualAddress = 0;
    PREQUEST_CONTEXT			rwContext = NULL;
    PFILE_CONTEXT				fileContext = NULL;
    WDFUSBPIPE					pipe;
    WDF_USB_PIPE_INFORMATION	pipeInfo;
    WDF_OBJECT_ATTRIBUTES		objectAttribs;
    USBD_PIPE_HANDLE			usbdPipeHandle;
    PDEVICE_CONTEXT				deviceContext;
	WDF_REQUEST_SEND_OPTIONS	sendOptions;

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - begins\n"));

    // First validate input parameters.
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize)
	{
        PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite))
	{
        PSDrv_DbgPrint(1, ("RequestType has to be either Read or Write! (RequestType = %d)\n", RequestType));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    // Get the pipe associate with this request.
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;
    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

    if((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType))
	{
        PSDrv_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt! (PipeType = %d)\n", pipeInfo.PipeType));
        status = STATUS_INVALID_DEVICE_REQUEST;
        goto Exit;
    }

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead)
	{
        status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status))
		{
            PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed! (Status = %x)\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_IN;
        rwContext->Read = TRUE;
        PSDrv_DbgPrint(3, ("This is a read operation...\n"));
    }
	else
	{
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status))
		{
			PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed! (Status = %x)\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
        rwContext->Read = FALSE;
        PSDrv_DbgPrint(3, ("This is a write operation...\n"));
    }


    urbFlags |= USBD_SHORT_TRANSFER_OK;

    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

    // The transfer request is for totalLength. We can perform a max of MAX_TRANSFER_SIZE in each stage.
    if (totalLength > MAX_TRANSFER_SIZE)
	{
        stageLength = MAX_TRANSFER_SIZE;
    }
    else
	{
        stageLength = totalLength;
    }

    newMdl = IoAllocateMdl((PVOID)virtualAddress, totalLength, FALSE, FALSE, NULL);
    if (newMdl == NULL)
	{
        PSDrv_DbgPrint(1, ("IoAllocateMdl failed! (newMdl is NULL)\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    // Map the portion of user-buffer described by an mdl to another mdl
    IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress, stageLength);

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;

    status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*)&urb);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfMemoryCreate for urbMemory failed! (Status = %x)\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);

    UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL);

    status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL);

    // Set REQUEST_CONTEXT parameters.
    rwContext->UrbMemory       = urbMemory;
    rwContext->Mdl             = newMdl;
    rwContext->Length          = totalLength - stageLength;
    rwContext->Numxfer         = 0;
    rwContext->VirtualAddress  = virtualAddress + stageLength;

	// Set the timeout
	if (fileContext->nTimeOut != 0)
	{
		WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT);
		WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(fileContext->nTimeOut));

		PSDrv_DbgPrint(3, ("Pipe timeout is set to: %d\n", fileContext->nTimeOut));

		if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), &sendOptions))
		{
			status = WdfRequestGetStatus(Request);
			ASSERT(!NT_SUCCESS(status));
		}
	}
	else
	{
		if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS))
		{
			status = WdfRequestGetStatus(Request);
			ASSERT(!NT_SUCCESS(status));
		}
	}

Exit:
    if (!NT_SUCCESS(status))
	{
        WdfRequestCompleteWithInformation(Request, status, 0);

        if (newMdl != NULL)
		{
            IoFreeMdl(newMdl);
        }
    }

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - ends\n"));

    return;
}
Пример #11
0
VOID
VIOSerialPortRead(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t     Length
    )
{
    PRAWPDO_VIOSERIAL_PORT  pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue));
    size_t             length;
    NTSTATUS           status;
    PVOID              systemBuffer;
    BOOLEAN            nonBlock;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "-->%s\n", __FUNCTION__);

    nonBlock = ((WdfFileObjectGetFlags(WdfRequestGetFileObject(Request)) & FO_SYNCHRONOUS_IO) != FO_SYNCHRONOUS_IO);

    status = WdfRequestRetrieveOutputBuffer(Request, Length, &systemBuffer, &length);
    if (!NT_SUCCESS(status))
    {
        WdfRequestComplete(Request, status);
        return;
    }

	WdfSpinLockAcquire(pdoData->port->InBufLock);

	if (!VIOSerialPortHasDataLocked(pdoData->port))
    {
        if (!pdoData->port->HostConnected)
        {
           WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
        }
		else
		{
			ASSERT (pdoData->port->PendingReadRequest == NULL);
			status = WdfRequestMarkCancelableEx(Request,
				VIOSerialPortReadRequestCancel);
			if (!NT_SUCCESS(status))
			{
				WdfRequestComplete(Request, status);
			}
			else
			{
				pdoData->port->PendingReadRequest = Request;
			}
		}
    }
    else
    {
        length = (ULONG)VIOSerialFillReadBufLocked(pdoData->port, systemBuffer, length);
        if (length)
        {
           WdfRequestCompleteWithInformation(Request, status, (ULONG_PTR)length);
        }
        else
        {
           WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
        }
    }
    WdfSpinLockRelease(pdoData->port->InBufLock);
    
	TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,"<-- %s\n", __FUNCTION__);
    return;
}
void
DeviceContext::DeviceIo(
    _In_ WDFREQUEST Request,
    _In_ size_t /*OutputBufferLength*/,
    _In_ size_t /*InputBufferLength*/,
    _In_ ULONG IoControlCode
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request);
    FileObjectContext* fileContext = FileObjectGetContext(fileObject);

    using CommandFunctionType = NTSTATUS (DeviceContext::*)(_In_ WDFREQUEST Request);
    CommandFunctionType commandFunction = nullptr;
    switch (fileContext->GetType())
    {
    case FileObjectContext::Type::NciSim:
        switch (IoControlCode)
        {
        case IOCTL_NCISIM_GET_NEXT_CALLBACK:
            commandFunction = &DeviceContext::CommandGetNextCallback;
            break;

        case IOCTL_NCISIM_NCI_READ:
            commandFunction = &DeviceContext::CommandNciRead;
            break;

        case IOCTL_NCISIM_HARDWARE_EVENT:
            commandFunction = &DeviceContext::CommandHardwareEvent;
            break;

        case IOCTL_NCISIM_SEQUENCE_HANDLER_COMPLETE:
            commandFunction = &DeviceContext::CommandSequenceHandlerComplete;
            break;

        case IOCTL_NCISIM_NCI_WRITE_COMPLETE:
            commandFunction = &DeviceContext::CommandNciWriteComplete;
            break;
        }
        break;
    }

    NTSTATUS commandStatus = STATUS_SUCCESS;
    if (commandFunction)
    {
        commandStatus = (this->*commandFunction)(Request);
    }
    else
    {
        commandStatus = STATUS_INVALID_DEVICE_STATE;
        TRACE_LINE(LEVEL_ERROR, "Unsupported IOCTL (%d): 0x%08X. %!STATUS!", int(fileContext->GetType()), IoControlCode, commandStatus);
    }

    if (!NT_SUCCESS(commandStatus))
    {
        TRACE_LINE(LEVEL_ERROR, "Request failed. %!STATUS!", commandStatus);
        WdfRequestComplete(Request, commandStatus);
        return;
    }

    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
}
Пример #13
0
VOID
ReadWriteBulkEndPoints(
    _In_ WDFQUEUE         Queue,
    _In_ WDFREQUEST       Request,
    _In_ ULONG            Length,
    _In_ WDF_REQUEST_TYPE RequestType
    )
/*++

Routine Description:

    This callback is invoked when the framework received  WdfRequestTypeRead or
    RP_MJ_WRITE request. This read/write is performed in stages of
    maximum transfer size. Once a stage of transfer is complete, then the
    request is circulated again, until the requested length of transfer is
    performed.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.

    Request - Handle to a framework request object. This one represents
              the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework.

    Length - Length of the input/output buffer.

Return Value:

   VOID

--*/
{
    size_t                totalLength = Length;
    size_t                stageLength = 0;
    NTSTATUS              status;
    PVOID                 virtualAddress = 0;
    PREQUEST_CONTEXT      rwContext = NULL;
    PFILE_CONTEXT         fileContext = NULL;
    WDFUSBPIPE            pipe;
    WDF_USB_PIPE_INFORMATION pipeInfo;
    WDFMEMORY             reqMemory;
    WDFMEMORY_OFFSET      offset;
    WDF_OBJECT_ATTRIBUTES objectAttribs;
    PDEVICE_CONTEXT       deviceContext;
    PPIPE_CONTEXT         pipeContext;

    ULONG                 maxTransferSize;
 
    UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - begins\n"));

    //
    // First validate input parameters.
    //
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize) {
        UsbSamp_DbgPrint(1, ("Transfer length > circular buffer\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) &&
        (RequestType != WdfRequestTypeWrite)) {
        UsbSamp_DbgPrint(1, ("RequestType has to be either Read or Write\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    //
    // Get the pipe associate with this request.
    //
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;
    pipeContext = GetPipeContext(pipe);
    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

    rwContext = GetRequestContext(Request);

    if (RequestType == WdfRequestTypeRead) {
        status = WdfRequestRetrieveOutputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = TRUE;

    } 
    else { //Write

        status = WdfRequestRetrieveInputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = FALSE;
    }

    if (!NT_SUCCESS(status)){
        UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n"));
        goto Exit;
    }

    //
    // The transfer request is for totalLength.
    // We can perform a max of maxTransfersize in each stage.
    //
    maxTransferSize = GetMaxTransferSize(pipe, deviceContext);

    if (totalLength > maxTransferSize) {
        stageLength = maxTransferSize;
    }
    else {
        stageLength = totalLength;   
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;
    status = WdfMemoryCreatePreallocated(&objectAttribs,
                                         virtualAddress,
                                         totalLength,
                                         &reqMemory);
    if (!NT_SUCCESS(status)){
        UsbSamp_DbgPrint(1, ("WdfMemoryCreatePreallocated failed\n"));
        goto Exit;
    }

    offset.BufferOffset = 0;
    offset.BufferLength = stageLength;

    //
    // The framework format call validates to make sure that you are reading or
    // writing to the right pipe type, sets the appropriate transfer flags,
    // creates an URB and initializes the request.
    //
    if (RequestType == WdfRequestTypeRead) {

        UsbSamp_DbgPrint(3, ("Read operation\n"));
        status = WdfUsbTargetPipeFormatRequestForRead(pipe,
                                                      Request,
                                                      reqMemory,
                                                      &offset);
    } 
    else {

        UsbSamp_DbgPrint(3, ("Write operation\n"));
        status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
                                                       Request,
                                                       reqMemory,
                                                       &offset);
    }

    if (!NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("WdfUsbTargetPipeFormatRequest failed 0x%x\n", status));
        goto Exit;
    }

#if (NTDDI_VERSION >= NTDDI_WIN8)
    //
    // If the request is for a super speed bulk pipe with streams,
    // configure its urb's PipeHandle with its associated stream's PipeHandle
    //
    if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
        pipeContext->StreamConfigured == TRUE) {
        ConfigureStreamPipeHandleForRequest(Request, pipe);
    }
#endif

    WdfRequestSetCompletionRoutine(
                            Request,
                            UsbSamp_EvtReadWriteCompletion,
                            deviceContext);
    //
    // set REQUEST_CONTEXT parameters.
    //
    rwContext->Length  = (ULONG)totalLength - (ULONG)stageLength;
    rwContext->Numxfer = 0;

    //
    // Send the request asynchronously.
    //
    if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) {
        UsbSamp_DbgPrint(1, ("WdfRequestSend failed\n"));
        status = WdfRequestGetStatus(Request);
        goto Exit;
    }


Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(Request, status, 0);
    }

    UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - ends\n"));

    return;
}
Пример #14
0
VOID
ReadWriteBulkEndPoints(
    _In_ WDFQUEUE         Queue,
    _In_ WDFREQUEST       Request,
    _In_ ULONG            Length,
    _In_ WDF_REQUEST_TYPE RequestType
    )
/*++

Routine Description:

    This callback is invoked when the framework received  WdfRequestTypeRead or
    WdfRequestTypeWrite request. This read/write is performed in stages of
    maximum transfer size. Once a stage of transfer is complete, then the
    request is circulated again, until the requested length of transfer is
    performed.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.

    Request - Handle to a framework request object. This one represents
              the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework.

    Length - Length of the input/output buffer.

Return Value:

   VOID

--*/
{
    PMDL                    newMdl=NULL, requestMdl = NULL;
    PURB                    urb = NULL;
    WDFMEMORY               urbMemory;
    ULONG                   totalLength = Length;
    ULONG                   stageLength = 0;
    ULONG                   urbFlags = 0;
    NTSTATUS                status;
    ULONG_PTR               virtualAddress = 0;
    PREQUEST_CONTEXT        rwContext = NULL;
    PFILE_CONTEXT           fileContext = NULL;
    WDFUSBPIPE              pipe;
    WDF_USB_PIPE_INFORMATION   pipeInfo;
    WDF_OBJECT_ATTRIBUTES   objectAttribs;
    USBD_PIPE_HANDLE        usbdPipeHandle;
    PDEVICE_CONTEXT         deviceContext;
    ULONG                   maxTransferSize;
    PPIPE_CONTEXT           pipeContext;

    UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - begins\n"));

    //
    // First validate input parameters.
    //
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize) {
        UsbSamp_DbgPrint(1, ("Transfer length > circular buffer\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) &&
        (RequestType != WdfRequestTypeWrite)) {
        UsbSamp_DbgPrint(1, ("RequestType has to be either Read or Write\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    //
    // Get the pipe associate with this request.
    //
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;
    pipeContext = GetPipeContext(pipe);
    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

    if ((WdfUsbPipeTypeBulk != pipeInfo.PipeType) &&
            (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType)) {
        UsbSamp_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt\n"));
        status = STATUS_INVALID_DEVICE_REQUEST;
        goto Exit;

    }

    rwContext = GetRequestContext(Request);

    if (RequestType == WdfRequestTypeRead) {

        status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
        if (!NT_SUCCESS(status)){
            UsbSamp_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_IN;
        rwContext->Read = TRUE;
        UsbSamp_DbgPrint(3, ("Read operation\n"));

    } 
    else {
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if (!NT_SUCCESS(status)){
            UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed %x\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
        rwContext->Read = FALSE;
        UsbSamp_DbgPrint(3, ("Write operation\n"));
    }

    urbFlags |= USBD_SHORT_TRANSFER_OK;
    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

    //
    // The transfer request is for totalLength.
    // We can perform a max of maxTransfersize in each stage.
    //
    maxTransferSize = GetMaxTransferSize(pipe, deviceContext);

    if (totalLength > maxTransferSize) {
        stageLength = maxTransferSize;
    }
    else {
        stageLength = totalLength;
    }

    newMdl = IoAllocateMdl((PVOID) virtualAddress,
                           totalLength,
                           FALSE,
                           FALSE,
                           NULL);

    if (newMdl == NULL) {
        UsbSamp_DbgPrint(1, ("Failed to alloc mem for mdl\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    //
    // map the portion of user-buffer described by an mdl to another mdl
    //
    IoBuildPartialMdl(requestMdl,
                      newMdl,
                      (PVOID) virtualAddress,
                      stageLength);

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;

    status = WdfUsbTargetDeviceCreateUrb(deviceContext->WdfUsbTargetDevice,
		                     &objectAttribs,
                             &urbMemory,
                             &urb);

    if (!NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("WdfUsbTargetDeviceCreateUrb failed %x\n", status));
        goto Exit;
    }

#if (NTDDI_VERSION >= NTDDI_WIN8)
    if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
        pipeContext->StreamConfigured == TRUE) {
        //
        // For super speed bulk pipe with streams, we specify one of its associated 
        // usbd pipe handles to format an URB for sending or receiving data. 
        // The usbd pipe handle is returned by the HCD via sucessful open-streams request
        //
        usbdPipeHandle = GetStreamPipeHandleFromBulkPipe(pipe);
    }
    else {
        usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);
    }
#else
    usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);
#endif

    UsbBuildInterruptOrBulkTransferRequest(urb,
                                           sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                                           usbdPipeHandle,
                                           NULL,
                                           newMdl,
                                           stageLength,
                                           urbFlags,
                                           NULL);

    status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL  );
    if (!NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("Failed to format requset for urb\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(Request, UsbSamp_EvtReadWriteCompletion, deviceContext);

    //
    // set REQUEST_CONTEXT  parameters.
    //
    rwContext->UrbMemory       = urbMemory;
    rwContext->Mdl             = newMdl;
    rwContext->Length          = totalLength - stageLength;
    rwContext->Numxfer         = 0;
    rwContext->VirtualAddress  = virtualAddress + stageLength;

    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
        status = WdfRequestGetStatus(Request);
        NT_ASSERT(!NT_SUCCESS(status));
    }

Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(Request, status, 0);

        if (newMdl != NULL) {
            IoFreeMdl(newMdl);
        }
    }

    UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - ends\n"));

    return;
}
Пример #15
0
VCHIQ_PAGED_SEGMENT_BEGIN

/*++

Routine Description:

     VchiqIoDeviceControl handles VCHIQ IOCTL.

Arguments:

     DeviceContextPtr - Pointer to device context

     WdfRequest - A handle to a framework request object.

     OutputBufferLength - The length, in bytes, of the request's output buffer,
          if an output buffer is available.

     InputBufferLength - The length, in bytes, of the request's input buffer,
          if an input buffer is available.

     IoControlCode - The driver-defined or system-defined I/O control code
          (IOCTL) that is associated with the request.

Return Value:

     None

--*/
_Use_decl_annotations_
VOID VchiqIoDeviceControl (
    WDFQUEUE Queue,
    WDFREQUEST WdfRequest,
    size_t OutputBufferLength,
    size_t InputBufferLength,
    ULONG IoControlCode
    )
{
    NTSTATUS status;
    VCHIQ_FILE_CONTEXT* vchiqFileContextPtr;
    WDFDEVICE device = WdfIoQueueGetDevice(Queue);
    DEVICE_CONTEXT* deviceContextPtr = VchiqGetDeviceContext(device);

    PAGED_CODE();

    if (deviceContextPtr->VCConnected == FALSE) {
        VCHIQ_LOG_WARNING("VCHIQ interface not ready");
        status = STATUS_DEVICE_NOT_READY;
        goto CompleteRequest;
    }

    // First process IOCTL that does not require a file context
    switch (IoControlCode)
    {
    case IOCTL_VCHIQ_CONNECT:
        {
            // Connect is a simple ioctl to ensure that we have establish 
            // connection with VC firmware. Connection is establish by 
            // initiating the slots which if we reach this point has 
            // already been initialize. We just send a message to notify
            // the firmware too
            WDFFILEOBJECT wdfFileObject = WdfRequestGetFileObject(WdfRequest);
            if (wdfFileObject == NULL) {
                WDF_REQUEST_PARAMETERS wdfRequestParameters;
                WdfRequestGetParameters(WdfRequest, &wdfRequestParameters);
                VCHIQ_LOG_ERROR(
                    "Fail to retrieve file object. \
                         (WdfRequest = 0x%p, Type = 0x%lx)",
                    WdfRequest,
                    (ULONG)wdfRequestParameters.Type);
                status = STATUS_INTERNAL_ERROR;
                goto CompleteRequest;
            }

            // Create a file context here as vchiq_arm would immediately begin
            // to send IOCTL to wait for completion message
            vchiqFileContextPtr = VchiqGetFileContext(wdfFileObject);
            if (vchiqFileContextPtr != NULL) {
                VCHIQ_LOG_ERROR(
                    "Caller has already connected to a service");
                status = STATUS_UNSUCCESSFUL;
                goto CompleteRequest;
            }

            status = VchiqAllocateFileObjContext(
                deviceContextPtr,
                wdfFileObject,
                &vchiqFileContextPtr);
            if (!NT_SUCCESS (status)) {
                VCHIQ_LOG_ERROR(
                    "VchiqAllocateFileObjContext failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            status = VchiqQueueMessageAsync(
                deviceContextPtr,
                vchiqFileContextPtr,
                VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0),
                NULL,
                0);
            if (!NT_SUCCESS (status)) {
                VCHIQ_LOG_ERROR(
                    "VchiqQueueMessageAsync failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            goto CompleteRequest;
        }
    case IOCTL_VCHIQ_GET_CONFIG:
        {
            VCHIQ_CONFIG vchiqCurrentConfig =
                {
                    VCHIQ_MAX_MSG_SIZE,
                    VCHIQ_MAX_MSG_SIZE,
                    VCHIQ_NUM_SERVICE_BULKS,
                    VCHIQ_MAX_SERVICES,
                    VCHIQ_VERSION,
                    VCHIQ_VERSION_MIN
                };

            VCHIQ_GET_CONFIG* clientConfigPtr;
            status = WdfRequestRetrieveInputBuffer(
                WdfRequest,
                sizeof(*clientConfigPtr),
                &clientConfigPtr,
                NULL);
            if (!NT_SUCCESS(status)) {
                VCHIQ_LOG_ERROR(
                    "WdfRequestRetrieveInputBuffer failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            // Ensure that the buffer provided is not too big.
            if (clientConfigPtr->ConfigSize > sizeof(VCHIQ_CONFIG)) {
                VCHIQ_LOG_WARNING("Config buffer too big");
                status = STATUS_INVALID_PARAMETER;
                goto CompleteRequest;
            }

            VCHIQ_CONFIG* configurationPtr;
            size_t bufferSize;
            configurationPtr = WdfMemoryGetBuffer(
                clientConfigPtr->WdfMemoryConfiguration,
                &bufferSize);
            if ((configurationPtr == NULL) ||
                (bufferSize != sizeof(*configurationPtr))) {
                VCHIQ_LOG_ERROR(
                    "Caller provided invalid VCHIQ_CONFIG buffer 0x%08x %d",
                    (ULONG)configurationPtr,
                    bufferSize);
                status = STATUS_INVALID_PARAMETER;
                goto CompleteRequest;
            }

            RtlCopyMemory(
                configurationPtr,
                &vchiqCurrentConfig, 
                sizeof(*clientConfigPtr->PConfig));

            status = STATUS_SUCCESS;
        }
        goto CompleteRequest;
    case IOCTL_VCHIQ_LIB_VERSION:
        {
            ULONG* libVersion;
            status = WdfRequestRetrieveInputBuffer(
                WdfRequest,
                sizeof(*libVersion),
                &libVersion,
                NULL);
            if (!NT_SUCCESS(status)) {
                VCHIQ_LOG_ERROR(
                    "WdfRequestRetrieveInputBuffer failed (%!STATUS!)",
                    status);
                goto CompleteRequest;
            }

            if (*libVersion < VCHIQ_VERSION_MIN) {
                VCHIQ_LOG_ERROR(
                    "Library version %d unsupported",
                    *libVersion);
                status = STATUS_NOT_SUPPORTED;
                goto CompleteRequest;
            }
            status = STATUS_SUCCESS;
        }
        goto CompleteRequest;
    case IOCTL_VCHIQ_CREATE_SERVICE:
    default:
        {
            WDFFILEOBJECT wdfFileObject = WdfRequestGetFileObject(WdfRequest);
            if (wdfFileObject == NULL) {
                WDF_REQUEST_PARAMETERS wdfRequestParameters;
                WdfRequestGetParameters(WdfRequest, &wdfRequestParameters);
                VCHIQ_LOG_ERROR(
                    "Fail to retrieve file object. \
                         (WdfRequest = 0x%p, Type = 0x%lx)",
                    WdfRequest,
                    (ULONG)wdfRequestParameters.Type);
                status = STATUS_INTERNAL_ERROR;
                goto CompleteRequest;
            }

            vchiqFileContextPtr = VchiqGetFileContext(wdfFileObject);
            if ((vchiqFileContextPtr == NULL) &&
                (IoControlCode == IOCTL_VCHIQ_CREATE_SERVICE)) {

                // Functional test does not call connect prior to a create
                // service call, so we allocate a file context here instead
                status = VchiqAllocateFileObjContext(
                    deviceContextPtr,
                    wdfFileObject,
                    &vchiqFileContextPtr);
                if (!NT_SUCCESS (status)) {
                    VCHIQ_LOG_ERROR(
                        "VchiqAllocateFileObjContext failed (%!STATUS!)",
                        status);
                    goto CompleteRequest;
                }
            } else if (vchiqFileContextPtr == NULL) {
                VCHIQ_LOG_ERROR(
                    "Caller has not connected to a service %d",
                    ((IoControlCode >> 2) & 0x0FFF));
                status = STATUS_UNSUCCESSFUL;
                goto CompleteRequest;
            }
        }
    }
static VOID
XenBus_EvtIoWrite(WDFQUEUE queue, WDFREQUEST request, size_t length)
{
  NTSTATUS status;
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfIoQueueGetDevice(queue));
  WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;
  WDFREQUEST read_request;

  PUCHAR buffer;
  PUCHAR src_ptr;
  ULONG src_len;
  PUCHAR dst_ptr;
  ULONG copy_len;
  struct xsd_sockmsg *rep;
  xenbus_read_queue_item_t *list_entry;
  watch_context_t *watch_context;
  PCHAR watch_path;
  PCHAR watch_token;
  PCHAR msg;
  
  FUNCTION_ENTER();
  
  status = WdfRequestRetrieveInputBuffer(request, length, &buffer, NULL);
  ASSERT(NT_SUCCESS(status));
  
  src_ptr = (PUCHAR)buffer;
  src_len = (ULONG)length;
  dst_ptr = xpdid->xenbus.u.buffer + xpdid->xenbus.len;
  while (src_len != 0)
  {
    KdPrint((__DRIVER_NAME "     %d bytes of write buffer remaining\n", src_len));
    /* get a complete msg header */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
      continue;
    /* get a complete msg body */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      continue;
    }
    
    switch (xpdid->xenbus.u.msg.type)
    {
    case XS_WATCH:
    case XS_UNWATCH:
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      watch_context = (watch_context_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(watch_context_t), XENPCI_POOL_TAG);
      watch_path = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg));
      watch_token = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg) + strlen(watch_path) + 1);
      RtlStringCbCopyA(watch_context->path, ARRAY_SIZE(watch_context->path), watch_path);
      RtlStringCbCopyA(watch_context->token, ARRAY_SIZE(watch_context->path), watch_token);
      watch_context->file_object = file_object;
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        InsertTailList(&xpdid->xenbus.watch_list_head, &watch_context->entry);
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        msg = XenBus_AddWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      else
        msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      if (msg != NULL)
      {
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(msg) + 1, XENPCI_POOL_TAG);
        rep->type = XS_ERROR;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = (ULONG)(strlen(msg) + 0);
        RtlStringCbCopyA((PCHAR)(rep + 1), strlen(msg) + 1, msg);
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
          RemoveEntryList(&watch_context->entry);
      }
      else
      {
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
        {
          WdfObjectReference(file_object);
        }
        else
        {
          RemoveEntryList(&watch_context->entry);
          WdfObjectDereference(file_object);
        }
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg), XENPCI_POOL_TAG);
        rep->type = xpdid->xenbus.u.msg.type;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = 0;
      }
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      break;
    default:
      rep = XenBus_Raw(xpdd, &xpdid->xenbus.u.msg);
      break;
    }
    xpdid->xenbus.len = 0;
    
    KeAcquireSpinLock(&xpdid->lock, &old_irql);
    list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
    list_entry->data = rep;
    list_entry->length = sizeof(*rep) + rep->len;
    list_entry->offset = 0;
    InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry);

	// Check if someone was waiting for the answer already
	status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &read_request);
    if (NT_SUCCESS(status))
    {
		WDF_REQUEST_PARAMETERS parameters;
		KdPrint((__DRIVER_NAME "     post-write: found pending read\n"));
		WDF_REQUEST_PARAMETERS_INIT(&parameters);
		WdfRequestGetParameters(read_request, &parameters);
		XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, read_request, parameters.Parameters.Read.Length);
		WdfRequestComplete(read_request, STATUS_SUCCESS);
    }
    else
    {
		KdPrint((__DRIVER_NAME "     post-write: no pending read (%08x)\n", status));
    }

    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  KdPrint((__DRIVER_NAME "     completing request with length %d\n", length));
  WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, length);

  FUNCTION_EXIT();
}
Пример #17
0
VOID
NdisProtEvtIoWrite(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN size_t           Length
    )
/*++

Routine Description:

    Dispatch routine to handle Request_MJ_WRITE.

Arguments:

    Queue - Default queue handle
    Request - Handle to the read/write request
    Lenght - Length of the data buffer associated with the request.
                 The default property of the queue is to not dispatch
                 zero lenght read & write requests to the driver and
                 complete is with status success. So we will never get
                 a zero length request.

Return Value:

    VOID

--*/
{
    ULONG                   DataLength;
    NTSTATUS                NtStatus;
    PNDISPROT_OPEN_CONTEXT  pOpenContext;
    PNET_BUFFER_LIST        pNetBufferList;
    NDISPROT_ETH_HEADER UNALIGNED *pEthHeader;
    PVOID                   CancelId;
    ULONG                   SendFlags = 0;
    PMDL                    pMdl = NULL;
    WDFFILEOBJECT           fileObject;
    PREQUEST_CONTEXT        reqContext;
    WDF_OBJECT_ATTRIBUTES   attributes;

    UNREFERENCED_PARAMETER(Queue);

    fileObject = WdfRequestGetFileObject(Request);
    pOpenContext = GetFileObjectContext(fileObject)->OpenContext;

    do
    {
        //
        // Create a context to track the length of transfer and NDIS packet
        // associated with this request.
        //
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);

        NtStatus = WdfObjectAllocateContext(Request, &attributes, &reqContext);
        if(!NT_SUCCESS(NtStatus)){
            DEBUGP(DL_WARN, ("Write: WdfObjectAllocateContext failed: %x\n", NtStatus));
            NtStatus = STATUS_INVALID_HANDLE;
            break;

        }

        reqContext->Length = (ULONG) Length;

        if (pOpenContext == NULL)
        {
            DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n",
                fileObject));
            NtStatus = STATUS_INVALID_HANDLE;
            break;
        }

        NPROT_STRUCT_ASSERT(pOpenContext, oc);

        NtStatus = WdfRequestRetrieveInputWdmMdl(Request, &pMdl);
        if (!NT_SUCCESS(NtStatus))
        {
            DEBUGP(DL_FATAL, ("Write: WdfRequestRetrieveInputWdmMdl failed %x\n", NtStatus));
            break;
        }

        //
        // Try to get a virtual address for the MDL.
        //
        pEthHeader = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority | MdlMappingNoExecute);

        if (pEthHeader == NULL)
        {
            DEBUGP(DL_FATAL, ("Write: MmGetSystemAddr failed for"
                    " Request %p, MDL %p\n",
                    Request, pMdl));
            NtStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        //
        // Sanity-check the length.
        //
        DataLength = MmGetMdlByteCount(pMdl);
        if (DataLength < sizeof(NDISPROT_ETH_HEADER))
        {
            DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)\n",
                DataLength));
            NtStatus = STATUS_BUFFER_TOO_SMALL;
            break;
        }

        if (DataLength > (pOpenContext->MaxFrameSize + sizeof(NDISPROT_ETH_HEADER)))
        {
            DEBUGP(DL_WARN, ("Write: Open %p: data length (%d)"
                    " larger than max frame size (%d)\n",
                    pOpenContext, DataLength, pOpenContext->MaxFrameSize));

            NtStatus = STATUS_INVALID_BUFFER_SIZE;
            break;
        }

        //
        // To prevent applications from sending packets with spoofed
        // mac address, we will do the following check to make sure the source
        // address in the packet is same as the current MAC address of the NIC.
        //
        if ((WdfRequestGetRequestorMode(Request) == UserMode) &&
            !NPROT_MEM_CMP(pEthHeader->SrcAddr, pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN))
        {
            DEBUGP(DL_WARN, ("Write: Failing with invalid Source address"));
            NtStatus = STATUS_INVALID_PARAMETER;
            break;
        }

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE);

        if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_ACTIVE))
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);

            DEBUGP(DL_FATAL, ("Write: Open %p is not bound"
            " or in low power state\n", pOpenContext));

            NtStatus = STATUS_INVALID_HANDLE;
            break;
        }

        if ((pOpenContext->State == NdisprotPaused)
            || (pOpenContext->State == NdisprotPausing))
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);

            DEBUGP(DL_INFO, ("Device is paused.\n"));
            NtStatus = STATUS_UNSUCCESSFUL;
            break;
        }

        NPROT_ASSERT(pOpenContext->SendNetBufferListPool != NULL);
        pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
                                pOpenContext->SendNetBufferListPool,
                                sizeof(NPROT_SEND_NETBUFLIST_RSVD), //Request control offset delta
                                0,           // back fill size
                                pMdl,
                                0,          // Data offset
                                DataLength);

        if (pNetBufferList == NULL)
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);

            DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send net buffer list\n",
                    pOpenContext));
            NtStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
        pOpenContext->PendedSendCount++;

        NPROT_REF_OPEN(pOpenContext);  // pended send

        //
        //  Initialize the NetBufferList ref count. This NetBufferList will be freed
        //  when this count goes to zero.
        //
        NPROT_SEND_NBL_RSVD(pNetBufferList)->RefCount = 1;

        //
        //  We set up a cancel ID on each send NetBufferList (which maps to a Write IRP),
        //  and save the NetBufferList pointer in the IRP. If the IRP gets cancelled, we use
        //  NdisCancelSendNetBufferLists() to cancel the NetBufferList.
        //
        //  Note that this sample code does not implement the cancellation logic. An actual
        //  driver may find value in implementing this.
        //

        CancelId = NPROT_GET_NEXT_CANCEL_ID();
        NDIS_SET_NET_BUFFER_LIST_CANCEL_ID(pNetBufferList, CancelId);
        reqContext->NetBufferList = (PVOID)pNetBufferList;

        NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE);

        //
        //  Set a back pointer from the packet to the IRP.
        //
        NPROT_REQUEST_FROM_SEND_NBL(pNetBufferList) = Request;

        NtStatus = STATUS_PENDING;

        pNetBufferList->SourceHandle = pOpenContext->BindingHandle;
        NPROT_ASSERT (pMdl->Next == NULL);

        SendFlags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK;

        NdisSendNetBufferLists(
                        pOpenContext->BindingHandle,
                        pNetBufferList,
                        NDIS_DEFAULT_PORT_NUMBER,
                        SendFlags);

    }
    while (FALSE);

    if (NtStatus != STATUS_PENDING)
    {
        WdfRequestComplete(Request, NtStatus);
    }

    return;
}
Пример #18
0
VOID
NdisProtEvtIoDeviceControl(
    IN WDFQUEUE     Queue,
    IN WDFREQUEST   Request,
    IN size_t       OutputBufferLength,
    IN size_t       InputBufferLength,
    IN ULONG        IoControlCode
)
/*++

Routine Description:

    This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
    requests from the system.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.
Return Value:

    VOID

--*/
{
    NTSTATUS                NtStatus;
    NDIS_STATUS             Status;
    PNDISPROT_OPEN_CONTEXT  pOpenContext;
    ULONG                   BytesReturned;
    PVOID                   sysBuffer;
    WDFFILEOBJECT           fileObject = WdfRequestGetFileObject(Request);
    size_t                  bufSize;

    UNREFERENCED_PARAMETER(Queue);
    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    DEBUGP(DL_LOUD, ("IoControl: Irp %p\n", Request));

    pOpenContext = GetFileObjectContext(fileObject)->OpenContext;

    BytesReturned = 0;


    switch (IoControlCode)
    {
        case IOCTL_NDISPROT_BIND_WAIT:
            //
            //  Block until we have seen a NetEventBindsComplete event,
            //  meaning that we have finished binding to all running
            //  adapters that we are supposed to bind to.
            //
            //  If we don't get this event in 5 seconds, time out.
            //
            NPROT_ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);

            if (NPROT_WAIT_EVENT(&Globals.BindsComplete, 5000))
            {
                NtStatus = STATUS_SUCCESS;
            }
            else
            {
                NtStatus = STATUS_TIMEOUT;
            }
            DEBUGP(DL_INFO, ("IoControl: BindWait returning %x\n", NtStatus));
            break;

        case IOCTL_NDISPROT_QUERY_BINDING:

            NPROT_ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);

            NtStatus = WdfRequestRetrieveOutputBuffer(Request,
                                        sizeof(NDISPROT_QUERY_BINDING),
                                        &sysBuffer,
                                        &bufSize);
            if( !NT_SUCCESS(NtStatus) ) {
                DEBUGP(DL_FATAL, ("WdfRequestRetrieveOutputBuffer failed %x\n", NtStatus));
                break;
            }

            Status = ndisprotQueryBinding(
                            sysBuffer,
                            (ULONG) bufSize,
                            (ULONG) bufSize,
                            &BytesReturned
                            );

            NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);

            DEBUGP(DL_LOUD, ("IoControl: QueryBinding returning %x\n", NtStatus));

            break;

        case IOCTL_NDISPROT_OPEN_DEVICE:

            NPROT_ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);
            if (pOpenContext != NULL)
            {
                NPROT_STRUCT_ASSERT(pOpenContext, oc);
                DEBUGP(DL_WARN, ("IoControl: OPEN_DEVICE: FileObj %p already"
                    " associated with open %p\n", fileObject, pOpenContext));

                NtStatus = STATUS_DEVICE_BUSY;
                break;
            }

            NtStatus = WdfRequestRetrieveInputBuffer(Request,
                                        0,
                                        &sysBuffer,
                                        &bufSize);
            if( !NT_SUCCESS(NtStatus) ) {
                DEBUGP(DL_FATAL, ("WdfRequestRetrieveInputBuffer failed %x\n", NtStatus));
                break;
            }

            NtStatus = ndisprotOpenDevice(
                            sysBuffer,
                            (ULONG)bufSize,
                            fileObject,
                            &pOpenContext
                            );

            if (NT_SUCCESS(NtStatus))
            {

                DEBUGP(DL_VERY_LOUD, ("IoControl OPEN_DEVICE: Open %p <-> FileObject %p\n",
                        pOpenContext,  fileObject));
            }

            break;

        case IOCTL_NDISPROT_QUERY_OID_VALUE:

            NPROT_ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);

            NtStatus = WdfRequestRetrieveOutputBuffer(Request,
                                        sizeof(NDISPROT_QUERY_OID),
                                        &sysBuffer,
                                        &bufSize);
            if( !NT_SUCCESS(NtStatus) ) {
                DEBUGP(DL_FATAL, ("WdfRequestRetrieveOutputBuffer failed %x\n", NtStatus));
                break;
            }

            if (pOpenContext != NULL)
            {
                Status = ndisprotQueryOidValue(
                            pOpenContext,
                            sysBuffer,
                            (ULONG)bufSize,
                            &BytesReturned
                            );

                NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
            }
            else
            {
                NtStatus = STATUS_DEVICE_NOT_CONNECTED;
            }
            break;

        case IOCTL_NDISPROT_SET_OID_VALUE:

            NPROT_ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);

            NtStatus = WdfRequestRetrieveInputBuffer(Request,
                                        sizeof(NDISPROT_SET_OID),
                                        &sysBuffer,
                                        &bufSize);
            if( !NT_SUCCESS(NtStatus) ) {
                DEBUGP(DL_FATAL, ("WdfRequestRetrieveInputBuffer failed %x\n", NtStatus));
                break;
            }


            if (pOpenContext != NULL)
            {
                Status = ndisprotSetOidValue(
                            pOpenContext,
                            sysBuffer,
                            (ULONG)bufSize
                            );

                BytesReturned = 0;

                NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
            }
            else
            {
                NtStatus = STATUS_DEVICE_NOT_CONNECTED;
            }
            break;

        case IOCTL_NDISPROT_INDICATE_STATUS:

            NPROT_ASSERT((IoControlCode & 0x3) == METHOD_BUFFERED);

            if (pOpenContext != NULL)
            {
                NtStatus = WdfRequestForwardToIoQueue(Request,
                                            pOpenContext->StatusIndicationQueue
                                            );
                if(NT_SUCCESS(NtStatus)) {
                    NtStatus = STATUS_PENDING;
                }
            }
            else
            {
                NtStatus = STATUS_DEVICE_NOT_CONNECTED;
            }
            break;

         default:

            NtStatus = STATUS_NOT_SUPPORTED;
            break;
    }

    if (NtStatus != STATUS_PENDING)
    {
        WdfRequestCompleteWithInformation(Request, NtStatus, BytesReturned);
    }

    return;
}
NTSTATUS
NfcCxSCPresentAbsentDispatcherSetRequest(
    _In_ PNFCCX_FDO_CONTEXT FdoContext,
    _In_ PNFCCX_SC_PRESENT_ABSENT_DISPATCHER Dispatcher,
    _In_ WDFREQUEST Request
    )
/*++

Routine Description:

    Stores a request in the dispatcher. If a request is already pending in the dispatcher, the new request will
    be completed with STATUS_DEVICE_BUSY.

Arguments:

    FdoContext - Pointer to the FDO Context
    Dispatcher - Pointer to the Dispatcher.
    Request - The request to store in the dispatcher.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS status;
    bool powerReferenceAcquired = false;
    bool cancelCallbackSet = false;

    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request);
    PNFCCX_FILE_CONTEXT fileContext = NfcCxFileGetContext(fileObject);

    // Pre-check if there is a current request.
    if (ReadPointerAcquire((void**)&Dispatcher->CurrentRequest) != nullptr)
    {
        status = STATUS_DEVICE_BUSY;
        TRACE_LINE(LEVEL_ERROR, "An Is Present/Absent request is already pending. %!STATUS!", status);
        goto Done;
    }

    // Allocate and initialize the request context
    PNFCCX_SC_REQUEST_CONTEXT requestContext = nullptr;

    WDF_OBJECT_ATTRIBUTES contextAttributes;
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&contextAttributes, NFCCX_SC_REQUEST_CONTEXT);

    status = WdfObjectAllocateContext(Request, &contextAttributes, (void**)&requestContext);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "Failed to set request's context. %!STATUS!", status);
        goto Done;
    }

    requestContext->Dispatcher = Dispatcher;

    // Add a power reference (if required).
    if (Dispatcher->PowerManaged)
    {
        status = NfcCxPowerFileAddReference(FdoContext->Power, fileContext, NfcCxPowerReferenceType_Proximity);
        if (!NT_SUCCESS(status))
        {
            TRACE_LINE(LEVEL_VERBOSE, "Failed to acquire power reference. %!STATUS!", status);
            goto Done;
        }

        powerReferenceAcquired = true;
    }

    // Setup cancel callback.
    status = WdfRequestMarkCancelableEx(Request, NfcCxSCPresentAbsentDispatcherRequestCanceled);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "Failed to set request canceled callback. %!STATUS!", status);
        goto Done;
    }

    // Add a ref-count to the request, which is owned by the cancel callback.
    WdfObjectReference(Request);
    cancelCallbackSet = true;

    // Try to set the current request.
    void* previousRequest = InterlockedCompareExchangePointer((void**)&Dispatcher->CurrentRequest, /*exchange*/ Request, /*compare*/ nullptr);

    // Check if we already have a pending request.
    if (previousRequest != nullptr)
    {
        status = STATUS_DEVICE_BUSY;
        TRACE_LINE(LEVEL_ERROR, "An Is Present/Absent request is already pending. %!STATUS!", status);
        goto Done;
    }

Done:
    if (!NT_SUCCESS(status))
    {
        if (cancelCallbackSet)
        {
            NTSTATUS unmarkStatus = WdfRequestUnmarkCancelable(Request);
            if (unmarkStatus != STATUS_CANCELLED)
            {
                // Cancel callback will not be called.
                // So release cancel callback's request ref-count.
                WdfObjectDereference(Request);
            }
        }

        if (powerReferenceAcquired)
        {
            NfcCxPowerFileRemoveReference(FdoContext->Power, fileContext, NfcCxPowerReferenceType_Proximity);
        }
    }

    TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
    return status;
}
Пример #20
0
VOID
ReadWriteBulkEndPoints(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN ULONG            Length,
    IN WDF_REQUEST_TYPE RequestType
    )
/*++

Routine Description:

    This callback is invoked when the framework received  WdfRequestTypeRead or
    RP_MJ_WRITE request. This read/write is performed in stages of
    MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the
    request is circulated again, until the requested length of transfer is
    performed.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.

    Request - Handle to a framework request object. This one represents
              the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework.

    Length - Length of the input/output buffer.

Return Value:

   VOID

--*/
{
    size_t                totalLength = Length;
    size_t                stageLength = 0;
    NTSTATUS              status;
    PVOID                 virtualAddress = 0;
    PREQUEST_CONTEXT      rwContext = NULL;
    PFILE_CONTEXT         fileContext = NULL;
    WDFUSBPIPE            pipe;
    WDFMEMORY             reqMemory;
    WDFMEMORY_OFFSET      offset;
    WDF_OBJECT_ATTRIBUTES objectAttribs;
    PDEVICE_CONTEXT       deviceContext;

    kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - begins\n"));

    //
    // First validate input parameters.
    //
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize) {
        kJtag_DbgPrint(1, ("Transfer length > circular buffer\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) &&
        (RequestType != WdfRequestTypeWrite)) {
        kJtag_DbgPrint(1, ("RequestType has to be either Read or Write\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    //
    // Get the pipe associate with this request.
    //
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead) {
        status = WdfRequestRetrieveOutputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = TRUE;

    } else { //Write

        status = WdfRequestRetrieveInputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = FALSE;
    }

    if(!NT_SUCCESS(status)){
        kJtag_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n"));
        goto Exit;
    }

    //
    // If the totalLength exceeds MAX_TRANSFER_SIZE, we will break
    // that into multiple transfer of size no more than MAX_TRANSFER_SIZE
    // in each stage.
    //
    if (totalLength > MAX_TRANSFER_SIZE) {
        stageLength = MAX_TRANSFER_SIZE;
    }
    else {
        stageLength = totalLength;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;
    status = WdfMemoryCreatePreallocated(&objectAttribs,
                                         virtualAddress,
                                         totalLength,
                                         &reqMemory);
    if(!NT_SUCCESS(status)){
        kJtag_DbgPrint(1, ("WdfMemoryCreatePreallocated failed\n"));
        goto Exit;
    }

    offset.BufferOffset = 0;
    offset.BufferLength = stageLength;

    //
    // The framework format call validates to make sure that you are reading or
    // writing to the right pipe type, sets the appropriate transfer flags,
    // creates an URB and initializes the request.
    //
    if(RequestType == WdfRequestTypeRead) {

        kJtag_DbgPrint(3, ("Read operation\n"));
        status = WdfUsbTargetPipeFormatRequestForRead(pipe,
                                                      Request,
                                                      reqMemory,
                                                      &offset);
    } else {

        kJtag_DbgPrint(3, ("Write operation\n"));
        status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
                                                       Request,
                                                       reqMemory,
                                                       &offset);
    }

    if (!NT_SUCCESS(status)) {
        kJtag_DbgPrint(1, ("WdfUsbTargetPipeFormatRequest failed 0x%x\n", status));
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(
                            Request,
                            ReadWriteCompletion,
                            NULL);
    //
    // set REQUEST_CONTEXT parameters.
    //
    rwContext->Length  = totalLength - stageLength;
    rwContext->Numxfer = 0;

    //
    // Send the request asynchronously.
    //
    if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) {
        kJtag_DbgPrint(1, ("WdfRequestSend failed\n"));
        status = WdfRequestGetStatus(Request);
        goto Exit;
    }


Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(Request, status, 0);
    }

    kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - ends\n"));

    return;
}
VOID
NfcCxSCPresentAbsentDispatcherCompleteRequest(
    _In_ PNFCCX_FDO_CONTEXT FdoContext,
    _In_ PNFCCX_SC_PRESENT_ABSENT_DISPATCHER Dispatcher
    )
/*++

Routine Description:

    If there is a request in the dispatcher, the request is completed.

Arguments:

    FdoContext - Pointer to the FDO Context
    Dispatcher - Pointer to the Dispatcher

Return Value:

    VOID

--*/
{
    NTSTATUS status = STATUS_SUCCESS;

    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    // Remove the current request from the dispatcher.
    WDFREQUEST request = (WDFREQUEST)InterlockedExchangePointer((void**)&Dispatcher->CurrentRequest, nullptr);

    // Check if another thread has already completed the request.
    if (request == nullptr)
    {
        // Nothing to do.
        goto Done;
    }

    WDFFILEOBJECT fileObject = WdfRequestGetFileObject(request);
    PNFCCX_FILE_CONTEXT fileContext = NfcCxFileGetContext(fileObject);

    // Try to unset the request's cancel callback.
    status = WdfRequestUnmarkCancelable(request);
    if (status != STATUS_CANCELLED)
    {
        // The cancel callback will not be called.
        // So we have to release its ref-count for it.
        WdfObjectDereference(request);

        if (!NT_SUCCESS(status))
        {
            // Something is pretty wrong.
            NT_ASSERT(false);

            TRACE_LINE(LEVEL_ERROR, "Failed to unset request canceled callback. %!STATUS!", status);
            goto Done;
        }
    }

    // Release power reference (if required).
    if (Dispatcher->PowerManaged)
    {
        NfcCxPowerFileRemoveReference(FdoContext->Power, fileContext, NfcCxPowerReferenceType_Proximity);
    }

    // Complete the request
    WdfRequestComplete(request, STATUS_SUCCESS);

Done:
    TRACE_FUNCTION_EXIT(LEVEL_VERBOSE);
    return;
}
Пример #22
0
/*
** Driver TODO: Complete the implementation of EvtIoDeviceControl for your specific device (if necessary)
**
** WDF calls this callback when a device instance is added to the driver.  Good drivers will do a lot of
** work here to set up everything necessary, such as adding callbacks for PNP power state changes.
** This function defines an IO queue for handling DeviceIoControl and file read requests, both of which are
** important to the POS magnetic stripe reader model.
**
** Note that this is not a complete device add implementation, as the PNP power callbacks are not handled.
** Additionally, driver writers may wish to set up additional queues to serialize device property requests
** (see Ioctl.cpp for more info).
*/
VOID EvtIoDeviceControl(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode)
{
    UNREFERENCED_PARAMETER(Queue);

    NTSTATUS status = STATUS_SUCCESS;
    ULONG_PTR information = 0;
    WDFDEVICE device = WdfIoQueueGetDevice(Queue);
    WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request);

    // These are the set of IOCTLs that your device should handle to work with the Windows.Devices.PointOfService APIs.
    switch (IoControlCode)
    {
    // The first three IOCTLs shouldn't require additional processing other than handing them off to PosCx
    case IOCTL_POINT_OF_SERVICE_CLAIM_DEVICE:
        status = PosCxClaimDevice(device, Request);
        break;

    case IOCTL_POINT_OF_SERVICE_RELEASE_DEVICE:
        status = PosCxReleaseDevice(device, fileObject);
        break;

    case IOCTL_POINT_OF_SERVICE_RETAIN_DEVICE:
        status = PosCxRetainDevice(device, Request);
        break;


    case IOCTL_POINT_OF_SERVICE_MSR_RETRIEVE_DEVICE_AUTHENTICATION:
        status = ProcessRetrieveDeviceAuthentication(device, fileObject, Request, &information);
        break;

    case IOCTL_POINT_OF_SERVICE_MSR_AUTHENTICATE_DEVICE:
        status = ProcessAuthenticateDevice(device, fileObject, Request);
        break;

    case IOCTL_POINT_OF_SERVICE_MSR_DEAUTHENTICATE_DEVICE:
        status = ProcessDeauthenticateDevice(device, fileObject, Request);
        break;

    case IOCTL_POINT_OF_SERVICE_MSR_UPDATE_KEY:
        status = ProcessUpdateKey(device, fileObject, Request);
        break;

    case IOCTL_POINT_OF_SERVICE_GET_PROPERTY:
        status = ProcessGetPropertyRequest(Request, InputBufferLength, &information);
        break;

    case IOCTL_POINT_OF_SERVICE_SET_PROPERTY:
        status = ProcessSetPropertyRequest(Request, InputBufferLength, &information);
        break;

    case IOCTL_POINT_OF_SERVICE_RETRIEVE_STATISTICS:
        status = ProcessRetrieveStatisticsRequest(Request, OutputBufferLength, &information);
        break;

    case IOCTL_POINT_OF_SERVICE_RESET_STATISTICS:
        status = ProcessResetStatisticsRequest(Request);
        break;

    case IOCTL_POINT_OF_SERVICE_UPDATE_STATISTICS:
        status = ProcessUpdateStatisticsRequest(Request);
        break;

    case IOCTL_POINT_OF_SERVICE_CHECK_HEALTH:
        status = ProcessCheckHealthRequest(Request, &information);
        break;

    // The Get Device Basics IOCTL is always the first IOCTL called by an application using the Windows.Devices.PointOfService APIs.
    // Use it to determine when to call PosCxMarkPosApp (see notes about apps marked this way in IoRead.cpp)
    case IOCTL_POINT_OF_SERVICE_GET_DEVICE_BASICS:
        status = ProcessGetDeviceBasicsRequest(Request, &information);
        (void)PosCxMarkPosApp(device, fileObject, TRUE);
        break;

    default:
        // Your device may support additional IOCTLs.  In this sample, we return failure for anything else.
        status = STATUS_NOT_SUPPORTED;
        break;
    }

    if (status != STATUS_PENDING)
    {
        WdfRequestCompleteWithInformation(Request, status, information);
    }
}
Пример #23
0
// handles operations that must be performed when an application requests access to a device.
VOID vJoy_EvtDeviceFileCreate(
  __in  WDFDEVICE Device,
  __in  WDFREQUEST Request,
  __in  WDFFILEOBJECT FileObject
)
{
		WDFFILEOBJECT FileObj;
		PCUNICODE_STRING pName;
		UNICODE_STRING TmpUstr;
		NTSTATUS status = STATUS_SUCCESS;
		int  id=0;
		WCHAR RefStr[100];
		PFILEOBJECT_EXTENSION pExtension=NULL;
		PDEVICE_EXTENSION    pDevContext = NULL;
		PRPDO_DEVICE_DATA	pPdoData=NULL;
		size_t len;
		DWORD_PTR ProcessId;

	    PAGED_CODE ();
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_EvtDeviceFileCreate\n");


		// Get file object then get its filename
		FileObj = WdfRequestGetFileObject(Request);
		if (!FileObj)
			goto going_out;
		pName = WdfFileObjectGetFileName(FileObj);
		if (!pName)
			goto going_out;

		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: File name=%wZ\n", pName);

		// Extract id from interface number
		status = RtlStringCchLengthW(VJOY_INTERFACE, 100, &len);
		if (!NT_SUCCESS(status))
			goto going_out;
		status = RtlStringCchCopyNW(RefStr, 100, pName->Buffer+len+1,4);	// Copy the numeric part of the string (000)
		if (!NT_SUCCESS(status))
			goto going_out;
		RtlInitUnicodeString(&TmpUstr, RefStr);								// Convert "000" to UNICODE_STRING
		status = RtlUnicodeStringToInteger(&TmpUstr, 10, &id);				// Convert "000" to integer (0)
		if (!NT_SUCCESS(status))
			goto going_out;

		if (id>0)
		{
			// Verify that this interface has a corresponding device
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: ID=%d\n", id);
			pPdoData = PdoGetData(Device);
			pDevContext = GetDeviceContext(pPdoData->hParentDevice);
			if (!pDevContext)
				goto going_out;
			if (!pDevContext->positions[id - 1])
				goto going_out;

			// Get the file object context space
			// Test that this interface is not in use
			// and store there the parent (Raw PDO) context
			pExtension = GetFileObjectContext(FileObject);
			if (!pExtension)
				goto going_out;
			pExtension->pParentRawDeviceContext = pPdoData;
			if (pPdoData->UsedInterfacesMask & (1 << (id - 1)))
			{
				WdfRequestComplete(Request, STATUS_ACCESS_DENIED);
				ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
				TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d Failed (Access Denied)\n", ProcessId);
				return;
			}

			///// This is a successful file creation - Now record the file details

			// vJoy Device ID
			else
				pPdoData->UsedInterfacesMask |= 1 << (id - 1);

			// Put id in file object context space 
			pExtension->id = id; // Update

			// Get the id of the calling process
			ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
			pExtension->CallingProcessId = (DWORD)(ProcessId & 0xFFFFFFFF);
			TraceEvents(TRACE_LEVEL_WARNING, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d\n", pExtension->CallingProcessId);

			// Put the file object in the FDO extension
			pDevContext->DeviceFileObject[id - 1] = FileObject;

			// Activate FFB Queues
			FfbActiveSet(TRUE, id, pDevContext);


			WdfRequestComplete(Request, status);
			return;

		} // if (id>0)

		// Case of General purpose and non device-specific Interface
		else // if (id<1)
		{
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate(2nd case): ID=%d\n", id);
#if 0
			pPdoData = PdoGetData(Device);
			pDevContext = GetDeviceContext(pPdoData->hParentDevice);
			if (!pDevContext)
				goto going_out;

			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate(2nd case): Completing Request\n");

#endif // 0
			WdfRequestComplete(Request, status);
			return;
		}; // if (id<1)

	going_out:
		ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d Failed (Invalid Handle)\n", ProcessId);
		WdfRequestComplete(Request, STATUS_INVALID_HANDLE);
}
Пример #24
0
VOID
BthEchoCliRemoteConnectCompletion(
    __in WDFREQUEST  Request,
    __in WDFIOTARGET  Target,
    __in PWDF_REQUEST_COMPLETION_PARAMS  Params,
    __in WDFCONTEXT  Context
    )

/*++
Description:

    Completion routine for Create request which we format as open
    channel BRB and send down the stack. We complete the Create request 
    in this routine.

    We receive open channel BRB as the context. This BRB
    is part of the request context and doesn't need to be freed
    explicitly.

    Connection is part of the context in the BRB.

Arguments:

    Request - Create request that we formatted with open channel BRB
    Target - Target to which we sent the request
    Params - Completion params
    Context - We receive BRB as the context          

Return Value:

    NTSTATUS Status code.
--*/

{
    NTSTATUS status;
    struct _BRB_L2CA_OPEN_CHANNEL *brb;    
    PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx;
    PBTHECHO_CONNECTION connection;
    
    DevCtx = GetClientDeviceContext(WdfIoTargetGetDevice(Target));

    status = Params->IoStatus.Status;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONNECT, 
        "Connection completion, status: %!STATUS!", status);        

    brb = (struct _BRB_L2CA_OPEN_CHANNEL *) Context;

    connection = (PBTHECHO_CONNECTION) brb->Hdr.ClientContext[0];

    //
    // In the client we don't check for ConnectionStateDisconnecting state 
    // because only file close generates disconnect which
    // cannot happen before create completes. And we complete Create
    // only after we process this completion.
    //

    if(NT_SUCCESS(status))
    {
        connection->OutMTU = brb->OutResults.Params.Mtu;
        connection->InMTU = brb->InResults.Params.Mtu;
        connection->ChannelHandle = brb->ChannelHandle;
        connection->RemoteAddress = brb->BtAddress;

        connection->ConnectionState = ConnectionStateConnected;

        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONNECT, 
            "Connection established to server"); 

        //
        // Call the function in device.c (BthEchoCliConnectionStateConnected)
        // for any post processing after connection has been established
        //
        status = BthEchoCliConnectionStateConnected(WdfRequestGetFileObject(Request), connection);
        if (!NT_SUCCESS(status))
        {
            //
            // If such post processing fails we disconnect
            //
            BthEchoConnectionObjectRemoteDisconnect(
                &(DevCtx->Header),
                connection
                );
        }            
    }
    else
    {
        connection->ConnectionState = ConnectionStateConnectFailed;
    }

    //
    // Complete the Create request
    //
    WdfRequestComplete(Request, status);

    return;    
}
Пример #25
0
static VOID UsbChief_ReadEndPoint(IN WDFQUEUE Queue, IN WDFREQUEST Request,
			   IN ULONG totalLength)
{
	PMDL                    newMdl=NULL, requestMdl = NULL;
	PURB                    urb = NULL;
	WDFMEMORY               urbMemory;
	ULONG                   stageLength = 0;
	NTSTATUS                status;
	ULONG_PTR               virtualAddress = 0;
	PREQUEST_CONTEXT        rwContext = NULL;
	PFILE_CONTEXT           fileContext = NULL;
	WDFUSBPIPE              pipe;
	WDF_USB_PIPE_INFORMATION   pipeInfo;
	WDF_OBJECT_ATTRIBUTES   objectAttribs;
	USBD_PIPE_HANDLE        usbdPipeHandle;
	PDEVICE_CONTEXT         deviceContext;

	UsbChief_DbgPrint(DEBUG_RW, ("UsbChief_DispatchReadWrite - begins\n"));

	deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
	fileContext = GetFileContext(WdfRequestGetFileObject(Request));
	pipe = fileContext->Pipe;

	WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
	WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

	rwContext = GetRequestContext(Request);

	status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
	if(!NT_SUCCESS(status)){
		UsbChief_DbgPrint(0, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status));
		goto Exit;
	}
	virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

	if (totalLength > MAX_TRANSFER_SIZE)
		stageLength = MAX_TRANSFER_SIZE;
	else
		stageLength = totalLength;

	newMdl = IoAllocateMdl((PVOID) virtualAddress, totalLength,
			       FALSE, FALSE, NULL);

	if (!newMdl) {
		UsbChief_DbgPrint(0, ("Failed to alloc mem for mdl\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress,
			  stageLength);

	WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
	objectAttribs.ParentObject = Request;

	status = WdfMemoryCreate(&objectAttribs,
				 NonPagedPool,
				 POOL_TAG,
				 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
				 &urbMemory,
				 (PVOID*) &urb);

	if (!NT_SUCCESS(status)) {
		UsbChief_DbgPrint(0, ("Failed to alloc mem for urb\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);

	UsbBuildInterruptOrBulkTransferRequest(urb,
					       sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
					       usbdPipeHandle,
					       NULL,
					       newMdl,
					       stageLength,
					       USBD_TRANSFER_DIRECTION_IN |
					       USBD_SHORT_TRANSFER_OK,
					       NULL);

	status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL  );
	if (!NT_SUCCESS(status)) {
		UsbChief_DbgPrint(0, ("Failed to format requset for urb\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}
	WdfRequestSetCompletionRoutine(Request, UsbChief_ReadCompletion, NULL);

	rwContext->UrbMemory       = urbMemory;
	rwContext->Mdl             = newMdl;
	rwContext->Length          = totalLength - stageLength;
	rwContext->Numxfer         = 0;
	rwContext->VirtualAddress  = virtualAddress + stageLength;

	if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
		status = WdfRequestGetStatus(Request);
		ASSERT(!NT_SUCCESS(status));
	}

Exit:
	if (!NT_SUCCESS(status)) {
		WdfRequestCompleteWithInformation(Request, status, 0);

		if (newMdl != NULL) {
			IoFreeMdl(newMdl);
		}
	}
}