Beispiel #1
1
NTSTATUS PciDtfDeviceGetInfo(IN WDFDEVICE Device, IN WDFREQUEST Request)
{
	PCIDTF_DEV_INFO *ReqData;
	ULONG Value, Length;
	NTSTATUS Status = STATUS_SUCCESS;

	__try {
		Status = WdfRequestRetrieveOutputBuffer(Request,
							sizeof(PCIDTF_DEV_INFO),
							(PVOID *) & ReqData,
							NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status);
			__leave;
		}
		Status = WdfDeviceQueryProperty(Device,
						DevicePropertyBusNumber,
						sizeof(Value), &Value, &Length);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR
			    ("WdfDeviceQueryProperty(DevicePropertyBusNumber)",
			     Status);
			__leave;
		}
		ReqData->bus = (UINT8) Value;
		Status = WdfDeviceQueryProperty(Device,
						DevicePropertyAddress,
						sizeof(Value), &Value, &Length);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR
			    ("WdfDeviceQueryProperty(DevicePropertyAddress)",
			     Status);
			__leave;
		}
		ReqData->devfn = (UINT8) Value;
		ReqData->reg_count = (int)
		    WdfCollectionGetCount(GetDeviceData(Device)->RegSpaces);
		TRACE_MSG(TRACE_LEVEL_VERBOSE, TRACE_FLAG_QUEUE,
			  "bus=0x%X, devfn=0x%X, reg_count=%d\n", ReqData->bus,
			  ReqData->devfn, ReqData->reg_count);
		WdfRequestSetInformation(Request, sizeof(PCIDTF_DEV_INFO));
	}
	__finally {
		WdfRequestComplete(Request, Status);
	}
	return Status;
}
Beispiel #2
0
//
// Internal Function: UartCtlGetChars
//
VOID
UartCtlGetChars(
    _In_ WDFDEVICE Device, 
    _In_ WDFREQUEST Request,
    _In_ size_t OutputBufferLength,
    _In_ size_t InputBufferLength
    )
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device);
    PSERIAL_CHARS pSpecialChars = NULL;

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    FuncEntry(TRACE_FLAG_CONTROL);

    status = WdfRequestRetrieveOutputBuffer(Request, 
                    sizeof(SERIAL_CHARS), 
                    (PVOID*)(& pSpecialChars), 
                    NULL);

    if (!NT_SUCCESS(status))
    {
        TraceMessage(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_CONTROL,
            "Failed to retrieve output buffer for WDFREQUEST %p - "
            "%!STATUS!",
            Request,
            status);
    }

    if (NT_SUCCESS(status))
    {
        *pSpecialChars = pDevExt->SpecialChars;

        WdfRequestSetInformation(Request, sizeof(SERIAL_CHARS));
    }

    TraceMessage(TRACE_LEVEL_INFORMATION,
                    TRACE_FLAG_CONTROL,
                    "WdfRequestComplete( %!HANDLE! => %!STATUS! )",
                    Request,
                    status);
    WdfRequestComplete(Request, status);

    FuncExit(TRACE_FLAG_CONTROL);
}
VOID PVPanicEvtQueueDeviceControl(IN WDFQUEUE Queue,
                                  IN WDFREQUEST Request,
                                  IN size_t OutputBufferLength,
                                  IN size_t InputBufferLength,
                                  IN ULONG IoControlCode)
{
    NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
    ULONG    length = 0;
    PVOID    buffer;
    size_t   buffer_length;

    PAGED_CODE();

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

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> %!FUNC!");

    switch (IoControlCode)
    {
    case IOCTL_GET_CRASH_DUMP_HEADER:
    {
        // Return the full result of KeInitializeCrashDumpHeader.
        status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &buffer_length);
        if (!NT_SUCCESS(status))
        {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                "WdfRequestRetrieveInputBuffer failed: %!STATUS!", status);
            break;
        }

        status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL,
                                             0, // flags, must be 0
                                             buffer,
                                             (ULONG)buffer_length,
                                             &length);
        if (status == STATUS_INVALID_PARAMETER_4)
        {
            status = STATUS_BUFFER_TOO_SMALL;
        }
        break;
    }
    }

    WdfRequestCompleteWithInformation(Request, status, NT_SUCCESS(status) ? length : 0);
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %!FUNC!");
}
Beispiel #4
0
/*
** Driver TODO:
**
** Implement this function to handle the initial handshake IOCTL for Windows.Devices.PointOfService API <-> Driver communication.
** This sample will likely work for most cases.
*/
NTSTATUS ProcessGetDeviceBasicsRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information)
{
    if (Information == nullptr || Request == nullptr)
    {
        return STATUS_INVALID_PARAMETER;
    }

    UINT32* runtimeVersion;
    PosDeviceBasicsType* outputData;

    NTSTATUS status = WdfRequestRetrieveInputBuffer(
        Request,
        sizeof(UINT32),
        (PVOID*)&runtimeVersion,
        nullptr);

    if (!NT_SUCCESS(status))
    {
        return status;
    }

    status = WdfRequestRetrieveOutputBuffer(
        Request,
        sizeof(PosDeviceBasicsType),
        (PVOID*)&outputData,
        nullptr);

    if (!NT_SUCCESS(status))
    {
        return status;
    }

    // Tell the runtime what version of the POS IOCTL interface this driver supports so that
    // it won't send IOCTLs that the driver doesn't support.
    outputData->Version = POS_DRIVER_VERSION;
    // This is a magnetic stripe reader driver
    outputData->DeviceType = PosDeviceType::PosDeviceType_MagneticStripeReader;
    // This value will be used to set the initial ReadFile buffer size.  A small size that is
    // likely to cover most of the data events is suggested.  The runtime will grow the ReadFile
    // buffer size as needed.
    outputData->RecommendedBufferSize = 128;

    *Information = sizeof(PosDeviceBasicsType);

    return STATUS_SUCCESS;
}
// 中断Pipe回调函数。这样一旦设备产生了中断信息,驱动就能够读取到。
//
VOID InterruptRead(WDFUSBPIPE Pipe, WDFMEMORY Buffer, size_t NumBytesTransferred, WDFCONTEXT Context)
{
	NTSTATUS status;
	size_t size = 0;
	PDEVICE_CONTEXT pContext = (PDEVICE_CONTEXT)Context;
	WDFREQUEST Request = NULL;
	CHAR *pchBuf = NULL;

	KDBG(DPFLTR_INFO_LEVEL, "[InterruptRead]");
	UNREFERENCED_PARAMETER(Pipe);

	// Read数据缓冲区。注意到,缓冲区长度总是管道最大包长度的倍数。
	// 我们这里只用缓冲区的第一个有效字节。
	pchBuf = (CHAR*)WdfMemoryGetBuffer(Buffer, &size);
	if(pchBuf == NULL || size == 0)
		return;

	// 第一个字节为确认字节,一定是0xD4
	//if(pchBuf[0] != 0xD4)return;

	// 从队列中提取一个未完成请求
	status = WdfIoQueueRetrieveNextRequest(pContext->InterruptManualQueue, &Request);

	if(NT_SUCCESS(status))
	{
		CHAR* pOutputBuffer = NULL;
		status = WdfRequestRetrieveOutputBuffer(Request, 1, &pOutputBuffer, NULL);

		if(NT_SUCCESS(status))
		{
			// 把结果返回给应用程序
			pOutputBuffer[0] = pchBuf[1];
			WdfRequestCompleteWithInformation(Request, status, 1);
		}
		else
		{
			// 返回错误
			WdfRequestComplete(Request, status);
		}

		KDBG(DPFLTR_INFO_LEVEL, "Get and finish an interrupt read request.");
	}else{
		// 队列空,将放弃从设备获取的数据。
		KDBG(DPFLTR_INFO_LEVEL, "Manual interrupt queue is empty!!!");
	}
}
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();
}
Beispiel #7
0
///////////////////////////////////////////////////////////////////////////////
// SmplFilterCompletionRoutineRead
///////////////////////////////////////////////////////////////////////////////
void SmplFilterCompletionRoutineRead(
  __in  WDFREQUEST Request,
  __in  WDFIOTARGET Target,
  __in  PWDF_REQUEST_COMPLETION_PARAMS Params,
  __in  WDFCONTEXT Context
)
{
    size_t CountByte;
    PKEYBOARD_INPUT_DATA pKeyboardInputData;
    NTSTATUS Status;

    DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterCompletionRoutineRead\n");

    Status = WdfRequestRetrieveOutputBuffer(Request,
                                            sizeof(KEYBOARD_INPUT_DATA),
                                            &pKeyboardInputData,
                                            &CountByte);
    if (NT_SUCCESS (Status)) 
    {
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "Size of data: %d.\n", CountByte);
        if (CountByte < sizeof(KEYBOARD_INPUT_DATA))
        {
            DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "Buffer too small.\n");
        }
        else
        {
            DbgPrintEx( DPFLTR_IHVDRIVER_ID, 
                        1234, 
                        "Unit: %x  MakCode: %x, Flags: %x  ExtraInformation %x.\n", 
                        pKeyboardInputData->UnitId, 
                        pKeyboardInputData->MakeCode, 
                        pKeyboardInputData->Flags, 
                        pKeyboardInputData->ExtraInformation);
        }
    }
    else
    {
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "WdfRequestRetrieveOutputBuffer() failed.\n");
    }

    WdfRequestComplete(Request, WdfRequestGetStatus(Request));

} // end SmplFilterCompletionRoutineRead
Beispiel #8
0
// 读回调
VOID EvtIoRead( IN WDFQUEUE Queue, 
			   IN WDFREQUEST Request, 
			   IN size_t Length )
{
	NTSTATUS status;
	PVOID outBuf; // 输出缓冲区
	size_t bufLength; // 输出缓冲区大小
	ULONG_PTR bytesRead = 0; // 实际读取的字节数

	// 获取输出缓冲区地址
	status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufLength);
	if( !NT_SUCCESS(status) )
	{
		KdPrint(("[EvtIoRead] WdfRequestRetrieveOutputBuffer failed!"));

		WdfRequestComplete(Request, status);
		return ;
	}

	// 实际读取的字节数与文件指针有关
	bytesRead = ((IO_BUFFER_SIZE - gFilePointer) < Length ) ? 
		IO_BUFFER_SIZE - gFilePointer : Length;

	// 检查参数
	if( bufLength < bytesRead )
	{
		WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
		return;
	}

	// 文件指针已经到末尾
	if( 0 == bytesRead )
	{
		WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 0);
		return;
	}

	// 拷贝内容到输出缓冲区
	RtlCopyMemory(outBuf, gFileBuffer+gFilePointer, bytesRead);

	WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, bytesRead);
}
Beispiel #9
0
NTSTATUS PciDtfDeviceGetDma(IN WDFDEVICE Device, IN WDFREQUEST Request)
{
	PDEVICE_DATA DeviceData = GetDeviceData(Device);
	PCIDTF_DMA_INFO *ReqData;
	WDFCOMMONBUFFER CommonBuffer;
	NTSTATUS Status = STATUS_SUCCESS;

	__try {
		Status = WdfRequestRetrieveInputBuffer(Request,
						       sizeof(PCIDTF_DMA_INFO),
						       (PVOID *) & ReqData,
						       NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveInputBuffer", Status);
			__leave;
		}
		Status = WdfRequestRetrieveOutputBuffer(Request,
							sizeof(PCIDTF_DMA_INFO),
							(PVOID *) & ReqData,
							NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status);
			__leave;
		}
		CommonBuffer =
		    PciDtfCommonBufferFind(DeviceData, ReqData->id, FALSE);
		if (CommonBuffer == NULL) {
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}
		ReqData->addr =
		    WdfCommonBufferGetAlignedLogicalAddress
		    (CommonBuffer).QuadPart;
		ReqData->len = (int)WdfCommonBufferGetLength(CommonBuffer);
		WdfRequestSetInformation(Request, sizeof(PCIDTF_DMA_INFO));
	}
	__finally {
		WdfRequestComplete(Request, Status);
	}
	return Status;
}
Beispiel #10
0
VOID VirtRngEvtIoRead(IN WDFQUEUE Queue,
                      IN WDFREQUEST Request,
                      IN size_t Length)
{
    PDEVICE_CONTEXT context = GetDeviceContext(WdfIoQueueGetDevice(Queue));
    NTSTATUS status;
    PVOID buffer;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ,
        "--> %!FUNC! Queue: %p Request: %p Length: %d",
        Queue, Request, (ULONG)Length);

    status = WdfRequestRetrieveOutputBuffer(Request, Length, &buffer, NULL);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
            "WdfRequestRetrieveOutputBuffer failed: %!STATUS!", status);
        WdfRequestComplete(Request, status);
        return;
    }

    status = WdfRequestMarkCancelableEx(Request, VirtRngEvtRequestCancel);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
            "WdfRequestMarkCancelableEx failed: %!STATUS!", status);
        WdfRequestComplete(Request, status);
        return;
    }

    status = VirtQueueAddBuffer(context, Request, Length);
    if (!NT_SUCCESS(status))
    {
        if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED)
        {
            WdfRequestComplete(Request, status);
        }
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- %!FUNC!");
}
Beispiel #11
0
//
// Assumes trace fifo already locked
//
NTSTATUS 
__BusDogFufillRequestWithTraces(
    IN WDFREQUEST Request,
    OUT size_t* bytesWritten
    )
{
    PVOID    outputBuffer = NULL;
    size_t   realLength;
    NTSTATUS status = STATUS_SUCCESS;    

    *bytesWritten = 0;

    //
    // Get the output buffer...
    //
    status = WdfRequestRetrieveOutputBuffer(Request,
            sizeof(BUSDOG_FILTER_TRACE),
            &outputBuffer,
            &realLength);

    if (NT_SUCCESS(status)) 
    {
        //
        // Fill buffer with traces
        //

        status = __BusDogFillBufferWithTraces(outputBuffer, 
                                              realLength, 
                                              bytesWritten);
    }
    else
    {
        BusDogPrint(BUSDOG_DEBUG_ERROR, "WdfRequestRetrieveOutputBuffer failed - 0x%x\n",
                status);
    }

    return status;
}
Beispiel #12
0
NTSTATUS PciDtfDeviceAllocDma(IN WDFDEVICE Device, IN WDFREQUEST Request)
{
	PDEVICE_DATA DeviceData = GetDeviceData(Device);
	PCIDTF_DMA_INFO *ReqData;
	WDF_OBJECT_ATTRIBUTES ObjectAttributes;
	WDFCOMMONBUFFER CommonBuffer = NULL;
	PCOMMON_BUFFER_DATA CommonBufferData;
	NTSTATUS Status = STATUS_SUCCESS;

	__try {
		Status = WdfRequestRetrieveInputBuffer(Request,
						       sizeof(PCIDTF_DMA_INFO),
						       (PVOID *) & ReqData,
						       NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveInputBuffer", Status);
			__leave;
		}
		Status = WdfRequestRetrieveOutputBuffer(Request,
							sizeof(PCIDTF_DMA_INFO),
							(PVOID *) & ReqData,
							NULL);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status);
			__leave;
		}
		WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ObjectAttributes,
							COMMON_BUFFER_DATA);
		Status = WdfCommonBufferCreate(DeviceData->DmaEnabler,
					       ReqData->len, &ObjectAttributes,
					       &CommonBuffer);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfCommonBufferCreate", Status);
			__leave;
		}
		CommonBufferData = GetCommonBufferData(CommonBuffer);
		CommonBufferData->ID = PciDtfCommonBufferAssignId(DeviceData);
		Status = WdfCollectionAdd(DeviceData->CommonBuffers,
					  CommonBuffer);
		if (!NT_SUCCESS(Status)) {
			TRACE_ERR("WdfCollectionAdd", Status);
			__leave;
		}
		ReqData->id = CommonBufferData->ID;
		ReqData->addr =
		    WdfCommonBufferGetAlignedLogicalAddress
		    (CommonBuffer).QuadPart;
		WdfRequestSetInformation(Request, sizeof(PCIDTF_DMA_INFO));

		TRACE_MSG(TRACE_LEVEL_VERBOSE, TRACE_FLAG_QUEUE,
			  "va 0x%p, pa 0x%llX, len 0x%X\n",
			  WdfCommonBufferGetAlignedVirtualAddress(CommonBuffer),
			  WdfCommonBufferGetAlignedLogicalAddress
			  (CommonBuffer).QuadPart,
			  WdfCommonBufferGetLength(CommonBuffer));
	}
	__finally {
		if (!NT_SUCCESS(Status) && CommonBuffer != NULL) {
			WdfObjectDelete(CommonBuffer);
		}
		WdfRequestComplete(Request, Status);
	}
	return Status;
}
Beispiel #13
0
/*
** Driver TODO: Add code to ProcessCheckHealthRequest to handle different health check cases.  The result should be a localized string that is returned to the user in the output buffer of the IOCTL.
**
** Implement this function to handle health check requests.
*/
NTSTATUS ProcessCheckHealthRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information)
{
    if (Information == nullptr || Request == nullptr)
    {
        return STATUS_INVALID_PARAMETER;
    }

    DriverUnifiedPosHealthCheckLevel* level;

    NTSTATUS status = WdfRequestRetrieveInputBuffer(
        Request,
        sizeof(DriverUnifiedPosHealthCheckLevel),
        (PVOID*)&level,
        nullptr);

    if (!NT_SUCCESS(status))
    {
        return status;
    }

    PosStringType* outputBuffer;
    size_t outputBufferLength;
    status = WdfRequestRetrieveOutputBuffer(
        Request,
        sizeof(PosStringType),
        (void**)(&outputBuffer),
        &outputBufferLength
        );

    if (!NT_SUCCESS(status))
    {
        return status;
    }

    switch (*level)
    {
    case DriverUnifiedPosHealthCheckLevel::POSInternal:
    case DriverUnifiedPosHealthCheckLevel::External:
    case DriverUnifiedPosHealthCheckLevel::Interactive:
        {
            // Handle the specific health check level, depending on the applicability to your device.
            // Return the result as a string that the user can use to determine whether the device is
            // operational or needs attention.
            LPCWSTR result = L"OK";
            size_t lengthInBytes = wcslen(result) * sizeof(WCHAR);
            status = RtlSizeTToUInt32(lengthInBytes, &(outputBuffer->DataLengthInBytes));
            if (NT_SUCCESS(status))
            {
                *Information = sizeof(PosStringType);
                if (outputBufferLength >= sizeof(PosStringType)+outputBuffer->DataLengthInBytes)
                {
                    void* outputStringStart = (void*)(outputBuffer + 1);
                    memcpy(outputStringStart, result, outputBuffer->DataLengthInBytes);
                    *Information += outputBuffer->DataLengthInBytes;
                }
                else
                {
                    status = STATUS_BUFFER_OVERFLOW;
                }
            }
        }
        break;
    default:
        return STATUS_INVALID_PARAMETER;
    }

    return STATUS_SUCCESS;
}
Beispiel #14
0
/*
** Driver TODO: Replace the data in the ProcessRetrieveStatisticsRequest with your own statistics data
**
** Implement this function to handle retrieve statistics requests.
*/
NTSTATUS ProcessRetrieveStatisticsRequest(_In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _Inout_ ULONG_PTR* Information)
{
    if (Information == nullptr || Request == nullptr)
    {
        return STATUS_INVALID_PARAMETER;
    }

    struct
    {
        PosStatisticsHeader Header;
        PosValueStatisticsEntry Entries[1];
    } StatisticsData;

    // Initialize statics data so header data are identical for the same requested
    RtlZeroMemory(&StatisticsData, sizeof(StatisticsData));
    
    StatisticsData.Header.DataLength = sizeof(StatisticsData);
    wcscpy_s(StatisticsData.Header.DeviceInformation.DeviceCategory, L"MSR");
    wcscpy_s(StatisticsData.Header.DeviceInformation.FirmwareRevision, L"<eg, 1.1>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.InstallationDate, L"<installation date>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.Interface, L"<eg, USB>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.ManufactureDate, L"<eg, 2015/03/17>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.ManufacturerName, L"<eg, Conteso>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.MechanicalRevision, L"<eg, 2.0a>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.ModelName, L"<eg, MSR Model M>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.SerialNumber, L"<eg, 12345>");
    wcscpy_s(StatisticsData.Header.DeviceInformation.UnifiedPOSVersion, L"1.14");
    StatisticsData.Header.EntryCount = 1;
    wcscpy_s(StatisticsData.Entries[0].EntryName, L"<device specific statistics value>");
    StatisticsData.Entries[0].Value = (LONG)1;

    // This IOCTL is called twice by the Windows.Devices.PointOfService APIs
    // The first time will just retrieve the header to determine how big the buffer needs to be.
    PVOID outputBuffer;
    NTSTATUS status = WdfRequestRetrieveOutputBuffer(
        Request,
        sizeof(PosStatisticsHeader),
        &outputBuffer,
        nullptr
        );

    if (!NT_SUCCESS(status))
    {
        *Information = sizeof(StatisticsData);
        return status;
    }

    if (OutputBufferLength == sizeof(PosStatisticsHeader))
    {
        memcpy(outputBuffer, &(StatisticsData.Header), sizeof(PosStatisticsHeader));
        *Information = sizeof(PosStatisticsHeader);
    }
    else if (OutputBufferLength < sizeof(StatisticsData))
    {
        *Information = sizeof(StatisticsData);
        status = STATUS_BUFFER_TOO_SMALL;
    }
    else
    {
        memcpy(outputBuffer, &StatisticsData, sizeof(StatisticsData));
        *Information = sizeof(StatisticsData);
    }

    return status;
}
VOID
VIOSerialPortRead(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t     Length
    )
{
    PRAWPDO_VIOSERIAL_PORT  pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue));
    PVIOSERIAL_PORT         pport = pdoData->port;
    size_t             length;
    NTSTATUS           status;
    PVOID              systemBuffer;

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

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

	WdfSpinLockAcquire(pport->InBufLock);

	if (!VIOSerialPortHasDataLocked(pport))
	{
		if (!pport->HostConnected)
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			length = 0;
		}
		else
		{
			ASSERT (pport->PendingReadRequest == NULL);
			status = WdfRequestMarkCancelableEx(Request,
				VIOSerialPortReadRequestCancel);
			if (!NT_SUCCESS(status))
			{
				length = 0;
			}
			else
			{
				pport->PendingReadRequest = Request;
				Request = NULL;
			}
		}
    }
    else
    {
        length = (ULONG)VIOSerialFillReadBufLocked(pport, systemBuffer, length);
        if (!length)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    WdfSpinLockRelease(pport->InBufLock);

    if (Request != NULL)
    {
        // we are completing the request right here, either because of
        // an error or because data was available in the input buffer
        WdfRequestCompleteWithInformation(Request, status, (ULONG_PTR)length);
    }

	TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,"<-- %s\n", __FUNCTION__);
}
Beispiel #16
0
// IO控制
VOID EvtIoDeviceControl( IN WDFQUEUE Queue, 
						IN WDFREQUEST Request, 
						IN size_t OutputBufferLength, 
						IN size_t InputBufferLength, 
						IN ULONG IoControlCode )
{
	NTSTATUS status;
	PVOID inBuf; // 输入缓冲区地址
	PVOID outBuf; // 输出缓冲区地址
	CHAR offset; // 指针移动量

	switch( IoControlCode )
	{
		// 移动文件指针
	case IOSample_IOCTL_FILE_SEEK:

		// 检查输入参数
		if( 0 == InputBufferLength || 0 == OutputBufferLength )
		{
			WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
			return;
		}

		// 获取输入缓冲区地址
		status = WdfRequestRetrieveInputBuffer(Request, 1, &inBuf, NULL);
		if( !NT_SUCCESS(status) )
		{
			KdPrint(("[EvtIoDeviceControl] WdfRequestRetrieveInputBuffer failed!"));

			WdfRequestComplete(Request, status);
			return ;
		}

		// 获取输出缓冲区地址
		status = WdfRequestRetrieveOutputBuffer(Request, 1, &outBuf, NULL);
		if( !NT_SUCCESS(status) )
		{
			KdPrint(("[EvtIoDeviceControl] WdfRequestRetrieveOutputBuffer failed!"));

			WdfRequestComplete(Request, status);
			return ;
		}

		offset = *(CHAR*)inBuf;

		// 移动文件指针
		if( gFilePointer + offset < 0 )
			gFilePointer = 0;
		else if( gFilePointer + offset > IO_BUFFER_SIZE )
			gFilePointer = IO_BUFFER_SIZE;
		else
			gFilePointer = gFilePointer + offset;

		// 新的文件指针位置
		*(CHAR*)outBuf = gFilePointer;

		WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 1);

		break;

	default:
		WdfRequestCompleteWithInformation(Request, STATUS_INVALID_DEVICE_REQUEST, 0);
		break;
	}
}
Beispiel #17
0
VOID
HidFx2CompleteReadReport(
    WDFDEVICE Device
    )
/*++

Routine Description

    This method handles the completion of the pended request for the
    IOCTL_HID_READ_REPORT

Arguments:

    Device - Handle to a framework device.

Return Value:

    None.

--*/
{
    NTSTATUS             status = STATUS_SUCCESS;
    WDFREQUEST           request;
    PDEVICE_EXTENSION    pDevContext = NULL;
    size_t               bytesReturned = 0;
#ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR
    UCHAR                toggledSwitch = 0;
#endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR
    ULONG                bytesToCopy = 0;
    PHIDFX2_INPUT_REPORT inputReport = NULL;

    pDevContext = GetDeviceContext(Device);

    //
    // Check if there are any pending requests in the Interrupt Message Queue.
    // If a request is found then complete the pending request.
    //
    status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request);

    if (NT_SUCCESS(status)) {
        //
        // IOCTL_HID_READ_REPORT is METHOD_NEITHER so WdfRequestRetrieveOutputBuffer
        // will correctly retrieve buffer from Irp->UserBuffer. Remember that
        // HIDCLASS provides the buffer in the Irp->UserBuffer field
        // irrespective of the ioctl buffer type. However, framework is very
        // strict about type checking. You cannot get Irp->UserBuffer by using
        // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER
        // internal ioctl.
        //
        bytesToCopy = sizeof(HIDFX2_INPUT_REPORT);
        status = WdfRequestRetrieveOutputBuffer(request,
                                                bytesToCopy,
                                                &inputReport,
                                                &bytesReturned);// BufferLength

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "WdfRequestRetrieveOutputBuffer failed with status: 0x%x\n", status);
        } else {

#ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR
            //
            // Map switch pack state. The lower 7 bits of switch pack
            // state are mapped to usages in consumer control collection
            // while the highest one bit is mapped to sleep usage in system
            // control collection
            //
            toggledSwitch = pDevContext->LatestToggledSwitch;

			if (toggledSwitch & CONSUMER_CONTROL_BUTTONS_BIT_MASK) {
                //
                //these are consumer control buttons
                //
                TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
                    "Consumer control SwitchState: 0x%x\n", toggledSwitch);

                inputReport->ReportId = CONSUMER_CONTROL_REPORT_ID;
                inputReport->SwitchStateAsByte = toggledSwitch;
                bytesReturned = bytesToCopy;
            }
            else if (toggledSwitch & SYSTEM_CONTROL_BUTTONS_BIT_MASK) {
                //
                // these are system control buttons
                //
                TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
                    "System Control SwitchState: 0x%x\n", toggledSwitch);

                inputReport->ReportId = SYSTEM_CONTROL_REPORT_ID;
                inputReport->SwitchStateAsByte = toggledSwitch;
                bytesReturned = bytesToCopy;
            }
            else {
                //
                // We can't be here since we already rejected the switch
                // state with no swicthes turned on
                //
                ASSERT(FALSE);
            }
#else
            //
            // Using vendor collection reports instead of HID collections that integrate
            // into consumer and system control
            //
            TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
                "Vendor SwitchState: 0x%x\n", pDevContext->CurrentSwitchState);

            inputReport->ReportId = DIP_SWITCHES_REPORT_ID;
            inputReport->SwitchStateAsByte = pDevContext->CurrentSwitchState;
            bytesReturned = bytesToCopy;

#endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR

        }

        WdfRequestCompleteWithInformation(request, status, bytesReturned);

    } else if (status != STATUS_NO_MORE_ENTRIES) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
            "WdfIoQueueRetrieveNextRequest status %08x\n", status);
    }

    return;
}
Beispiel #18
0
VOID
FileEvtIoRead(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN size_t            Length
    )
/*++

Routine Description:

    This event is called when the framework receives IRP_MJ_READ requests.
    We will just read the file.

Arguments:

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

    Length  - number of bytes to be read.
                   Queue is by default configured to fail zero length read & write requests.

Return Value:

  None.

--*/
{
    NTSTATUS                   status = STATUS_SUCCESS;
    PVOID                       outBuf;
    IO_STATUS_BLOCK             ioStatus;
    PCONTROL_DEVICE_EXTENSION   devExt;
    FILE_POSITION_INFORMATION   position;
    ULONG_PTR                   bytesRead = 0;
    size_t  bufLength;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_RW, "FileEvtIoRead: Request: 0x%p, Queue: 0x%p\n",
                     Request, Queue);

    PAGED_CODE ();

    //
    // Get the request buffer. Since the device is set to do buffered
    // I/O, this function will retrieve Irp->AssociatedIrp.SystemBuffer.
    //
    status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufLength);
    if(!NT_SUCCESS(status)) {
        WdfRequestComplete(Request, status);
        return;

    }

    devExt = ControlGetData(WdfIoQueueGetDevice(Queue));

    if(devExt->FileHandle) {

        //
        // Set the file position to the beginning of the file.
        //
        position.CurrentByteOffset.QuadPart = 0;
        status = ZwSetInformationFile(devExt->FileHandle,
                             &ioStatus,
                             &position,
                             sizeof(FILE_POSITION_INFORMATION),
                             FilePositionInformation);
        if (NT_SUCCESS(status)) {

            status = ZwReadFile (devExt->FileHandle,
                                NULL,//   Event,
                                NULL,// PIO_APC_ROUTINE  ApcRoutine
                                NULL,// PVOID  ApcContext
                                &ioStatus,
                                outBuf,
                                (ULONG)Length,
                                0, // ByteOffset
                                NULL // Key
                                );

            if (!NT_SUCCESS(status)) {

                TraceEvents(TRACE_LEVEL_ERROR, DBG_RW,
                               "ZwReadFile failed with status 0x%x",
                               status);
            }

            status = ioStatus.Status;
            bytesRead = ioStatus.Information;
        }
    }

    WdfRequestCompleteWithInformation(Request, status, bytesRead);

}
Beispiel #19
0
VOID
SingleCompEvtIoDeviceControl(
    _In_ WDFQUEUE Queue,
    _In_ WDFREQUEST Request,
    _In_ size_t OutputBufferLength,
    _In_ size_t InputBufferLength,
    _In_ ULONG IoControlCode
    )
/*++
Routine Description:

    Callback invoked by WDFQUEUE for a Device Io Control request.

Arguments:

    Queue - Device I/O control queue
              
    Request - Device I/O control request

    OutputBufferLength - Output buffer length for the I/O control

    InputBufferLength - Input buffer length for the I/O control

    IoControlCode - I/O control code
                
--*/
{
    NTSTATUS status;
    PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer = NULL;
    WDFDEVICE device = NULL;
    ULONG componentData;
    ULONG_PTR information = 0;
    FDO_DATA *fdoContext = NULL;
    
    //
    // When we complete the request, make sure we don't get the I/O manager to 
    // copy any more data to the client address space than what we write to the
    // output buffer. The only data that we write to the output buffer is the 
    // component data and the C_ASSERT below ensures that the output buffer does
    // not have room to contain anything other than that.
    //
    C_ASSERT(sizeof(componentData) == sizeof(*outputBuffer));

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    //
    // This is a power-managed queue. So our queue stop/start logic should have 
    // ensured that we are in the active condition when a request is dispatched
    // from this queue.
    //
    device = WdfIoQueueGetDevice(Queue);
    fdoContext = FdoGetContext(device);
    if (FALSE == fdoContext->IsActive) {
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - IOCTL %d was dispatched from WDFQUEUE %p when the "
              "component was not in an active condition.",
              IOCTL_POWERFX_READ_COMPONENT,
              Queue);
        WdfVerifierDbgBreakPoint();
    }
    
    //
    // Validate Ioctl code
    //
    if (IOCTL_POWERFX_READ_COMPONENT != IoControlCode) {
        status = STATUS_NOT_SUPPORTED;
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! -Unsupported IoControlCode. Expected: %d. Actual: %d."
              " %!status!.", 
              IOCTL_POWERFX_READ_COMPONENT,
              IoControlCode,
              status);
        goto exit;
    }
    
    //
    // Get the output buffer
    //
    status = WdfRequestRetrieveOutputBuffer(Request,
                                            sizeof(*outputBuffer),
                                            (PVOID*) &outputBuffer,
                                            NULL // Length
                                            );
    if (FALSE == NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - WdfRequestRetrieveOutputBuffer failed with %!status!.",
              status);
        goto exit;
    }
    
    //
    // Read the data from the component
    //
    componentData = HwSimReadComponent(device);
    outputBuffer->ComponentData = componentData;
    information = sizeof(*outputBuffer);
    
    status = STATUS_SUCCESS;
    
exit:
    //
    // Complete the request
    //
    WdfRequestCompleteWithInformation(Request, status, information);
    return;
}
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;
}
Beispiel #21
0
/*++
PCIEDeviceIoCtrl handles IRP from user-mode application and upper driver.

Note: IRQL: <= DISPATCH_LEVEL unless device's or driver's 
      WDF_OBJECT_ATTRIBUTES struct is set to WdfExecutionLevelPassive.
--*/
VOID PCIEDeviceIoCtrl(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
{
    NTSTATUS                Status = STATUS_SUCCESS;
    HRESULT                 hRes   = S_OK;

    PDEVICE_EXTENSION       pDevExt;
    
    PVOID                   pInputBuffer;
    PVOID                   pOutputBuffer;
    size_t                  InputBufferSize;
    size_t                  OutputBufferSize;
    
    ULONG                   RetInfo = 0;    
    //KIRQL                   Irql = KeGetCurrentIrql();
    //
    // Get the device extension.
    //
    pDevExt = PCIEGetDeviceContext(WdfIoQueueGetDevice( Queue ));

    if (InputBufferLength > 0)
    {
        Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &pInputBuffer, &InputBufferSize);
        if( !NT_SUCCESS(Status) )
        {
            WdfRequestComplete(Request, Status);
            return;
        }
    }
    else
    {
        pInputBuffer = NULL;
        InputBufferSize = 0;
    }

    if (OutputBufferLength > 0)
    {
        Status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &pOutputBuffer, &OutputBufferSize);
        if( !NT_SUCCESS(Status) )
        {
            WdfRequestComplete(Request, Status);
            return;
        }
    }
    else
    {
        pOutputBuffer = NULL;
        OutputBufferSize = 0;
    }

    //
    // Handle this request's specific code.
    //
    switch (IoControlCode)
    {
    case __IOCTL_REQUEST_RADIOS:
        hRes = PCIEHandleRadiosReq(
                    pDevExt, 
                    pInputBuffer, 
                    InputBufferSize, 
                    pOutputBuffer, 
                    OutputBufferSize);
        RetInfo = sizeof(LIST_ENTRY);
        break;
    case IOCTL_DUMP_RADIO_RX:
        {

            ULONG radioIndex = (*(ULONG*)pInputBuffer);
            ULONG nWritten;
            DbgPrint("[DUMP] Output buffer size %08x, address=%08x, radioIndex=%08x\n", 
                OutputBufferSize, pOutputBuffer, radioIndex);
            RadioManagerDumpRX(
                &pDevExt->RadioManager.__radio_pool[radioIndex], 
                pOutputBuffer, 
                OutputBufferSize, 
                &nWritten);
            RetInfo = nWritten;
        }
        break;
	case __IOCTL_RELEASE_RADIOS: {
			LIST_ENTRY* head;
			head = (LIST_ENTRY*)pInputBuffer;
			if (head) {
				LIST_ENTRY* entry;
				for(entry = head->Flink; entry != head; entry = entry->Flink) {
					SORA_RADIO* radio;
					radio = CONTAINING_RECORD(entry, SORA_RADIO, RadiosList);
					pDevExt->RadioMask &= ~(1<<radio->__radio_no);
				}
			}
		}
		break;
	case __IOCTL_MAP_SORA_REGISTER:
		hRes = PCIEMapSoraRegister(
			pDevExt, 
			pInputBuffer,
			InputBufferSize,
			pOutputBuffer,
			OutputBufferSize,
			&RetInfo);
		break;
	case __IOCTL_RELEASE_RESOURCE:
		hRes = PCIEReleaseResource(
			pDevExt, 
			pInputBuffer,
			InputBufferSize,
			pOutputBuffer,
			OutputBufferSize,
			&RetInfo);		
		break;
	case __IOCTL_ACQUIRE_RADIO_MANAGER: {
			if (OutputBufferLength >= sizeof(PSORA_RADIO_MANAGER*)) {
				PSORA_RADIO_MANAGER* sora_radio_manager;				
				sora_radio_manager = (PSORA_RADIO_MANAGER*)pOutputBuffer;
			   *sora_radio_manager = &pDevExt->RadioManager;
			    pDevExt->RadioManagerRef ++;
				RetInfo = sizeof(PSORA_RADIO_MANAGER*);
				Status = STATUS_SUCCESS;
			}
			else {
				RetInfo = 0;
				Status = STATUS_BUFFER_TOO_SMALL;
			}
		}
		break;
	case __IOCTL_RELEASE_RADIO_MANAGER: {
				pDevExt->RadioManagerRef --;
				RetInfo = 0;
				Status = STATUS_SUCCESS;
		}
		break;		
    default:
		Status = STATUS_INVALID_PARAMETER;
        break;
    }
    
    if (Status != STATUS_PENDING)
    {
        WdfRequestCompleteWithInformation(Request, Status, RetInfo);
    }
}
Beispiel #22
0
VOID
OsrUsbIoctlGetInterruptMessage(
    _In_ WDFDEVICE Device,
    _In_ NTSTATUS  ReaderStatus
    )
/*++

Routine Description

    This method handles the completion of the pended request for the IOCTL
    IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE.

Arguments:

    Device - Handle to a framework device.

Return Value:

    None.

--*/
{
    NTSTATUS            status;
    WDFREQUEST          request;
    PDEVICE_CONTEXT     pDevContext;
    size_t              bytesReturned = 0;
    PSWITCH_STATE       switchState = NULL;

    pDevContext = GetDeviceContext(Device);

    do {

        //
        // Check if there are any pending requests in the Interrupt Message Queue.
        // If a request is found then complete the pending request.
        //
        status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request);

        if (NT_SUCCESS(status)) {
            status = WdfRequestRetrieveOutputBuffer(request,
                                                    sizeof(SWITCH_STATE),
                                                    &switchState,
                                                    NULL);// BufferLength

            if (!NT_SUCCESS(status)) {

                TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                    "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n");
                bytesReturned = sizeof(SWITCH_STATE);

            } else {

                //
                // Copy the state information saved by the continuous reader.
                //
                if (NT_SUCCESS(ReaderStatus)) {
                    switchState->SwitchesAsUChar = pDevContext->CurrentSwitchState;
                    bytesReturned = sizeof(SWITCH_STATE);
                } else {
                    bytesReturned = 0;
                }
            }

            //
            // Complete the request.  If we failed to get the output buffer then 
            // complete with that status.  Otherwise complete with the status from the reader.
            //
            WdfRequestCompleteWithInformation(request, 
                                              NT_SUCCESS(status) ? ReaderStatus : status, 
                                              bytesReturned);
            status = STATUS_SUCCESS;

        } else if (status != STATUS_NO_MORE_ENTRIES) {
            KdPrint(("WdfIoQueueRetrieveNextRequest status %08x\n", status));
        }

        request = NULL;

    } while (status == STATUS_SUCCESS);

    return;

}
Beispiel #23
0
VOID
OsrFxEvtIoDeviceControl(
    _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

--*/
{
    WDFDEVICE           device;
    PDEVICE_CONTEXT     pDevContext;
    size_t              bytesReturned = 0;
    PBAR_GRAPH_STATE    barGraphState = NULL;
    PSWITCH_STATE       switchState = NULL;
    PUCHAR              sevenSegment = NULL;
    BOOLEAN             requestPending = FALSE;
    NTSTATUS            status = STATUS_INVALID_DEVICE_REQUEST;

    UNREFERENCED_PARAMETER(InputBufferLength);
    UNREFERENCED_PARAMETER(OutputBufferLength);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "--> OsrFxEvtIoDeviceControl\n");
    //
    // initialize variables
    //
    device = WdfIoQueueGetDevice(Queue);
    pDevContext = GetDeviceContext(device);

    switch(IoControlCode) {

    case IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR: {

        PUSB_CONFIGURATION_DESCRIPTOR   configurationDescriptor = NULL;
        USHORT                          requiredSize = 0;

        //
        // First get the size of the config descriptor
        //
        status = WdfUsbTargetDeviceRetrieveConfigDescriptor(
                                    pDevContext->UsbDevice,
                                    NULL,
                                    &requiredSize);

        if (status != STATUS_BUFFER_TOO_SMALL) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status);
            break;
        }

        //
        // Get the buffer - make sure the buffer is big enough
        //
        status = WdfRequestRetrieveOutputBuffer(Request,
                                        (size_t)requiredSize,  // MinimumRequired
                                        &configurationDescriptor,
                                        NULL);
        if(!NT_SUCCESS(status)){
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status);
            break;
        }

        status = WdfUsbTargetDeviceRetrieveConfigDescriptor(
                                        pDevContext->UsbDevice,
                                        configurationDescriptor,
                                        &requiredSize);
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status);
            break;
        }

        bytesReturned = requiredSize;

        }
        break;

    case IOCTL_OSRUSBFX2_RESET_DEVICE:

        status = ResetDevice(device);
        break;

    case IOCTL_OSRUSBFX2_REENUMERATE_DEVICE:

        //
        // Otherwise, call our function to reenumerate the
        //  device
        //
        status = ReenumerateDevice(pDevContext);

        bytesReturned = 0;
        break;

    case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY:

        //
        // Make sure the caller's output buffer is large enough
        //  to hold the state of the bar graph
        //
        status = WdfRequestRetrieveOutputBuffer(Request,
                            sizeof(BAR_GRAPH_STATE),
                            &barGraphState,
                            NULL);

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "User's output buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n");
            break;
        }
        //
        // Call our function to get the bar graph state
        //
        status = GetBarGraphState(pDevContext, barGraphState);

        //
        // If we succeeded return the user their data
        //
        if (NT_SUCCESS(status)) {

            bytesReturned = sizeof(BAR_GRAPH_STATE);

        } else {

            bytesReturned = 0;

        }
        break;

    case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY:

        status = WdfRequestRetrieveInputBuffer(Request,
                            sizeof(BAR_GRAPH_STATE),
                            &barGraphState,
                            NULL);
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "User's input buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n");
            break;
        }

        //
        // Call our routine to set the bar graph state
        //
        status = SetBarGraphState(pDevContext, barGraphState);

        //
        // There's no data returned for this call
        //
        bytesReturned = 0;
        break;

    case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY:

        status = WdfRequestRetrieveOutputBuffer(Request,
                            sizeof(UCHAR),
                            &sevenSegment,
                            NULL);

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "User's output buffer is too small for this IOCTL, expecting an UCHAR\n");
            break;
        }

        //
        // Call our function to get the 7 segment state
        //
        status = GetSevenSegmentState(pDevContext, sevenSegment);

        //
        // If we succeeded return the user their data
        //
        if (NT_SUCCESS(status)) {

            bytesReturned = sizeof(UCHAR);

        } else {

            bytesReturned = 0;

        }
        break;

    case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY:

        status = WdfRequestRetrieveInputBuffer(Request,
                            sizeof(UCHAR),
                            &sevenSegment,
                            NULL);
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "User's input buffer is too small for this IOCTL, expecting an UCHAR\n");
            bytesReturned = sizeof(UCHAR);
            break;
        }

        //
        // Call our routine to set the 7 segment state
        //
        status = SetSevenSegmentState(pDevContext, sevenSegment);

        //
        // There's no data returned for this call
        //
        bytesReturned = 0;
        break;

    case IOCTL_OSRUSBFX2_READ_SWITCHES:

        status = WdfRequestRetrieveOutputBuffer(Request,
                            sizeof(SWITCH_STATE),
                            &switchState,
                            NULL);// BufferLength

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
                "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n");
            bytesReturned = sizeof(SWITCH_STATE);
            break;

        }

        //
        // Call our routine to get the state of the switches
        //
        status = GetSwitchState(pDevContext, switchState);

        //
        // If successful, return the user their data
        //
        if (NT_SUCCESS(status)) {

            bytesReturned = sizeof(SWITCH_STATE);

        } else {
            //
            // Don't return any data
            //
            bytesReturned = 0;
        }
        break;

    case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE:

        //
        // Forward the request to an interrupt message queue and dont complete
        // the request until an interrupt from the USB device occurs.
        //
        status = WdfRequestForwardToIoQueue(Request, pDevContext->InterruptMsgQueue);
        if (NT_SUCCESS(status)) {
            requestPending = TRUE;
        }

        break;

    default :
        status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    if (requestPending == FALSE) {
        WdfRequestCompleteWithInformation(Request, status, bytesReturned);
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "<-- OsrFxEvtIoDeviceControl\n");

    return;
}
static VOID
XenUsb_EvtIoDeviceControl(
  WDFQUEUE queue,
  WDFREQUEST request,
  size_t output_buffer_length,
  size_t input_buffer_length,
  ULONG io_control_code)
{
  NTSTATUS status;
  WDFDEVICE device = WdfIoQueueGetDevice(queue);
  PXENUSB_DEVICE_DATA xudd = GetXudd(device);

  UNREFERENCED_PARAMETER(queue);
  UNREFERENCED_PARAMETER(input_buffer_length);
  UNREFERENCED_PARAMETER(output_buffer_length);

  FUNCTION_ENTER();

  status = STATUS_BAD_INITIAL_PC;

  // these are in api\usbioctl.h
  switch(io_control_code)
  {
  case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
    break;
  case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
    FUNCTION_MSG("IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_NAME:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
    break;
  case IOCTL_USB_DIAG_IGNORE_HUBS_ON:
    FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_ON\n");
    break;
  case IOCTL_USB_DIAG_IGNORE_HUBS_OFF:
    FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
    break;
  case IOCTL_USB_GET_HUB_CAPABILITIES:
    FUNCTION_MSG("IOCTL_USB_GET_HUB_CAPABILITIES\n");
    break;
  case IOCTL_USB_HUB_CYCLE_PORT:
    FUNCTION_MSG("IOCTL_USB_HUB_CYCLE_PORT\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n");
    break;
  case IOCTL_USB_GET_ROOT_HUB_NAME:
  {
    PUSB_HCD_DRIVERKEY_NAME uhdn;
    size_t length;
    ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
    
    FUNCTION_MSG("IOCTL_USB_GET_ROOT_HUB_NAME\n");
    FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length);
      
    if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
      status = STATUS_BUFFER_TOO_SMALL;
    } else {
      status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
      if (NT_SUCCESS(status)) {
        WDFSTRING symbolic_link_wdfstring;
        UNICODE_STRING symbolic_link;
        
        uhdn->DriverKeyName[0] = 0;
        status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolic_link_wdfstring);
        if (NT_SUCCESS(status)) {
          status = WdfDeviceRetrieveDeviceInterfaceString(xudd->root_hub_device, &GUID_DEVINTERFACE_USB_HUB, NULL, symbolic_link_wdfstring);
          if (NT_SUCCESS(status)) {
            WdfStringGetUnicodeString(symbolic_link_wdfstring, &symbolic_link);
            /* remove leading \??\ from name */
            symbolic_link.Buffer += 4;
            symbolic_link.Length -= 4 * sizeof(WCHAR);
            required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + symbolic_link.Length + sizeof(WCHAR);
            FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
            FUNCTION_MSG("required_length = %d\n", required_length);
            if (output_buffer_length >= required_length) {
              uhdn->ActualLength = required_length;
              memcpy(uhdn->DriverKeyName, symbolic_link.Buffer, symbolic_link.Length);
              uhdn->DriverKeyName[symbolic_link.Length / 2] = 0;
              WdfRequestSetInformation(request, required_length);
            } else {
              uhdn->ActualLength = required_length;
              uhdn->DriverKeyName[0] = 0;
              status = STATUS_SUCCESS;
              WdfRequestSetInformation(request, output_buffer_length);
            }
          } else {
            FUNCTION_MSG("WdfStringCreate = %08x\n", status);
          }
        } else {
          FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString = %08x\n", status);
          status = STATUS_INVALID_PARAMETER;
        }
      } else {
        FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status);
      }
      FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
      FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
    }
    break;
  }
  case IOCTL_GET_HCD_DRIVERKEY_NAME:
  {
    PUSB_HCD_DRIVERKEY_NAME uhdn;
    size_t length;
    ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
    ULONG key_length;
    
    FUNCTION_MSG("IOCTL_GET_HCD_DRIVERKEY_NAME\n");
    FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length);
      
    if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
      FUNCTION_MSG("Buffer too small (%d < %d)\n", output_buffer_length, sizeof(USB_HCD_DRIVERKEY_NAME));
      status = STATUS_BUFFER_TOO_SMALL;
      break;
    }
    status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
    if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status);
      break;
    }
    status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 0, NULL, &key_length);
    if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("WdfDeviceQueryProperty = %08x\n", status);
      break;
    }    
    FUNCTION_MSG(" key_length = %d\n", key_length);
    required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + key_length + 2;
    uhdn->ActualLength = required_length;
    FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
    FUNCTION_MSG("required_length = %d\n", required_length);
    if (output_buffer_length >= required_length)
    {
      status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 
        required_length - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName), uhdn->DriverKeyName,
        &key_length);
      WdfRequestSetInformation(request, required_length);
    }
    else
    {
      uhdn->DriverKeyName[0] = 0;
      status = STATUS_SUCCESS;
      WdfRequestSetInformation(request, output_buffer_length);
    }
    FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
    FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
    break;
  }
#if 0
  case IOCTL_USB_RESET_HUB:
    FUNCTION_MSG("IOCTL_USB_RESET_HUB\n");
    break;
#endif
  default:
    FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code);
    break;
  }
  FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n", status);
  WdfRequestComplete(request, status);

  FUNCTION_EXIT();
}
Beispiel #25
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;
}
Beispiel #26
0
/*
** Driver TODO: Add code to handle various get-property cases.
**
** Implement this function to handle property get requests.
*/
NTSTATUS ProcessGetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information)
{
    if (Information == nullptr || Request == nullptr || InputBufferLength < sizeof(PosPropertyId))
    {
        return STATUS_INVALID_PARAMETER;
    }

    // POS properties are identified by the property ID that's transmitted in the input buffer.
    PosPropertyId* propertyId;
    NTSTATUS status = WdfRequestRetrieveInputBuffer(
        Request,
        sizeof(PosPropertyId),
        reinterpret_cast<PVOID*>(&propertyId),
        nullptr
        );

    if (!NT_SUCCESS(status))
    {
        return status;
    }

    // All get properties will need access to the output buffer in order to return results.
    // The minimum size returned is a UINT32
    void* outputBuffer;
    size_t outputBufferLength;
    status = WdfRequestRetrieveOutputBuffer(
        Request,
        sizeof(UINT32),
        &outputBuffer,
        &outputBufferLength
        );

    if (!NT_SUCCESS(status))
    {
        return status;
    }

    // Handle this set of readable properties
    switch (*propertyId)
    {
    case PosPropertyId::IsEnabled:
        // BOOL result, true when the app has called SetProperty(IsEnabled) = TRUE
        {
            BOOL isEnabled = TRUE; // Get this value from device context or by querying the device
            *((BOOL*)outputBuffer) = isEnabled;
            *Information = sizeof(BOOL);
        }
        break;

    case PosPropertyId::IsDisabledOnDataReceived:
        // BOOL result, true when the app has called SetProperty(IsDisabledOnDataReceived) = TRUE
        {
            BOOL isDisabledOnDataReceived = TRUE; // Get this value from device context or by querying the device
            *((BOOL*)outputBuffer) = isDisabledOnDataReceived;
            *Information = sizeof(BOOL);
        }
        break;

    case PosPropertyId::MagneticStripeReaderIsDecodeDataEnabled:
        // BOOL result, true when the app has called SetProperty(MagneticStripeReaderIsDecodeDataEnabled) = TRUE
        {
            BOOL isDecodeDataEnabled = TRUE; // Get this value from device context or by querying the device
            *((BOOL*)outputBuffer) = isDecodeDataEnabled;
            *Information = sizeof(BOOL);
        }
        break;

    case PosPropertyId::MagneticStripeReaderCapabilities:
        {
            // PosMagneticStripeReaderCapabilitiesType result
            // These capabilities are likely hard-coded for the specific device.  In this case, example values are provided and should
            // be replaced with values that match your hardware
            PosMagneticStripeReaderCapabilitiesType capabilities;
            capabilities.PowerReportingType = DriverUnifiedPosPowerReportingType::Standard;
            capabilities.IsStatisticsReportingSupported = TRUE;
            capabilities.IsStatisticsUpdatingSupported = TRUE;
            capabilities.CardAuthenticationLength = 0;
            capabilities.SupportedEncryptionAlgorithms = MsrDataEncryption::MsrDataEncryption_AES;
            capabilities.AuthenticationLevel = DriverMagneticStripeReaderAuthenticationLevel::Optional;
            capabilities.IsIsoSupported = TRUE;
            capabilities.IsJisOneSupported = TRUE;
            capabilities.IsJisTwoSupported = TRUE;
            capabilities.IsTrackDataMaskingSupported = TRUE;
            capabilities.IsTransmitSentinelsSupported = TRUE;
            size_t bytesToCopy = sizeof(PosMagneticStripeReaderCapabilitiesType);
            if (outputBufferLength < bytesToCopy)
            {
                bytesToCopy = outputBufferLength;
                status = STATUS_BUFFER_OVERFLOW;
            }
            memcpy(outputBuffer, &capabilities, bytesToCopy);
            *Information = bytesToCopy;
        }
        break;

    case PosPropertyId::MagneticStripeReaderSupportedCardTypes:
        {
            // Supported card types.  The API understands Bank and AAMVA, but additional, device-specific values can be added as well
            // This property is typically hard coded based on the device type
            MSR_SUPPORTED_CARD_TYPES supportedCardTypes;
            RtlZeroMemory(&supportedCardTypes, sizeof(MSR_SUPPORTED_CARD_TYPES));
            supportedCardTypes.Count = 2;
            supportedCardTypes.CardTypes[0] = (unsigned int)MsrCardType::MsrCardType_Bank;
            supportedCardTypes.CardTypes[1] = (unsigned int)MsrCardType::MsrCardType_Aamva;
            size_t bytesToCopy = sizeof(MSR_SUPPORTED_CARD_TYPES);
            if (outputBufferLength < bytesToCopy)
            {
                bytesToCopy = outputBufferLength;
                status = STATUS_BUFFER_OVERFLOW;
            }
            memcpy(outputBuffer, &supportedCardTypes, bytesToCopy);
            *Information = bytesToCopy;
        }
        break;

    case PosPropertyId::MagneticStripeReaderDeviceAuthenticationProtocol:
        {
            // Returns whether the device supports challenge/response authentication or not.
            *((MsrAuthenticationProtocolType*)outputBuffer) = MsrAuthenticationProtocolType::MsrAuthenticationProtocolType_ChallengeResponse;
            *Information = sizeof(MsrAuthenticationProtocolType);
        }
        break;

    case PosPropertyId::MagneticStripeReaderErrorReportingType:
        {
            // Returns whether the device should report errors at the card or track level.
            // This value is typically retrieved from the device context based on a prior SetProperty(MagneticStripeReaderErrorReportingType)
            *((MsrErrorReportingType*)outputBuffer) = MsrErrorReportingType::MsrErrorReportingType_CardLevel;
            *Information = sizeof(MsrErrorReportingType);
        }
        break;

    case PosPropertyId::MagneticStripeReaderTracksToRead:
        {
            // typically this value is saved in the device context to track which tracks the application wants to read from the card
            MsrTrackIds tracksToRead = (MsrTrackIds)(MsrTrackIds::MsrTrackIds_Track1 | MsrTrackIds::MsrTrackIds_Track2);
            *((MsrTrackIds*)outputBuffer) = tracksToRead;
            *Information = sizeof(MsrTrackIds);
        }
        break;

    case PosPropertyId::MagneticStripeReaderIsTransmitSentinelsEnabled:
        {
            // BOOL property.  True if the data that is sent to the application will include start/end sentinals or not
            // This property can return STATUS_NOT_SUPPORTED if the IsTransmitSentinelsSupported capability is FALSE
            // Otherwise, the boolean that's returned should be captured from the device context or from the device itself
            BOOL isTransmitSentinelsEnabled = TRUE;
            *((BOOL*)outputBuffer) = isTransmitSentinelsEnabled;
            *Information = sizeof(BOOL);
        }
        break;

    case PosPropertyId::MagneticStripeReaderIsDeviceAuthenticated:
        {
            // BOOL property.  True if the the authentication process has been successful
            // This value should come from the device context or from the device itself
            BOOL isAuthenticated = TRUE;
            *((BOOL*)outputBuffer) = isAuthenticated;
            *Information = sizeof(BOOL);
        }
        break;

    case PosPropertyId::MagneticStripeReaderDataEncryptionAlgorithm:
        {
            // Returns the encryption algorithm used to decrypt the card data
            // If the device supports multiple algorithms, it should store the current one in the device context and use that value here
            // (or retrieve the value from the device itself)
            MsrDataEncryption currentEncryptionAlgorithm = MsrDataEncryption::MsrDataEncryption_AES;
            *((MsrDataEncryption*)outputBuffer) = currentEncryptionAlgorithm;
        }
        break;

    default:
        // no other readable properties for magnetic stripe reader
        return STATUS_INVALID_PARAMETER;
    }

    return STATUS_SUCCESS;
}
VOID
VIOSerialPortDeviceControl(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t     OutputBufferLength,
    IN size_t     InputBufferLength,
    IN ULONG      IoControlCode
    )
{
    PRAWPDO_VIOSERIAL_PORT  pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue));
    size_t                  length = 0;
    NTSTATUS                status = STATUS_SUCCESS;
    PVIRTIO_PORT_INFO       pport_info = NULL;
    size_t                  name_size = 0;

    PAGED_CODE();

    UNREFERENCED_PARAMETER( InputBufferLength  );
    UNREFERENCED_PARAMETER( OutputBufferLength  );

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> %s\n", __FUNCTION__);

    switch (IoControlCode)
    {

        case IOCTL_GET_INFORMATION:
        {
           status = WdfRequestRetrieveOutputBuffer(Request, sizeof(VIRTIO_PORT_INFO), (PVOID*)&pport_info, &length);
           if (!NT_SUCCESS(status))
           {
              TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                            "WdfRequestRetrieveInputBuffer failed 0x%x\n", status);
              WdfRequestComplete(Request, status);
              return;
           }
           if (pdoData->port->NameString.Buffer)
           {
              name_size = pdoData->port->NameString.MaximumLength;
           }
           if (length < sizeof (VIRTIO_PORT_INFO) + name_size)
           {
              status = STATUS_BUFFER_TOO_SMALL;
              TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                            "Buffer too small. get = %d, expected = %d\n", length, sizeof (VIRTIO_PORT_INFO) + name_size);
              length = sizeof (VIRTIO_PORT_INFO) + name_size;
              break;
           }
           RtlZeroMemory(pport_info, sizeof(VIRTIO_PORT_INFO));
           pport_info->Id = pdoData->port->PortId;
           pport_info->OutVqFull = pdoData->port->OutVqFull;
           pport_info->HostConnected = pdoData->port->HostConnected;
           pport_info->GuestConnected = pdoData->port->GuestConnected;

           if (pdoData->port->NameString.Buffer)
           {
              RtlZeroMemory(pport_info->Name, name_size);
              status = RtlStringCbCopyA(pport_info->Name, name_size - 1, pdoData->port->NameString.Buffer);
              if (!NT_SUCCESS(status))
              {
                 TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS,
                            "RtlStringCbCopyA failed 0x%x\n", status);
                 name_size = 0;
              }
           }
           status = STATUS_SUCCESS;
           length =  sizeof (VIRTIO_PORT_INFO) + name_size;
           break;
        }

        default:
           status = STATUS_INVALID_DEVICE_REQUEST;
           break;
    }
    WdfRequestCompleteWithInformation(Request, status, length);
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %s\n", __FUNCTION__);
}
Beispiel #28
0
VOID
FileEvtIoDeviceControl(
    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            status = STATUS_SUCCESS;// Assume success
    PCHAR               inBuf = NULL, outBuf = NULL; // pointer to Input and output buffer
    PCHAR               data = "this String is from Device Driver !!!";
    ULONG               datalen = (ULONG) strlen(data)+1;//Length of data including null
    PCHAR               buffer = NULL;
    PREQUEST_CONTEXT    reqContext = NULL;
    size_t               bufSize;

    UNREFERENCED_PARAMETER( Queue );

    PAGED_CODE();

    if(!OutputBufferLength || !InputBufferLength)
    {
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;
    }

    //
    // Determine which I/O control code was specified.
    //

    switch (IoControlCode)
    {
    case IOCTL_NONPNP_METHOD_BUFFERED:


        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_BUFFERED\n");

        //
        // For bufffered ioctls WdfRequestRetrieveInputBuffer &
        // WdfRequestRetrieveOutputBuffer return the same buffer
        // pointer (Irp->AssociatedIrp.SystemBuffer), so read the
        // content of the buffer before writing to it.
        //
        status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == InputBufferLength);

        //
        // Read the input buffer content.
        // We are using the following function to print characters instead
        // TraceEvents with %s format because the string we get may or
        // may not be null terminated. The buffer may contain non-printable
        // characters also.
        //
        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                        log_xstr(inBuf, (USHORT)InputBufferLength)));
        PrintChars(inBuf, InputBufferLength  );


        status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == OutputBufferLength);

        //
        // Writing to the buffer over-writes the input buffer content
        //

        RtlCopyMemory(outBuf, data, OutputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data to User : %!HEXDUMP!\n",
                        log_xstr(outBuf, (USHORT)datalen)));
        PrintChars(outBuf, datalen  );

        //
        // Assign the length of the data copied to IoStatus.Information
        // of the request and complete the request.
        //
        WdfRequestSetInformation(Request,
                OutputBufferLength < datalen? OutputBufferLength:datalen);

        //
        // When the request is completed the content of the SystemBuffer
        // is copied to the User output buffer and the SystemBuffer is
        // is freed.
        //

       break;


    case IOCTL_NONPNP_METHOD_IN_DIRECT:


        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_IN_DIRECT\n");

        //
        // Get the Input buffer. WdfRequestRetrieveInputBuffer returns
        // Irp->AssociatedIrp.SystemBuffer.
        //
        status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == InputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                        log_xstr(inBuf, (USHORT)InputBufferLength)));
        PrintChars(inBuf, InputBufferLength);

        //
        // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe
        // on the Irp->MdlAddress and returns the system address.
        // Oddity: For this method, this buffer is intended for transfering data
        // from the application to the driver.
        //

        status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize);
        if(!NT_SUCCESS(status)) {
            break;
        }

        ASSERT(bufSize == OutputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User in OutputBuffer: %!HEXDUMP!\n",
                        log_xstr(buffer, (USHORT)OutputBufferLength)));
        PrintChars(buffer, OutputBufferLength);

        //
        // Return total bytes read from the output buffer.
        // Note OutputBufferLength = MmGetMdlByteCount(Irp->MdlAddress)
        //

        WdfRequestSetInformation(Request, OutputBufferLength);

        //
        // NOTE: Changes made to the  SystemBuffer are not copied
        // to the user input buffer by the I/O manager
        //

      break;

    case IOCTL_NONPNP_METHOD_OUT_DIRECT:


        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_OUT_DIRECT\n");

        //
        // Get the Input buffer. WdfRequestRetrieveInputBuffer returns
        // Irp->AssociatedIrp.SystemBuffer.
        //
        status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == InputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                        log_xstr(inBuf, (USHORT)InputBufferLength)));
        PrintChars(inBuf, InputBufferLength);

        //
        // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe
        // on the Irp->MdlAddress and returns the system address.
        // For this method, this buffer is intended for transfering data from the
        // driver to the application.
        //
        status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize);
        if(!NT_SUCCESS(status)) {
            break;
        }

        ASSERT(bufSize == OutputBufferLength);

        //
        // Write data to be sent to the user in this buffer
        //
        RtlCopyMemory(buffer, data, OutputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data to User : %!HEXDUMP!\n",
                        log_xstr(buffer, (USHORT)datalen)));
        PrintChars(buffer, datalen);

        WdfRequestSetInformation(Request,
                    OutputBufferLength < datalen? OutputBufferLength: datalen);

        //
        // NOTE: Changes made to the  SystemBuffer are not copied
        // to the user input buffer by the I/O manager
        //

        break;

    case IOCTL_NONPNP_METHOD_NEITHER:
        {
            size_t inBufLength, outBufLength;

            //
            // The NonPnpEvtDeviceIoInCallerContext has already probe and locked the
            // pages and mapped the user buffer into system address space and
            // stored memory buffer pointers in the request context. We can get the
            // buffer pointer by calling WdfMemoryGetBuffer.
            //
            TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_NEITHER\n");

            reqContext = GetRequestContext(Request);

            inBuf = WdfMemoryGetBuffer(reqContext->InputMemoryBuffer, &inBufLength);
            outBuf = WdfMemoryGetBuffer(reqContext->OutputMemoryBuffer, &outBufLength);

            if(inBuf == NULL || outBuf == NULL) {
                status = STATUS_INVALID_PARAMETER;
            }

            ASSERT(inBufLength == InputBufferLength);
            ASSERT(outBufLength == OutputBufferLength);

            //
            // Now you can safely read the data from the buffer in any arbitrary
            // context.
            //
            Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                            log_xstr(inBuf, (USHORT)inBufLength)));
            PrintChars(inBuf, inBufLength);

            //
            // Write to the buffer in any arbitrary context.
            //
            RtlCopyMemory(outBuf, data, outBufLength);

            Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data to User : %!HEXDUMP!\n",
                            log_xstr(outBuf, (USHORT)datalen)));
            PrintChars(outBuf, datalen);

            //
            // Assign the length of the data copied to IoStatus.Information
            // of the Irp and complete the Irp.
            //
            WdfRequestSetInformation(Request,
                    outBufLength < datalen? outBufLength:datalen);

            break;
        }
    default:

        //
        // The specified I/O control code is unrecognized by this driver.
        //
        status = STATUS_INVALID_DEVICE_REQUEST;
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ERROR: unrecognized IOCTL %x\n", IoControlCode);
        break;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Completing Request %p with status %X",
                   Request, status );

    WdfRequestComplete( Request, status);

}
Beispiel #29
0
VOID
FilterEvtIoDeviceControlFromRawPdo(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
/*++

Routine Description:

    This routine is the dispatch routine for internal device control requests.
    
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

--*/
{
    PFILTER_EXTENSION               filterExt;
    NTSTATUS                        status = STATUS_SUCCESS;
	size_t                          bytesReturned = 0;
    WDFDEVICE                       device;
	BYTE*                           pDevInfoLen; // len retrieved from device
	BYTE*                           pDevInfoLenInput; // len input from app
	BYTE*                           pDevInfoData; // data retrieved from device

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    KdPrint(("--> FilterEvtIoDeviceControlFromRawPdo\n"));

    device = WdfIoQueueGetDevice(Queue);

    filterExt = FilterGetData(device);

    switch (IoControlCode) {

    //
    // Put your cases for handling IOCTLs here
    //
    case IOCTL_OSRUSBFX2_FILTER_GETDEVINFOLEN:
	    KdPrint(("Entered IOCTL_OSRUSBFX2_FILTER_GETDEVINFOLEN\n"));

		//
        // Make sure the caller's output buffer is large enough
        // to hold the state of the bar graph
        //
        status = WdfRequestRetrieveOutputBuffer(Request,
                            sizeof(BYTE),
                            &pDevInfoLen,
                            NULL);

        if (!NT_SUCCESS(status)) {
			KdPrint(("User's output buffer is too small for this IOCTL, expecting an BYTE\n"));
            break;
        }
        //
        // Call our function to get
        //
        status = GetDevInfoLength(filterExt, pDevInfoLen);

		//
        // If we succeeded return the user their data
        //
        if (NT_SUCCESS(status)) {
            bytesReturned = sizeof(BYTE);

        } else {
            bytesReturned = 0;

        }
		
		KdPrint(("Completed IOCTL_OSRUSBFX2_FILTER_GETDEVINFOLEN\n"));		
        break;

    case IOCTL_OSRUSBFX2_FILTER_GETDEVINFODATA:
	    KdPrint(("Entered IOCTL_OSRUSBFX2_FILTER_GETDEVINFODATA\n"));

        status = WdfRequestRetrieveInputBuffer(Request,
                            sizeof(BYTE),
                            &pDevInfoLenInput,
                            NULL);
        if (!NT_SUCCESS(status)) {
            KdPrint(("User's input buffer is too small for this IOCTL, expecting a BYTE\n"));
			bytesReturned = 0;
            break;
        }
		KdPrint(("Input length is %d\n", *pDevInfoLenInput));
		//
        // Make sure the caller's output buffer is large enough
        // to hold the state of the bar graph
        //
        status = WdfRequestRetrieveOutputBuffer(Request,
                            *pDevInfoLenInput,
                            &pDevInfoData,
                            NULL);

        if (!NT_SUCCESS(status)) {
			KdPrint(("User's output buffer is too small for this IOCTL, expecting an BYTE\n"));
			bytesReturned = 0;
            break;
        }
        //
        // Call our function to get
        //
        status = GetDevInfoData(filterExt, *pDevInfoLenInput, pDevInfoData, &bytesReturned );

		//
        // If we succeeded return the user their data
        //
        if (!NT_SUCCESS(status)) {
            bytesReturned = 0;
        }
		
		KdPrint(("Completed IOCTL_OSRUSBFX2_FILTER_GETDEVINFODATA\n"));		
        break;
		
	default:
		status = STATUS_INVALID_DEVICE_REQUEST;
		break;
		
    }
    
    WdfRequestCompleteWithInformation ( Request, status, bytesReturned );

    KdPrint(("<-- FilterEvtIoDeviceControlFromRawPdo\n"));
    
    return;
}
Beispiel #30
0
///////////////////////////////////////////////////////////////////////////////
//
//  BasicUsbInterruptPipeReadComplete
//
//    This is the callback we supplied for the continuous reader
//    on the interrupt IN pipe. It is called whenever the user
//    changes the state of the switches on the switch pack
//
//  INPUTS:
//
//      Pipe    - Our interrupt IN pipe
//
//      Buffer  - The WDFMEMORY object associated with the
//                 transfer. The buffer of thie memory contains
//                 the state of the switch pack
//
//      NumBytesTransferred - Self explanatory
//
//      Context - One of our per device context structures
//                (passed as a parameter to
//                 WDF_USB_CONTINUOUS_READER_CONFIG_INIT)
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      STATUS_SUCCESS, otherwise an error indicating why the driver could not
//                      load.
//
//  IRQL:
//
//      This routine is called at IRQL <= DISPATCH_LEVEL.
//
//  NOTES:
//
//      Even though we've applied a PASSIVE_LEVEL execution
//      level constraint on our device, this callback falls
//      outstide of the callbacks that the constraint is
//      enforced on.
//
///////////////////////////////////////////////////////////////////////////////
VOID
BasicUsbInterruptPipeReadComplete(
    IN WDFUSBPIPE Pipe,
    IN WDFMEMORY Buffer,
    IN size_t NumBytesTransferred,
    IN WDFCONTEXT Context
    ) {

    PUCHAR                   dataBuffer;
    WDFREQUEST               stateChangeRequest;
    PBASICUSB_DEVICE_CONTEXT devContext;
    PUCHAR                   userBuffer;
    NTSTATUS                 status;

    UNREFERENCED_PARAMETER(Pipe);
    UNREFERENCED_PARAMETER(NumBytesTransferred);
    UNREFERENCED_PARAMETER(Context);

    //
    // Someone toggled the switch pack. Complete a pending user
    // request if there is one.
    //

    devContext = (PBASICUSB_DEVICE_CONTEXT)Context;

    dataBuffer = (PUCHAR)WdfMemoryGetBuffer(Buffer, NULL);

#if DBG
    DbgPrint("Interrupt read complete. Bytes transferred = 0x%x, Data = 0x%x\n",
             (ULONG)NumBytesTransferred, *dataBuffer);
#endif

    //
    // See if there is anyone waiting to be notified of the state
    // change.
    //
    status = WdfIoQueueRetrieveNextRequest(
                                        devContext->SwitchPackStateChangeQueue,
                                        &stateChangeRequest);

    if (NT_SUCCESS(status)) {

#if DBG
        DbgPrint("State change request 0x%p pending\n", 
                 stateChangeRequest);
#endif
        //
        // Yup, someone waiting. Complete their request with the switch
        // pack state.
        //
        status = WdfRequestRetrieveOutputBuffer(stateChangeRequest, 
                                                sizeof(UCHAR),
                                                (PVOID *)&userBuffer,
                                                NULL);

        if (NT_SUCCESS(status)) {

            //
            // Stuff the value into the buffer...
            //
            *userBuffer = *dataBuffer;

            //
            // And complete the request, indicating the proper number of
            // bytes transferred.
            //
            WdfRequestCompleteWithInformation(stateChangeRequest,
                                              STATUS_SUCCESS,
                                              sizeof(UCHAR));
        } else {
#if DBG
            DbgPrint("Failed to get user buffer ofState change request 0x%x\n",
                     status);
#endif
            WdfRequestComplete(stateChangeRequest, status);

        }

    } else {
#if DBG
        DbgPrint("No state change requests pending? (0x%x)\n", 
                 status);
#endif

    }

    return;
}