VOID
GetEnhancedVerifierOptions(
    __in PCLIENT_INFO ClientInfo,
    __out PULONG Options
    )
{
    NTSTATUS status;
    ULONG value;
    FxAutoRegKey hKey, hWdf;
    DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf");
    DECLARE_CONST_UNICODE_STRING(valueName, WDF_ENHANCED_VERIFIER_OPTIONS_VALUE_NAME);

    *Options = 0;
    if (ClientInfo == NULL                       ||
        ClientInfo->Size != sizeof(CLIENT_INFO)  ||
        ClientInfo->RegistryPath == NULL         ||
        ClientInfo->RegistryPath->Length == 0    ||
        ClientInfo->RegistryPath->Buffer == NULL ||
        Options == NULL) {

        __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
                 ": Invalid ClientInfo received from wdfldr \n"));
        return;
    }

    status = FxRegKey::_OpenKey(NULL,
                                ClientInfo->RegistryPath,
                                &hWdf.m_Key,
                                KEY_READ);
    if (!NT_SUCCESS(status)) {
        return;
    }

    status = FxRegKey::_OpenKey(hWdf.m_Key,
                                &parametersPath,
                                &hKey.m_Key,
                                KEY_READ);
    if (!NT_SUCCESS(status)) {
        return;
    }

    status = FxRegKey::_QueryULong(
        hKey.m_Key, &valueName, &value);

    //
    // Examine key values and set Options only on success.
    //
    if (NT_SUCCESS(status)) {
        if (value) {
            *Options = value;
        }
    }
}
_Must_inspect_result_
BOOLEAN
FX_DRIVER_GLOBALS::IsCorrectVersionRegistered(
    _In_ PCUNICODE_STRING ServiceKeyName
    )
{
    FxAutoRegKey hDriver, hWdf;
    DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf");
    DECLARE_CONST_UNICODE_STRING(wdfMajorValue, WDF_MAJOR_VERSION_VALUE);
    DECLARE_CONST_UNICODE_STRING(wdfMinorValue, WDF_MINOR_VERSION_VALUE);
    ULONG registeredMajor = 0, registeredMinor = 0;
    NTSTATUS status;
    
    status = FxRegKey::_OpenKey(NULL, 
                                ServiceKeyName, 
                                &hDriver.m_Key, 
                                KEY_READ
                                );
    if (!NT_SUCCESS(status)) {
        return FALSE;
    }

    status = FxRegKey::_OpenKey(hDriver.m_Key, 
                                &parametersPath, 
                                &hWdf.m_Key, 
                                KEY_READ
                                );
    if (!NT_SUCCESS(status)) {
        return FALSE;
    }

    status = FxRegKey::_QueryULong(hWdf.m_Key,
                                   &wdfMajorValue,
                                   &registeredMajor);
    
    if (!NT_SUCCESS(status) || registeredMajor != WdfBindInfo->Version.Major) {
        return FALSE;
    }

    status = FxRegKey::_QueryULong(hWdf.m_Key,
                                   &wdfMinorValue,
                                   &registeredMinor);
    
    if  (!NT_SUCCESS(status) || registeredMinor != WdfBindInfo->Version.Minor){
        return FALSE;
    }
    else {
        return TRUE;
    }
}
_Use_decl_annotations_
NTSTATUS
SaveSimBattStateToRegistry (
    WDFDEVICE Device,
    PSIMBATT_STATE State
    )

/*
 Routine Description:

    Called to save simbatt state data to the registry.

Arguments:

    Device - Supplies WDF device handle.

    State - Supplies the pointer to the simbatt state.

Return Value:

    NTSTATUS

--*/

{

    WDFKEY  KeyHandle;
    DECLARE_CONST_UNICODE_STRING(SimbattStateRegNameStr, SIMBATT_STATE_REG_NAME);
    NTSTATUS Status;

    PAGED_CODE();

    Status = WdfDeviceOpenRegistryKey(
        Device,
        PLUGPLAY_REGKEY_DEVICE,
        KEY_WRITE,
        NULL,
        &KeyHandle
        );

    if (!NT_SUCCESS (Status)) {
        goto SaveSimBattStateToRegistryEnd;
    }

    Status = WdfRegistryAssignValue(
        KeyHandle,
        &SimbattStateRegNameStr,
        REG_BINARY,
        sizeof(SIMBATT_STATE),
        State
        );

    WdfRegistryClose(KeyHandle);
    if (!NT_SUCCESS (Status)) {
        goto SaveSimBattStateToRegistryEnd;
    }

SaveSimBattStateToRegistryEnd:
    return Status;
}
Example #4
0
NTSTATUS WriteBackupRegistersToRegistry(HANDLE_DEV Device)
{
    WDFKEY key = NULL;
    WDFKEY subkey = NULL;
    NTSTATUS status;

    // Retrieve registry settings.
    DECLARE_CONST_UNICODE_STRING(subConfigName, L"Config");
    DECLARE_CONST_UNICODE_STRING(backupName, L"backup");

    status = WdfDeviceOpenRegistryKey(Device, PLUGPLAY_REGKEY_DEVICE, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &key);

    if (!NT_SUCCESS(status))
    {
        TraceLog(TRACE_LEVEL_WARNING, TRACE_ALGO, "Error opening device registry key - %!STATUS!", status);
    }
    else
    {
        status = WdfRegistryOpenKey(key, &subConfigName, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &subkey);

        if (!NT_SUCCESS(status))
        {
            TraceLog(TRACE_LEVEL_WARNING, TRACE_ALGO, "Error opening registry subkey for 'Config' - %!STATUS!", status);
        }
        else
        {
            ULONG length = sizeof(gs_backupRegisters);
            status = WdfRegistryAssignValue(subkey, &backupName, REG_BINARY, length, gs_backupRegisters);

            if (!NT_SUCCESS(status))
            {
                TraceLog(TRACE_LEVEL_WARNING, TRACE_ALGO, "Error querying registry value for 'backup reg' - %!STATUS!", status);
            }
        }
        if (subkey != NULL)
        {
            WdfRegistryClose(subkey);
            subkey = NULL;
        }
    }
    if (key != NULL)
    {
        WdfRegistryClose(key);
        key = NULL;
    }
    return status;
}
Example #5
0
VOID
EvtDeviceCleanup(
    _In_  WDFOBJECT         Object
    )
{
    WDFDEVICE               device = (WDFDEVICE) Object;
    PDEVICE_CONTEXT         deviceContext = GetDeviceContext(device);
    NTSTATUS                status;
    WDFKEY                  key = NULL;
    UNICODE_STRING          pdoString = {0};
    
    DECLARE_CONST_UNICODE_STRING(deviceSubkey, SERIAL_DEVICE_MAP);

    if (deviceContext->CreatedLegacyHardwareKey == TRUE) {
    
        RtlInitUnicodeString(&pdoString, deviceContext->PdoName);
    
        status = WdfDeviceOpenDevicemapKey(device,
                                           &deviceSubkey,
                                           KEY_SET_VALUE,
                                           WDF_NO_OBJECT_ATTRIBUTES,
                                           &key);
                                           
        if (!NT_SUCCESS(status)) {
            Trace(TRACE_LEVEL_ERROR,
                "Error: Failed to open DEVICEMAP\\SERIALCOMM key 0x%x", status);
            goto exit;
        }
        
        status = WdfRegistryRemoveValue(key,
                                        &pdoString);
        if (!NT_SUCCESS(status)) {
            Trace(TRACE_LEVEL_ERROR,
                "Error: Failed to delete %S key, 0x%x", pdoString.Buffer, status);  
            goto exit;
        }
        
        status = WdfRegistryRemoveKey(key);
        if (!NT_SUCCESS(status)) {
            Trace(TRACE_LEVEL_ERROR,
                "Error: Failed to delete %S, 0x%x", SERIAL_DEVICE_MAP, status);  
            goto exit;
        }           
    }
        
exit:

    if (key != NULL) {
        WdfRegistryClose(key);
        key = NULL;
    }

    return;
}
Example #6
0
VOID MamakuRegistryInit(IN WDFDRIVER Driver)
{
    NTSTATUS status;
    WDFKEY key;
    DECLARE_CONST_UNICODE_STRING(UseMultitouchName, L"UseMultitouchDebug");
    DECLARE_CONST_UNICODE_STRING(DragThresholdName, L"DragThreshold");

    status = WdfDriverOpenParametersRegistryKey(Driver, STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &key);

    if (!NT_SUCCESS(status)) 
    {
        MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT,
            "WdfDriverOpenParametersRegistryKey failed with status 0x%x\n", status);

        return;
    }

    status = WdfRegistryQueryULong(key, &UseMultitouchName, &UseMultitouch);

    if (!NT_SUCCESS(status)) 
    {
        MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT,
            "WdfRegistryQueryULong(UseMultitouch) failed with status 0x%x\n", status);
    }

    MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT,
        "UseMultitouchDebug = %d\n", UseMultitouch);

    status = WdfRegistryQueryULong(key, &DragThresholdName, &DragThreshold);

    if (!NT_SUCCESS(status)) 
    {
        MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT,
            "WdfRegistryQueryULong(DragThreshold) failed with status 0x%x\n", status);
    }

    MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT,
        "DragThreshold = %d\n", DragThreshold);

    WdfRegistryClose(key);
}
_Use_decl_annotations_
NTSTATUS
TreeSampleCreateSecureDeviceContext(
    WDFDEVICE MasterDevice
    )

/*++

    Routine Description:

        This routine is called when the secure environment is first started.

    Arguments:

        MasterDevice - Supplies a handle to the master device object.

        DeviceContext - Supplies a pointer to store any context information
                        required for future calls.

    Return Value:

        NTSTATUS code.

--*/

{

    WDF_OBJECT_ATTRIBUTES ContextAttributes;
    PTREE_SAMPLE_DEVICE_CONTEXT MasterContext;
    NTSTATUS Status;
    DECLARE_CONST_UNICODE_STRING(SymbolicLink, L"\\DosDevices\\SampleTrEEDriver");

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes,
                                            TREE_SAMPLE_DEVICE_CONTEXT);

    Status = WdfObjectAllocateContext(MasterDevice, &ContextAttributes, &MasterContext);
    if (!NT_SUCCESS(Status)) {
        goto TreeSampleCreateSecureDeviceContextEnd;
    }

    MasterContext->MasterDevice = MasterDevice;

    //
    // Create a symbolic link so that usermode program can access master device.
    //
    Status = WdfDeviceCreateSymbolicLink(MasterDevice, &SymbolicLink);
    if (!NT_SUCCESS(Status)) {
        goto TreeSampleCreateSecureDeviceContextEnd;
    }

TreeSampleCreateSecureDeviceContextEnd:
    return Status;
}
Example #8
0
//
// Register our GUID and Datablock generated from the Firefly.mof file.
//
NTSTATUS
WmiInitialize(
    WDFDEVICE       Device,
    PDEVICE_CONTEXT DeviceContext
    )
{
    WDF_WMI_PROVIDER_CONFIG providerConfig;
    WDF_WMI_INSTANCE_CONFIG instanceConfig;
    WDF_OBJECT_ATTRIBUTES woa;
    WDFWMIINSTANCE instance;
    NTSTATUS status;
    DECLARE_CONST_UNICODE_STRING(mofRsrcName, MOFRESOURCENAME);

    UNREFERENCED_PARAMETER(DeviceContext);

    PAGED_CODE();

    status = WdfDeviceAssignMofResourceName(Device, &mofRsrcName);
    if (!NT_SUCCESS(status)) {
        KdPrint(("FireFly: Error in WdfDeviceAssignMofResourceName %x\n", status));
        return status;
    }

    WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &FireflyDeviceInformation_GUID);
    providerConfig.MinInstanceBufferSize = sizeof(FireflyDeviceInformation);

    WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig);
    instanceConfig.Register = TRUE;
    instanceConfig.EvtWmiInstanceQueryInstance = EvtWmiInstanceQueryInstance;
    instanceConfig.EvtWmiInstanceSetInstance = EvtWmiInstanceSetInstance;
    instanceConfig.EvtWmiInstanceSetItem = EvtWmiInstanceSetItem;

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, FireflyDeviceInformation);

    //
    // No need to store the WDFWMIINSTANCE in the device context because it is
    // passed back in the WMI instance callbacks and is not referenced outside
    // of those callbacks.
    //
    status = WdfWmiInstanceCreate(Device, &instanceConfig, &woa, &instance);

    if (NT_SUCCESS(status)) {
        FireflyDeviceInformation* info;

        info = InstanceGetInfo(instance);
        info->TailLit = TRUE;
    }

    return status;
}
NTSTATUS
TLInspectLoadConfig(
   _In_ const WDFKEY key
   )
{
   NTSTATUS status;
   DECLARE_CONST_UNICODE_STRING(valueName, L"RemoteAddressToInspect");
   DECLARE_UNICODE_STRING_SIZE(value, INET6_ADDRSTRLEN);
   
   status = WdfRegistryQueryUnicodeString(key, &valueName, NULL, &value);

   if (NT_SUCCESS(status))
   {
      PWSTR terminator;
      // Defensively null-terminate the string
      value.Length = min(value.Length, value.MaximumLength - sizeof(WCHAR));
      value.Buffer[value.Length/sizeof(WCHAR)] = UNICODE_NULL;

      status = RtlIpv4StringToAddressW(
                  value.Buffer,
                  TRUE,
                  &terminator,
                  &remoteAddrStorageV4
                  );

      if (NT_SUCCESS(status))
      {
         remoteAddrStorageV4.S_un.S_addr = 
            RtlUlongByteSwap(remoteAddrStorageV4.S_un.S_addr);
         configInspectRemoteAddrV4 = &remoteAddrStorageV4.S_un.S_un_b.s_b1;
      }
      else
      {
         status = RtlIpv6StringToAddressW(
                     value.Buffer,
                     &terminator,
                     &remoteAddrStorageV6
                     );

         if (NT_SUCCESS(status))
         {
            configInspectRemoteAddrV6 = (UINT8*)(&remoteAddrStorageV6.u.Byte[0]);
         }
      }
   }

   return status;
}
Example #10
0
NTSTATUS
DeviceWriteLegacyHardwareKey(
    _In_  PWSTR             PdoName,
    _In_  PWSTR             ComPort,
    _In_  WDFDEVICE         Device
    )
{
    WDFKEY                  key = NULL;
    NTSTATUS                status;
    UNICODE_STRING          pdoString = {0};
    UNICODE_STRING          comPort = {0};
    
    DECLARE_CONST_UNICODE_STRING(deviceSubkey, SERIAL_DEVICE_MAP);
                
    RtlInitUnicodeString(&pdoString, PdoName);  
    RtlInitUnicodeString(&comPort, ComPort);
   
    status = WdfDeviceOpenDevicemapKey(Device,
                                       &deviceSubkey,
                                       KEY_SET_VALUE,
                                       WDF_NO_OBJECT_ATTRIBUTES,
                                       &key);
    if (!NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
            "Error: Failed to open DEVICEMAP\\SERIALCOMM key 0x%x", status);
        goto exit;
    }
    
    status = WdfRegistryAssignUnicodeString(key,
                                            &pdoString,
                                            &comPort);
                                            
    if (!NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
            "Error: Failed to write to DEVICEMAP\\SERIALCOMM key 0x%x", status);
        goto exit;
    }                                 

exit:

    if (key != NULL) {
        WdfRegistryClose(key);
        key = NULL;
    }

    return status;
}
Example #11
0
void otPlatSettingsInit(otInstance *otCtx)
{
    NT_ASSERT(otCtx);
    PMS_FILTER pFilter = otCtxToFilter(otCtx);

    DECLARE_CONST_UNICODE_STRING(SubKeyName, L"OpenThread");

    OBJECT_ATTRIBUTES attributes;
    ULONG disposition;

    LogFuncEntry(DRIVER_DEFAULT);

    InitializeObjectAttributes(
        &attributes,
        (PUNICODE_STRING)&SubKeyName,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        pFilter->InterfaceRegKey,
        NULL);

    // Create/Open the 'OpenThread' sub key
    NTSTATUS status =
        ZwCreateKey(
            &pFilter->otSettingsRegKey,
            KEY_ALL_ACCESS,
            &attributes,
            0,
            NULL,
            REG_OPTION_NON_VOLATILE,
            &disposition);

    NT_ASSERT(NT_SUCCESS(status));
    if (!NT_SUCCESS(status))
    {
        LogError(DRIVER_DEFAULT, "ZwCreateKey for 'OpenThread' key failed, %!STATUS!", status);
    }

    LogFuncExit(DRIVER_DEFAULT);
}
Example #12
0
NTSTATUS
RamDiskEvtDeviceAdd(
    IN WDFDRIVER Driver,
    IN PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    WDF_OBJECT_ATTRIBUTES   deviceAttributes;
    NTSTATUS                status;
    WDFDEVICE               device;
    WDF_OBJECT_ATTRIBUTES   queueAttributes;
    WDF_IO_QUEUE_CONFIG     ioQueueConfig;
    PDEVICE_EXTENSION       pDeviceExtension;
    PQUEUE_EXTENSION        pQueueContext = NULL;
    WDFQUEUE                queue;
    DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME);

    PAGED_CODE();

    UNREFERENCED_PARAMETER(Driver);

    //
    // Storage drivers have to name their FDOs. Since we are not unique'fying
    // the device name, we wouldn't be able to install more than one instance
    // of this ramdisk driver.
    //
    status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK);
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
    WdfDeviceInitSetExclusive(DeviceInit, FALSE);

    //
    // Since this is a pure software only driver, there is no need to register
    // any PNP/Power event callbacks. Framework will respond to these
    // events appropriately.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION);
    deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup;

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Now that the WDF device object has been created, set up any context
    // that it requires.
    //

    pDeviceExtension = DeviceGetExtension(device);

    //
    // Configure a default queue so that requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
    // other queues get dispatched here.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (
        &ioQueueConfig,
        WdfIoQueueDispatchSequential
        );

    ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl;
    ioQueueConfig.EvtIoRead          = RamDiskEvtIoRead;
    ioQueueConfig.EvtIoWrite         = RamDiskEvtIoWrite;

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION);

    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests or 
    // forward them to other drivers. This driver completes the requests 
    // directly in the queue's handlers. If the EvtIoStop callback is not 
    // implemented, the framework waits for all driver-owned requests to be
    // done before moving in the Dx/sleep states or before removing the 
    // device, which is the correct behavior for this type of driver.
    // If the requests were taking an indeterminate amount of time to complete,
    // or if the driver forwarded the requests to a lower driver/another stack,
    // the queue should have an EvtIoStop/EvtIoResume.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate( device,
                               &ioQueueConfig,
                               &queueAttributes,
                               &queue );
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if (!NT_SUCCESS(status)) {
        return status;
    }

     // Context is the Queue handle
    pQueueContext = QueueGetExtension(queue);

    //
    // Set the context for our default queue as our device extension.
    //
    pQueueContext->DeviceExtension = pDeviceExtension;

#if KMDF_VERSION_MINOR >= 9

    //
    // Enable forward progress on the queue we just created.
    // NOTE: If you are planning to use this code without forward progress,
    // comment out the call to SetForwardProgressOnQueue below. 
    //
    status = SetForwardProgressOnQueue(queue);
    if (!NT_SUCCESS(status)) {
        return status;
    }

#endif

    //
    // Now do any RAM-Disk specific initialization
    //
    pDeviceExtension->DiskRegInfo.DriveLetter.Buffer =
        (PWSTR) &pDeviceExtension->DriveLetterBuffer;
    pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength =
        sizeof(pDeviceExtension->DriveLetterBuffer);

    //
    // Get the disk parameters from the registry
    //
    RamDiskQueryDiskRegParameters(
        WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)),
        &pDeviceExtension->DiskRegInfo
        );

    //
    // Allocate memory for the disk image.
    //
    pDeviceExtension->DiskImage = ExAllocatePoolWithTag(
        NonPagedPool,
        pDeviceExtension->DiskRegInfo.DiskSize,
        RAMDISK_TAG
        );

    if (pDeviceExtension->DiskImage) {

        UNICODE_STRING deviceName;
        UNICODE_STRING win32Name;

        RamDiskFormatDisk(pDeviceExtension);

        status = STATUS_SUCCESS;

        //
        // Now try to create a symbolic link for the drive letter.
        //
        RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME);
        RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME);

        pDeviceExtension->SymbolicLink.Buffer = (PWSTR)
            &pDeviceExtension->DosDeviceNameBuffer;
        pDeviceExtension->SymbolicLink.MaximumLength =
            sizeof(pDeviceExtension->DosDeviceNameBuffer);
        pDeviceExtension->SymbolicLink.Length = win32Name.Length;

        RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name);
        RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink,
                                       &pDeviceExtension->DiskRegInfo.DriveLetter);

        status = WdfDeviceCreateSymbolicLink(device,
                                             &pDeviceExtension->SymbolicLink);
    }

    return status;
}
NTSTATUS
VIOSerialDeviceListCreatePdo(
    IN WDFCHILDLIST DeviceList,
    IN PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
    IN PWDFDEVICE_INIT ChildInit
    )
{
    PVIOSERIAL_PORT                 pport = NULL;
    NTSTATUS                        status = STATUS_SUCCESS;

    WDFDEVICE                       hChild = NULL;

    WDF_OBJECT_ATTRIBUTES           attributes;
    WDF_PNPPOWER_EVENT_CALLBACKS    PnpPowerCallbacks;
    WDF_DEVICE_PNP_CAPABILITIES     pnpCaps;
    WDF_DEVICE_STATE                deviceState;
    WDF_IO_QUEUE_CONFIG             queueConfig;
    PRAWPDO_VIOSERIAL_PORT          rawPdo = NULL;
    WDF_FILEOBJECT_CONFIG           fileConfig;

    DECLARE_CONST_UNICODE_STRING(deviceId, PORT_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"RedHat VIOSerial Port" );

    DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH);

    UNREFERENCED_PARAMETER(DeviceList);
    PAGED_CODE();

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

    pport = CONTAINING_RECORD(IdentificationDescription,
                                 VIOSERIAL_PORT,
                                 Header
                                 );

    WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_SERIAL_PORT);
    WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);

    do
    {
        WdfDeviceInitSetExclusive(ChildInit, TRUE);
        status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_PORT_DEVICE);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignRawDevice failed - 0x%x\n", status);
           break;
        }

        status = WdfDeviceInitAssignSDDLString(ChildInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceInitAssignSDDLString failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignDeviceID failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAddHardwareID(ChildInit, &deviceId);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAddHardwareID failed - 0x%x\n", status);
           break;
        }

        status = RtlUnicodeStringPrintf(
                                 &buffer,
                                 L"%02u",
                                 pport->PortId
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignInstanceID failed - 0x%x\n", status);
           break;
        }

        status = RtlUnicodeStringPrintf(
                                 &buffer,
                                 L"vport%up%u",
                                 pport->DeviceId,
                                 pport->PortId
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "RtlUnicodeStringPrintf failed 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAddDeviceText(
                                 ChildInit,
                                 &buffer,
                                 &deviceLocation,
                                 0x409
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfPdoInitAddDeviceText failed 0x%x\n", status);
           break;
        }

        WdfPdoInitSetDefaultLocale(ChildInit, 0x409);

        WDF_FILEOBJECT_CONFIG_INIT(
                                 &fileConfig,
                                 VIOSerialPortCreate,
                                 VIOSerialPortClose,
                                 WDF_NO_EVENT_CALLBACK
                                 );

        WdfDeviceInitSetFileObjectConfig(
                                 ChildInit,
                                 &fileConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES
                                 );

        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
        PnpPowerCallbacks.EvtDeviceD0Entry = VIOSerialPortEvtDeviceD0Entry;
        PnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = VIOSerialPortEvtDeviceD0ExitPreInterruptsDisabled;
        PnpPowerCallbacks.EvtDeviceD0Exit = VIOSerialPortEvtDeviceD0Exit;
        WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks);

        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT);
        attributes.SynchronizationScope = WdfSynchronizationScopeDevice;
        attributes.ExecutionLevel = WdfExecutionLevelPassive;

        status = WdfDeviceCreate(
                                 &ChildInit,
                                 &attributes,
                                 &hChild
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceCreate failed 0x%x\n", status);
           break;
        }

        rawPdo = RawPdoSerialPortGetData(hChild);
        rawPdo->port = pport;
        pport->Device = hChild;

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                                 WdfIoQueueDispatchSequential
                                 );

        queueConfig.EvtIoDeviceControl = VIOSerialPortDeviceControl;
        status = WdfIoQueueCreate(hChild,
                                 &queueConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &pport->IoctlQueue
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate failed (IoCtrl Queue): 0x%x\n", status);
           break;
        }
        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->IoctlQueue,
                                 WdfRequestTypeDeviceControl
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (IoCtrl Queue): 0x%x\n", status);
           break;
        }

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                                 WdfIoQueueDispatchSequential);

        queueConfig.EvtIoRead   =  VIOSerialPortRead;
        queueConfig.EvtIoStop   =  VIOSerialPortIoStop;
        status = WdfIoQueueCreate(hChild,
                                 &queueConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &pport->ReadQueue
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate (Read Queue) failed 0x%x\n", status);
           break;
        }

        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->ReadQueue,
                                 WdfRequestTypeRead
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (Read Queue): 0x%x\n", status);
           break;
        }

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);
        queueConfig.AllowZeroLengthRequests = WdfFalse;
        queueConfig.EvtIoWrite = VIOSerialPortWrite;

        status = WdfIoQueueCreate(hChild, &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES, &pport->WriteQueue);

        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate failed (Write Queue): 0x%x\n", status);
           break;
        }
        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->WriteQueue,
                                 WdfRequestTypeWrite
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (Write Queue): 0x%x\n", status);
           break;
        }

        WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

        pnpCaps.NoDisplayInUI    =  WdfTrue;
        pnpCaps.Removable        =  WdfTrue;
        pnpCaps.EjectSupported   =  WdfTrue;
        pnpCaps.SurpriseRemovalOK=  WdfTrue;
        pnpCaps.Address          =  pport->DeviceId;
        pnpCaps.UINumber         =  pport->PortId;

        WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);

        WDF_DEVICE_STATE_INIT(&deviceState);
        deviceState.DontDisplayInUI = WdfTrue;
        WdfDeviceSetDeviceState(hChild, &deviceState);

        status = WdfDeviceCreateDeviceInterface(
                                 hChild,
                                 &GUID_VIOSERIAL_PORT,
                                 NULL
                                 );

        if (!NT_SUCCESS (status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceCreateDeviceInterface failed 0x%x\n", status);
           break;
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = hChild;
        status = WdfSpinLockCreate(
                                &attributes,
                                &pport->InBufLock
                                );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfSpinLockCreate failed 0x%x\n", status);
           break;
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = hChild;
        status = WdfSpinLockCreate(
                                &attributes,
                                &pport->OutVqLock
                                );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfSpinLockCreate failed 0x%x\n", status);
           break;
        }

    } while (0);

    if (!NT_SUCCESS(status))
    {
        // We can send this before PDO is PRESENT since the device won't send any response.
        VIOSerialSendCtrlMsg(pport->BusDevice, pport->PortId, VIRTIO_CONSOLE_PORT_READY, 0);
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s status 0x%x\n", __FUNCTION__, status);
    return status;
}
Example #14
0
NTSTATUS
OsrEvtDeviceListCreatePdo(
    WDFCHILDLIST DeviceList,
    PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
    PWDFDEVICE_INIT ChildInit
    )
/*++

Routine Description:

    Called by the framework in response to Query-Device relation when
    a new PDO for a child device needs to be created.

Arguments:

    DeviceList - Handle to the default WDFCHILDLIST created by the
                        framework as part of FDO.

    IdentificationDescription - Decription of the new child device.

    ChildInit - It's a opaque structure used in collecting device settings
                    and passed in as a parameter to CreateDevice.

Return Value:

    NT Status code.

--*/
{
    NTSTATUS                        status;
    WDFDEVICE                       hChild = NULL;
    PPDO_IDENTIFICATION_DESCRIPTION pDesc;
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
    DECLARE_CONST_UNICODE_STRING(deviceId, OSRUSBFX2_SWITCH_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(hardwareId, OSRUSBFX2_SWITCH_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"OSR USB-FX2 Learning Kit" );
    DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH);

    UNREFERENCED_PARAMETER(DeviceList);

    pDesc = CONTAINING_RECORD(IdentificationDescription,
                              PDO_IDENTIFICATION_DESCRIPTION,
                              Header);

    //
    // Mark the device RAW so that the child device can be started
    // and accessed without requiring a function driver. Since we are
    // creating a RAW PDO, we must provide a class guid.
    //
    status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_OSRUSBFX2);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Since our devices for switches can trigger nuclear explosion,
    // we must protect them from random users sending I/Os.
    //
    status = WdfDeviceInitAssignSDDLString(ChildInit,
                                           &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // On XP and later, there is no need to provide following IDs for raw pdos.
    // BusQueryHardwareIDs but on On Win2K, we must provide a HWID and a NULL
    // section in the INF to get the device installed without any problem.
    //
    status = WdfPdoInitAddHardwareID(ChildInit, &hardwareId);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Since we are enumerating more than one children, we must
    // provide a BusQueryInstanceID. If we don't, system will throw
    // CA bugcheck.
    //
    status =  RtlUnicodeStringPrintf(&buffer, L"%02d", pDesc->SwitchNumber);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Provide a description about the device. This text is usually read from
    // the device. In the case of USB device, this text comes from the string
    // descriptor. This text is displayed momentarily by the PnP manager while
    // it's looking for a matching INF. If it finds one, it uses the Device
    // Description from the INF file to display in the device manager.
    // Since our device is raw device and we don't provide any hardware ID
    // to match with an INF, this text will be displayed in the device manager.
    //
    status = RtlUnicodeStringPrintf(&buffer,
                                    L"OsrUsbFX2 RawPdo For Switch %02d",
                                    pDesc->SwitchNumber);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // You can call WdfPdoInitAddDeviceText multiple times, adding device
    // text for multiple locales. When the system displays the text, it
    // chooses the text that matches the current locale, if available.
    // Otherwise it will use the string for the default locale.
    // The driver can specify the driver's default locale by calling
    // WdfPdoInitSetDefaultLocale.
    //
    status = WdfPdoInitAddDeviceText(ChildInit,
                                        &buffer,
                                        &deviceLocation,
                                        0x409);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    WdfPdoInitSetDefaultLocale(ChildInit, 0x409);

    status = WdfDeviceCreate(&ChildInit, WDF_NO_OBJECT_ATTRIBUTES, &hChild);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;

    }

    //
    // Set idle-time out on the child device. This is required to allow
    // the parent device to idle-out when there are no active I/O.
    //
    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0);
    idleSettings.IdleTimeout = 1000; // 1-sec

    status = WdfDeviceAssignS0IdleSettings(hChild, &idleSettings);
    if ( !NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);
        return status;
    }

    return status;

Cleanup:

    TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"CreatePdo failed %x\n", status);

    //
    // On error, framework will cleanup all the resources when it deletes
    // the device. So there is nothing to do.
    //

    return status;
}
Example #15
0
NTSTATUS
DeviceConfigure(
    _In_  PDEVICE_CONTEXT   DeviceContext
    )
/*++

  Routine Description:

    This method is called after the device callback object has been initialized
    and returned to the driver.  It would setup the device's queues and their
    corresponding callback objects.

  Arguments:

    FxDevice - the framework device object for which we're handling events.

  Return Value:

    status

--*/
{
    NTSTATUS                status;
    WDFDEVICE               device = DeviceContext->Device;
    WDFKEY                  key;
    LPGUID                  guid;
    errno_t                 errorNo;
    
    DECLARE_CONST_UNICODE_STRING(portName,          REG_VALUENAME_PORTNAME);
    DECLARE_UNICODE_STRING_SIZE (comPort,           10);
    DECLARE_UNICODE_STRING_SIZE (symbolicLinkName,  SYMBOLIC_LINK_NAME_LENGTH);

#ifdef _FAKE_MODEM
    //
    // Compiled as fake modem
    //
    guid = (LPGUID) &GUID_DEVINTERFACE_MODEM;
#else
    //
    // Compiled as virtual serial port
    //
    guid = (LPGUID) &GUID_DEVINTERFACE_COMPORT;
#endif

    //
    // Create device interface
    //
    status = WdfDeviceCreateDeviceInterface(
                            device,
                            guid,
                            NULL);
    if (!NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
            "Error: Cannot create device interface");
        goto Exit;
    }

    //
    // Read the COM port number from the registry, which has been automatically
    // created by "MsPorts!PortsClassInstaller" if INF file says "Class=Ports"
    //
    status = WdfDeviceOpenRegistryKey(
                            device,
                            PLUGPLAY_REGKEY_DEVICE,
                            KEY_QUERY_VALUE,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &key);
    if (!NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
            "Error: Failed to retrieve device hardware key root");
        goto Exit;
    }

    status = WdfRegistryQueryUnicodeString(
                            key,
                            &portName,
                            NULL,
                            &comPort);
    if (!NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
            "Error: Failed to read PortName");
        goto Exit;
    }
        
    //
    // Manually create the symbolic link name. Length is the length in
    // bytes not including the NULL terminator.
    //
    // 6054 and 26035 are code analysis warnings that comPort.Buffer might
    // not be NULL terminated, while we know that they are. 
    //
    #pragma warning(suppress: 6054 26035)
    symbolicLinkName.Length = (USHORT)((wcslen(comPort.Buffer) * sizeof(wchar_t))
                                + sizeof(SYMBOLIC_LINK_NAME_PREFIX) - sizeof(UNICODE_NULL));
                                
    if (symbolicLinkName.Length >= symbolicLinkName.MaximumLength) {
        
        Trace(TRACE_LEVEL_ERROR, "Error: Buffer overflow when creating COM port name. Size"
            " is %d, buffer length is %d", symbolicLinkName.Length, symbolicLinkName.MaximumLength);
        status = STATUS_BUFFER_OVERFLOW;
        goto Exit;
    }
        
    errorNo = wcscpy_s(symbolicLinkName.Buffer,
                       SYMBOLIC_LINK_NAME_LENGTH,
                       SYMBOLIC_LINK_NAME_PREFIX);
                           
    if (errorNo != 0) {
        Trace(TRACE_LEVEL_ERROR, 
              "Failed to copy %ws to buffer with error %d",
              SYMBOLIC_LINK_NAME_PREFIX, errorNo);
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }
        
    errorNo = wcscat_s(symbolicLinkName.Buffer,
                       SYMBOLIC_LINK_NAME_LENGTH,
                       comPort.Buffer);
                           
    if (errorNo != 0) {
        Trace(TRACE_LEVEL_ERROR, 
              "Failed to copy %ws to buffer with error %d",
              comPort.Buffer, errorNo);
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }
                                
    //
    // Create symbolic link
    //
    status = WdfDeviceCreateSymbolicLink(
                            device,
                            &symbolicLinkName);
    if (!NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR,
            "Error: Cannot create symbolic link %ws", symbolicLinkName.Buffer);
        goto Exit;
    }

    status = DeviceGetPdoName(DeviceContext);
    if (!NT_SUCCESS(status)) {
        goto Exit;
    }

    status = DeviceWriteLegacyHardwareKey(
                            DeviceContext->PdoName,
                            comPort.Buffer,
                            DeviceContext->Device);
    if (NT_SUCCESS(status)) {
        DeviceContext->CreatedLegacyHardwareKey = TRUE;
    }

    status = QueueCreate(DeviceContext);
    if (!NT_SUCCESS(status)) {
        goto Exit;
    }

Exit:
    return status;
}
VOID
FX_DRIVER_GLOBALS::RegisterClientVersion(
    _In_ PCUNICODE_STRING ServiceKeyName
    )
{
    FxAutoRegKey hDriver, hParameters, hWdf;
    DECLARE_CONST_UNICODE_STRING(parametersPart, L"Parameters");
    DECLARE_CONST_UNICODE_STRING(wdfPart, L"Wdf");
    //
    //  Not defined with the macro because ZwSetValue doesn't use PCUNICODE_STRING
    //
    UNICODE_STRING wdfMajorValue;
    UNICODE_STRING wdfMinorValue;
    NTSTATUS status;
    
    RtlInitUnicodeString(&wdfMajorValue, WDF_MAJOR_VERSION_VALUE);
    RtlInitUnicodeString(&wdfMinorValue, WDF_MINOR_VERSION_VALUE);

    status = FxRegKey::_OpenKey(NULL, 
                                ServiceKeyName, 
                                &hDriver.m_Key, 
                                KEY_WRITE | KEY_READ
                                );
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 
            "Unable to open driver's service key, status %!STATUS!", status);
        return;
    }
    //
    //  Key creation, unlike user mode, must happen one level at a time, since
    //  create will also open take both steps instead of trying open first
    //
    status = FxRegKey::_Create(hDriver.m_Key, 
                               &parametersPart, 
                               &hParameters.m_Key, 
                               KEY_WRITE | KEY_READ
                               );
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 
            "Unable to write Parameters key, status %!STATUS!", status);
        return;
    }

    status = FxRegKey::_Create(hParameters.m_Key, 
                               &wdfPart, 
                               &hWdf.m_Key, 
                               KEY_WRITE | KEY_READ
                               );
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 
            "Unable to write Parameters key, status %!STATUS!", status);
        return;
    }

    //
    //  Using ZwSetValueKey here to avoid having to change the implementation
    //  in FxRegKey of SetValue to a static / thiscall pair
    //
    status = ZwSetValueKey(hWdf.m_Key, 
                           &wdfMajorValue, 
                           0, 
                           REG_DWORD, 
                           &WdfBindInfo->Version.Major, 
                           sizeof(WdfBindInfo->Version.Major)
                           );

    if  (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 
            "Failed to record driver major version value, status %!STATUS!", status);
    }

    status = ZwSetValueKey(hWdf.m_Key, 
                           &wdfMinorValue, 
                           0, 
                           REG_DWORD, 
                           &WdfBindInfo->Version.Minor, 
                           sizeof(WdfBindInfo->Version.Minor)
                           );

    if  (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, 
            "Failed to record driver version value, status %!STATUS!", status);
    }
}
Example #17
0
NTSTATUS
vJoy_CreateRawPdo(
    WDFDEVICE       Device,
    ULONG           InstanceNo
    )
/*++

Routine Description:

    This routine creates and initialize a PDO.

Arguments:

Return Value:

    NT Status code.

--*/
{   
    NTSTATUS                    status;
    PWDFDEVICE_INIT             pDeviceInit = NULL;
    PRPDO_DEVICE_DATA           pdoData = NULL;
    WDFDEVICE                   hChild = NULL;
    WDF_OBJECT_ATTRIBUTES       pdoAttributes;
    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
    WDF_IO_QUEUE_CONFIG         ioQueueConfig;
    WDFQUEUE                    queue;
    WDF_DEVICE_STATE            deviceState;
    PDEVICE_EXTENSION			devExt;
    DECLARE_CONST_UNICODE_STRING(deviceId,VJOY_RAW_DEVICE_ID );
    //DECLARE_CONST_UNICODE_STRING(hardwareId,VJOY_HARDWARE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation,L"vJoy Raw Device\0" );
    DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);
	PDEVICE_OBJECT				ChildDeviceObject;
	PDEVICE_OBJECT				ParentDeviceObject;
	DECLARE_CONST_UNICODE_STRING(
		SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_R_RES_R,
		L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GR;;;WD)(A;;GR;;;RC)"
		);
	DECLARE_CONST_UNICODE_STRING(
		SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R,
		L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GR;;;RC)"
		);

	int iInterface;
	WCHAR RefStr[20];
	UNICODE_STRING RefStr2;
	WDF_FILEOBJECT_CONFIG FileObjInit;
	WDF_OBJECT_ATTRIBUTES       FileObjAttributes;

	WDF_OBJECT_ATTRIBUTES		LockAttributes;


	TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_CreateRawPdo\n");


    //
    // Allocate a WDFDEVICE_INIT structure and set the properties
    // so that we can create a device object for the child.
    //
    pDeviceInit = WdfPdoInitAllocate(Device);

    if (pDeviceInit == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAllocate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }


    //
    // Mark the device RAW so that the child device can be started
    // and accessed without requiring a function driver. Since we are
    // creating a RAW PDO, we must provide a class guid.
    //
    status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVINTERFACE_VJOY);
    if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignRawDevice", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

	// TODO: Assign correct SDDL
    ////
    status = WdfDeviceInitAssignSDDLString(pDeviceInit,
                                           &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R);
    if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceInitAssignSDDLString", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }


    //
    // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID
    //
    status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);
    if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignDeviceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }


    //
    // We could be enumerating more than one children if the filter attaches
    // to multiple instances of keyboard, so we must provide a
    // BusQueryInstanceID. If we don't, system will throw CA bugcheck.
    //
    status =  RtlUnicodeStringPrintf(&buffer, VJOY_DEVICE_INSTANCE, InstanceNo);
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
       goto Cleanup;
    }

    status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignInstanceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // Provide a description about the device. This text is usually read from
    // the device. This text is displayed momentarily by the PnP manager while
    // it's looking for a matching INF. If it finds one, it uses the Device
    // Description from the INF file to display in the device manager.
    // Since our device is raw device and we don't provide any hardware ID
    // to match with an INF, this text will be displayed in the device manager.
    //
    status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_409 ); // English - United States
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // You can call WdfPdoInitAddDeviceText multiple times, adding device
    // text for multiple locales. When the system displays the text, it
    // chooses the text that matches the current locale, if available.
    // Otherwise it will use the string for the default locale.
    // The driver can specify the driver's default locale by calling
    // WdfPdoInitSetDefaultLocale.
    //
    status = WdfPdoInitAddDeviceText(pDeviceInit,
                                        &buffer,
                                        &deviceLocation,
                                        0x409 // English - United States
                                        );
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

#if 0
	// Hebrew (No real ned - just for fun)
	status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_40D, InstanceNo ); // Hebrew
	if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (3)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
		goto Cleanup;
	}

	status = WdfPdoInitAddDeviceText(pDeviceInit,
		&buffer,
		&deviceLocation,
		0x40D // Hebrew
		);
	if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
		goto Cleanup;
	}

#endif // 0


    WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); // English - United States

	WdfDeviceInitSetExclusive(pDeviceInit, FALSE);
	
	// Create a WDFFILEOBJECT
	WDF_OBJECT_ATTRIBUTES_INIT(&FileObjAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&FileObjAttributes, FILEOBJECT_EXTENSION);
	WDF_FILEOBJECT_CONFIG_INIT(&FileObjInit,  vJoy_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, vJoy_EvtFileCleanup);
	WdfDeviceInitSetFileObjectConfig(pDeviceInit, &FileObjInit, &FileObjAttributes);

    
    //
    // Initialize the attributes to specify the size of PDO device extension.
    // All the state information private to the PDO will be tracked here.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA);
	pdoAttributes.EvtCleanupCallback = rawEvtCleanupCallback;

    //
    // Set up our queue to allow forwarding of requests to the parent
    // This is done so that the cached data can be retrieved
    //
    //WdfPdoInitAllowForwardingRequestToParent(pDeviceInit);
	// TODO: Replace the above because it is needed for WdfRequestForwardToParentDeviceIoQueue()

    status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);
    if (!NT_SUCCESS(status)) {
  		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // Get the device context.
    //
    pdoData = PdoGetData(hChild);
	pdoData->InstanceNo = InstanceNo;
	pdoData->hParentDevice = Device;

    //
    // Save the I/O target handle and adjust the I/O stack size:
    //
    devExt = GetDeviceContext(Device);
    pdoData->IoTargetToParent = devExt->IoTargetToSelf;
	ChildDeviceObject = WdfDeviceWdmGetDeviceObject(hChild);
	ParentDeviceObject = WdfDeviceWdmGetDeviceObject(Device);
	ChildDeviceObject->StackSize = ParentDeviceObject->StackSize+1;

	// Create a wait-lock object that will be used to synch access to positions[i]
	// The lock is created when the raw device is created so the raw device is set to be its parent
	WDF_OBJECT_ATTRIBUTES_INIT(&LockAttributes);
	LockAttributes.ParentObject = hChild;
	status =  WdfWaitLockCreate(&LockAttributes, &(devExt->positionLock));
    if (!NT_SUCCESS(status)) {
		TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfWaitLockCreate failed 0x%x\n", status);
  		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfWaitLockCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // Configure the default queue associated with the control device object
    // to be Serial so that request passed to EvtIoDeviceControl are serialized.
    // A default queue gets all the requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching.
    //

    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                    WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoDeviceControl = vJoy_EvtIoDeviceControlForRawPdo;

    status = WdfIoQueueCreate(hChild,
                                        &ioQueueConfig,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &queue // pointer to default queue
                                        );
    if (!NT_SUCCESS(status)) {
		TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed 0x%x\n", status);
   		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfIoQueueCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
       goto Cleanup;
    }

    //
    // Set some properties for the child device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

    pnpCaps.Removable         = WdfTrue; // Remove Icon from " Devices and Printers"
    pnpCaps.SurpriseRemovalOK = WdfTrue;
    pnpCaps.NoDisplayInUI     = WdfTrue;

    // pnpCaps.Address  = InstanceNo;
    pnpCaps.UINumber = 0;

    WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);

    //
    // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we
    // have to do the following to hide the device. Following call
    // tells the framework to report the device state in
    // IRP_MN_QUERY_DEVICE_STATE request.
    //
    WDF_DEVICE_STATE_INIT(&deviceState);
    deviceState.DontDisplayInUI = WdfTrue; // Remove Icon from Device manager
    WdfDeviceSetDeviceState(hChild, &deviceState);

	//
	// Create 16 interfaces
	//
	for (iInterface=1 ; iInterface <= MAX_N_DEVICES; iInterface++)
	{
		RtlStringCchPrintfW((NTSTRSAFE_PWSTR)RefStr, 20, VJOY_INTERFACE L"%03d", iInterface);
		RtlInitUnicodeString(&RefStr2, (PCWSTR)RefStr);
		status = WdfDeviceCreateDeviceInterface(hChild,&GUID_DEVINTERFACE_VJOY,&RefStr2);

		if (!NT_SUCCESS (status)) {
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateDeviceInterface number %d failed 0x%x\n", iInterface, status);
   			LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreateDeviceInterface", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
			goto Cleanup;
		}
	};

	// Mark all interfaces as unused
	pdoData->UsedInterfacesMask=0;


	//
	// Add this device to the FDO's collection of children.
    // After the child device is added to the static collection successfully,
    // driver must call WdfPdoMarkMissing to get the device deleted. It
    // shouldn't delete the child device directly by calling WdfObjectDelete.
    //
    status = WdfFdoAddStaticChild(Device, hChild);
    if (!NT_SUCCESS(status)) {
   		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfFdoAddStaticChild", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    return STATUS_SUCCESS;

Cleanup:

    TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "KbFiltr_CreatePdo failed %x\n", status);
    //
    // Call WdfDeviceInitFree if you encounter an error while initializing
    // a new framework device object. If you call WdfDeviceInitFree,
    // do not call WdfDeviceCreate.
    //
    if (pDeviceInit != NULL) {
        WdfDeviceInitFree(pDeviceInit);
    }

    if(hChild) {
        WdfObjectDelete(hChild);
    }

    return status;
}
Example #18
0
NTSTATUS
NonPnpDeviceAdd(
    IN WDFDRIVER Driver,
    IN PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    Called by the DriverEntry to create a control-device. This call is
    responsible for freeing the memory for DeviceInit.

Arguments:

    DriverObject - a pointer to the object that represents this device
    driver.

    DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure.

Return Value:

    STATUS_SUCCESS if initialized; an error otherwise.

--*/
{
    NTSTATUS                       status;
    WDF_OBJECT_ATTRIBUTES           attributes;
    WDF_IO_QUEUE_CONFIG      ioQueueConfig;
    WDF_FILEOBJECT_CONFIG fileConfig;
    WDFQUEUE                            queue;
    WDFDEVICE   controlDevice;
    DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ;
    DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ;

    UNREFERENCED_PARAMETER( Driver );

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
                   "NonPnpDeviceAdd DeviceInit %p\n", DeviceInit);
    //
    // Set exclusive to TRUE so that no more than one app can talk to the
    // control device at any time.
    //
    WdfDeviceInitSetExclusive(DeviceInit, TRUE);

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);


    status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName);

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceInitAssignName failed %!STATUS!", status);
        goto End;
    }

    WdfControlDeviceInitSetShutdownNotification(DeviceInit,
                                                NonPnpShutdown,
                                                WdfDeviceShutdown);

    //
    // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the
    // framework whether you are interested in handling Create, Close and
    // Cleanup requests that gets generated when an application or another
    // kernel component opens an handle to the device. If you don't register
    // the framework default behaviour would be to complete these requests
    // with STATUS_SUCCESS. A driver might be interested in registering these
    // events if it wants to do security validation and also wants to maintain
    // per handle (fileobject) context.
    //

    WDF_FILEOBJECT_CONFIG_INIT(
                        &fileConfig,
                        NonPnpEvtDeviceFileCreate,
                        NonPnpEvtFileClose,
                        WDF_NO_EVENT_CALLBACK // not interested in Cleanup
                        );

    WdfDeviceInitSetFileObjectConfig(DeviceInit,
                                       &fileConfig,
                                       WDF_NO_OBJECT_ATTRIBUTES);

    //
    // In order to support METHOD_NEITHER Device controls, or
    // NEITHER device I/O type, we need to register for the
    // EvtDeviceIoInProcessContext callback so that we can handle the request
    // in the calling threads context.
    //
    WdfDeviceInitSetIoInCallerContextCallback(DeviceInit,
                                    NonPnpEvtDeviceIoInCallerContext);

    //
    // Specify the size of device context
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
                                    CONTROL_DEVICE_EXTENSION);

    status = WdfDeviceCreate(&DeviceInit,
                             &attributes,
                             &controlDevice);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed %!STATUS!", status);
        goto End;
    }

    //
    // Create a symbolic link for the control object so that usermode can open
    // the device.
    //


    status = WdfDeviceCreateSymbolicLink(controlDevice,
                                &symbolicLinkName);

    if (!NT_SUCCESS(status)) {
        //
        // Control device will be deleted automatically by the framework.
        //
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed %!STATUS!", status);
        goto End;
    }

    //
    // Configure a default queue so that requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
    // other queues get dispatched here.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                    WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoRead = FileEvtIoRead;
    ioQueueConfig.EvtIoWrite = FileEvtIoWrite;
    ioQueueConfig.EvtIoDeviceControl = FileEvtIoDeviceControl;

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    //
    // Since we are using Zw function set execution level to passive so that
    // framework ensures that our Io callbacks called at only passive-level
    // even if the request came in at DISPATCH_LEVEL from another driver.
    //
    //attributes.ExecutionLevel = WdfExecutionLevelPassive;

    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests or 
    // forward them to other drivers. This driver completes the requests 
    // directly in the queue's handlers. If the EvtIoStop callback is not 
    // implemented, the framework waits for all driver-owned requests to be
    // done before moving in the Dx/sleep states or before removing the 
    // device, which is the correct behavior for this type of driver.
    // If the requests were taking an indeterminate amount of time to complete,
    // or if the driver forwarded the requests to a lower driver/another stack,
    // the queue should have an EvtIoStop/EvtIoResume.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate(controlDevice,
                              &ioQueueConfig,
                              &attributes,
                              &queue // pointer to default queue
                              );
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed %!STATUS!", status);
        goto End;
    }

    //
    // Control devices must notify WDF when they are done initializing.   I/O is
    // rejected until this call is made.
    //
    WdfControlFinishInitializing(controlDevice);

End:
    //
    // If the device is created successfully, framework would clear the
    // DeviceInit value. Otherwise device create must have failed so we
    // should free the memory ourself.
    //
    if (DeviceInit != NULL) {
        WdfDeviceInitFree(DeviceInit);
    }

    return status;

}
Example #19
0
NTSTATUS
KbFiltr_CreateRawPdo(
    WDFDEVICE       Device,
    ULONG           InstanceNo
    )
/*++

Routine Description:

    This routine creates and initialize a PDO.

Arguments:

Return Value:

    NT Status code.

--*/
{   
    NTSTATUS                    status;
    PWDFDEVICE_INIT             pDeviceInit = NULL;
    PRPDO_DEVICE_DATA           pdoData = NULL;
    WDFDEVICE                   hChild = NULL;
    WDF_OBJECT_ATTRIBUTES       pdoAttributes;
    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
    WDF_IO_QUEUE_CONFIG         ioQueueConfig;
    WDFQUEUE                    queue;
    WDF_DEVICE_STATE            deviceState;
    PDEVICE_EXTENSION           devExt;
    DECLARE_CONST_UNICODE_STRING(deviceId,KBFILTR_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(hardwareId,KBFILTR_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation,L"Keyboard Filter\0" );
    DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);

    DebugPrint(("Entered KbFiltr_CreateRawPdo\n"));

    //
    // Allocate a WDFDEVICE_INIT structure and set the properties
    // so that we can create a device object for the child.
    //
    pDeviceInit = WdfPdoInitAllocate(Device);

    if (pDeviceInit == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Cleanup;
    }

    //
    // Mark the device RAW so that the child device can be started
    // and accessed without requiring a function driver. Since we are
    // creating a RAW PDO, we must provide a class guid.
    //
    status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVCLASS_KEYBOARD);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Since keyboard is secure device, we must protect ourselves from random
    // users sending ioctls and creating trouble.
    //
    status = WdfDeviceInitAssignSDDLString(pDeviceInit,
                                           &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID
    //
    status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // For RAW PDO, there is no need to provide BusQueryHardwareIDs
    // and BusQueryCompatibleIDs IDs unless we are running on
    // Windows 2000.
    //
    if (!RtlIsNtDdiVersionAvailable(NTDDI_WINXP)) {
        //
        // On Win2K, we must provide a HWID for the device to get enumerated.
        // Since we are providing a HWID, we will have to provide a NULL inf
        // to avoid the "found new device" popup and get the device installed
        // silently.
        //
        status = WdfPdoInitAddHardwareID(pDeviceInit, &hardwareId);
        if (!NT_SUCCESS(status)) {
            goto Cleanup;
        }
    }

    //
    // We could be enumerating more than one children if the filter attaches
    // to multiple instances of keyboard, so we must provide a
    // BusQueryInstanceID. If we don't, system will throw CA bugcheck.
    //
    status =  RtlUnicodeStringPrintf(&buffer, L"%02d", InstanceNo);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Provide a description about the device. This text is usually read from
    // the device. In the case of USB device, this text comes from the string
    // descriptor. This text is displayed momentarily by the PnP manager while
    // it's looking for a matching INF. If it finds one, it uses the Device
    // Description from the INF file to display in the device manager.
    // Since our device is raw device and we don't provide any hardware ID
    // to match with an INF, this text will be displayed in the device manager.
    //
    status = RtlUnicodeStringPrintf(&buffer,L"Keyboard_Filter_%02d", InstanceNo );
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // You can call WdfPdoInitAddDeviceText multiple times, adding device
    // text for multiple locales. When the system displays the text, it
    // chooses the text that matches the current locale, if available.
    // Otherwise it will use the string for the default locale.
    // The driver can specify the driver's default locale by calling
    // WdfPdoInitSetDefaultLocale.
    //
    status = WdfPdoInitAddDeviceText(pDeviceInit,
                                        &buffer,
                                        &deviceLocation,
                                        0x409
                                        );
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409);
    
    //
    // Initialize the attributes to specify the size of PDO device extension.
    // All the state information private to the PDO will be tracked here.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA);

    //
    // Set up our queue to allow forwarding of requests to the parent
    // This is done so that the cached Keyboard Attributes can be retrieved
    //
    WdfPdoInitAllowForwardingRequestToParent(pDeviceInit);

    status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Get the device context.
    //
    pdoData = PdoGetData(hChild);

    pdoData->InstanceNo = InstanceNo;

    //
    // Get the parent queue we will be forwarding to
    //
    devExt = FilterGetData(Device);
    pdoData->ParentQueue = devExt->rawPdoQueue;

    //
    // Configure the default queue associated with the control device object
    // to be Serial so that request passed to EvtIoDeviceControl are serialized.
    // A default queue gets all the requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching.
    //

    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                    WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlForRawPdo;

    status = WdfIoQueueCreate(hChild,
                                        &ioQueueConfig,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &queue // pointer to default queue
                                        );
    if (!NT_SUCCESS(status)) {
        DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status));
        goto Cleanup;
    }

    //
    // Set some properties for the child device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

    pnpCaps.Removable         = WdfTrue;
    pnpCaps.SurpriseRemovalOK = WdfTrue;
    pnpCaps.NoDisplayInUI     = WdfTrue;

    pnpCaps.Address  = InstanceNo;
    pnpCaps.UINumber = InstanceNo;

    WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);

    //
    // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we
    // have to do the following to hide the device. Following call
    // tells the framework to report the device state in
    // IRP_MN_QUERY_DEVICE_STATE request.
    //
    WDF_DEVICE_STATE_INIT(&deviceState);
    deviceState.DontDisplayInUI = WdfTrue;
    WdfDeviceSetDeviceState(hChild, &deviceState);

    //
    // Tell the Framework that this device will need an interface so that
    // application can find our device and talk to it.
    //
    status = WdfDeviceCreateDeviceInterface(
                 hChild,
                 &GUID_DEVINTERFACE_KBFILTER,
                 NULL
             );

    if (!NT_SUCCESS (status)) {
        DebugPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status));
        goto Cleanup;
    }

    //
    // Add this device to the FDO's collection of children.
    // After the child device is added to the static collection successfully,
    // driver must call WdfPdoMarkMissing to get the device deleted. It
    // shouldn't delete the child device directly by calling WdfObjectDelete.
    //
    status = WdfFdoAddStaticChild(Device, hChild);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // pDeviceInit will be freed by WDF.
    //
    return STATUS_SUCCESS;

Cleanup:

    DebugPrint(("KbFiltr_CreatePdo failed %x\n", status));

    //
    // Call WdfDeviceInitFree if you encounter an error while initializing
    // a new framework device object. If you call WdfDeviceInitFree,
    // do not call WdfDeviceCreate.
    //
    if (pDeviceInit != NULL) {
        WdfDeviceInitFree(pDeviceInit);
    }

    if(hChild) {
        WdfObjectDelete(hChild);
    }

    return status;
}
NTSTATUS
XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
  PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
  PWDFDEVICE_INIT child_init) {
  NTSTATUS status = STATUS_SUCCESS;
  WDF_OBJECT_ATTRIBUTES child_attributes;
  WDFDEVICE child_device;
  PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
  WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
  DECLARE_UNICODE_STRING_SIZE(buffer, 512);
  DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
  PXENPCI_PDO_DEVICE_DATA xppdd;
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
  //WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
  WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
  //UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
  WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
  
  FUNCTION_ENTER();

  WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
  
  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
  child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
  child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
  child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
  WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);

  FUNCTION_MSG("device = '%s', index = '%d', path = '%s'\n",
    identification->device, identification->index, identification->path);
  
  //status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
  //  IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  //if (!NT_SUCCESS(status)) {
  //  return status;
  //}
  
  //WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
  //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
  //pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
  //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
  //pdo_callbacks.EvtDeviceSetLock  = XenPciPdo_EvtDeviceSetLock;
  //WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);

  RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
  status = WdfPdoInitAssignDeviceID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  status = WdfPdoInitAddHardwareID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  status = WdfPdoInitAddCompatibleID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  
  RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
  status = WdfPdoInitAssignInstanceID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  
  RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
  status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  WdfPdoInitSetDefaultLocale(child_init, 0x0409);

  WdfDeviceInitSetPowerNotPageable(child_init);

  WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState);
  
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
  status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  xppdd = GetXppdd(child_device);
  
  xppdd->wdf_device = child_device;
  xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
  xppdd->xpdd = xpdd;

  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);

  WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
  child_pnp_capabilities.LockSupported = WdfFalse;
  child_pnp_capabilities.EjectSupported  = WdfTrue;
  child_pnp_capabilities.Removable  = WdfTrue;
  child_pnp_capabilities.DockDevice  = WdfFalse;
  child_pnp_capabilities.UniqueID  = WdfFalse;
  child_pnp_capabilities.SilentInstall  = WdfTrue;
  child_pnp_capabilities.SurpriseRemovalOK  = WdfTrue;
  child_pnp_capabilities.HardwareDisabled = WdfFalse;
  WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);

  WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
  child_power_capabilities.DeviceD1 = WdfTrue;
  child_power_capabilities.WakeFromD1 = WdfTrue;
  child_power_capabilities.DeviceWake = PowerDeviceD1;
  child_power_capabilities.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
  child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
  child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
  child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
  child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  child_power_capabilities.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
  WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);  

  RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
  RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
  xppdd->index = identification->index;
  KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
  ExInitializeFastMutex(&xppdd->backend_state_mutex);
  xppdd->backend_state = XenbusStateUnknown;
  xppdd->frontend_state = XenbusStateUnknown;
  xppdd->backend_path[0] = '\0';
  xppdd->backend_id = 0;
    
  FUNCTION_EXIT();
  
  return status;
}
Example #21
0
NTSTATUS
OnDeviceAdd(
    _In_    WDFDRIVER       FxDriver,
    _Inout_ PWDFDEVICE_INIT FxDeviceInit
    )
/*++
 
  Routine Description:

    This routine creates the device object for an SPB 
    controller and the device's child objects.

  Arguments:

    FxDriver - the WDF driver object handle
    FxDeviceInit - information about the PDO that we are loading on

  Return Value:

    Status

--*/
{
    //FuncEntry(TRACE_FLAG_WDFLOADING);

    PDEVICE_CONTEXT pDevice;
    NTSTATUS status;
    
    UNREFERENCED_PARAMETER(FxDriver);

    //
    // Setup PNP/Power callbacks.
    //

    {
        WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);

        pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware;
        pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware;
        pnpCallbacks.EvtDeviceD0Entry = OnD0Entry;
        pnpCallbacks.EvtDeviceD0Exit = OnD0Exit;

        WdfDeviceInitSetPnpPowerEventCallbacks(FxDeviceInit, &pnpCallbacks);
    }

    //
    // Prepare for file object handling.
    //

    {
        WDF_FILEOBJECT_CONFIG fileObjectConfig;

        WDF_FILEOBJECT_CONFIG_INIT(
            &fileObjectConfig, 
            nullptr, 
            nullptr,
            OnFileCleanup);

        WDF_OBJECT_ATTRIBUTES fileObjectAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);

        WdfDeviceInitSetFileObjectConfig(
            FxDeviceInit, 
            &fileObjectConfig,
            &fileObjectAttributes);
    }

    //
    // Set request attributes.
    //

    {
        WDF_OBJECT_ATTRIBUTES attributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &attributes,
            REQUEST_CONTEXT);

        WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes);
    }

    //
    // Create the device.
    //

    {
        WDFDEVICE fxDevice;
        WDF_OBJECT_ATTRIBUTES deviceAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

        status = WdfDeviceCreate(
            &FxDeviceInit, 
            &deviceAttributes,
            &fxDevice);

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating WDFDEVICE - %!STATUS!", 
                status);

            goto exit;
        }

        pDevice = GetDeviceContext(fxDevice);
        NT_ASSERT(pDevice != nullptr);

        pDevice->FxDevice = fxDevice;
    }

    //
    // Ensure device is disable-able
    //
    
    {
        WDF_DEVICE_STATE deviceState;
        WDF_DEVICE_STATE_INIT(&deviceState);
        
        deviceState.NotDisableable = WdfFalse;
        WdfDeviceSetDeviceState(pDevice->FxDevice, &deviceState);
    }

    //
    // Create queues to handle IO
    //

    {
        WDF_IO_QUEUE_CONFIG queueConfig;
        WDFQUEUE queue;

        //
        // Top-level queue
        //

        WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
            &queueConfig, 
            WdfIoQueueDispatchParallel);

        queueConfig.EvtIoDefault = OnTopLevelIoDefault;
        queueConfig.PowerManaged = WdfFalse;

        status = WdfIoQueueCreate(
            pDevice->FxDevice,
            &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES,
            &queue
            );

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating top-level IO queue - %!STATUS!", 
                status);

            goto exit;
        }

        //
        // Sequential SPB queue
        //

        WDF_IO_QUEUE_CONFIG_INIT(
            &queueConfig, 
            WdfIoQueueDispatchSequential);

        queueConfig.EvtIoRead = OnIoRead;
        queueConfig.EvtIoWrite = OnIoWrite;
        queueConfig.EvtIoDeviceControl = OnIoDeviceControl;
        queueConfig.PowerManaged = WdfFalse;

        status = WdfIoQueueCreate(
            pDevice->FxDevice,
            &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES,
            &pDevice->SpbQueue
            );

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating SPB IO queue - %!STATUS!", 
                status);

            goto exit;
        }
    }

    //
    // Create a symbolic link.
    //

    {
        DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128);

        status = RtlUnicodeStringPrintf(
            &symbolicLinkName, L"%ws",
            sensy_SYMBOLIC_NAME);

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating symbolic link string for device "
                "- %!STATUS!", 
                status);

            goto exit;
        }

        status = WdfDeviceCreateSymbolicLink(
            pDevice->FxDevice, 
            &symbolicLinkName);

        if (!NT_SUCCESS(status))
        {
            Trace(
                TRACE_LEVEL_ERROR, 
                TRACE_FLAG_WDFLOADING,
                "Error creating symbolic link for device "
                "- %!STATUS!", 
                status);

            goto exit;
        }
    }

    //
    // Retrieve registry settings.
    //

    {
        WDFKEY key = NULL;
        WDFKEY subkey = NULL;
        ULONG connectInterrupt = 0;
        NTSTATUS settingStatus;
    
        DECLARE_CONST_UNICODE_STRING(subkeyName, L"Settings");
        DECLARE_CONST_UNICODE_STRING(connectInterruptName, L"ConnectInterrupt");

        settingStatus = WdfDeviceOpenRegistryKey(
            pDevice->FxDevice,
            PLUGPLAY_REGKEY_DEVICE,
            KEY_READ,
            WDF_NO_OBJECT_ATTRIBUTES,
            &key);

        if (!NT_SUCCESS(settingStatus))
        {
            Trace(
                TRACE_LEVEL_WARNING, 
                TRACE_FLAG_WDFLOADING,
                "Error opening device registry key - %!STATUS!",
                settingStatus);
        }

        if (NT_SUCCESS(settingStatus))
        {
            settingStatus = WdfRegistryOpenKey(
                key,
                &subkeyName,
                KEY_READ,
                WDF_NO_OBJECT_ATTRIBUTES,
                &subkey);

            if (!NT_SUCCESS(settingStatus))
            {
                Trace(
                    TRACE_LEVEL_WARNING, 
                    TRACE_FLAG_WDFLOADING,
                    "Error opening registry subkey for 'Settings' - %!STATUS!", 
                    settingStatus);
            }
        }

        if (NT_SUCCESS(settingStatus))
        {

            settingStatus = WdfRegistryQueryULong(
                subkey,
                &connectInterruptName,
                &connectInterrupt);

            if (!NT_SUCCESS(settingStatus))
            {
                Trace(
                    TRACE_LEVEL_WARNING, 
                    TRACE_FLAG_WDFLOADING,
                    "Error querying registry value for 'ConnectInterrupt' - %!STATUS!", 
                    settingStatus);
            }
        }

        if (key != NULL)
        {
            WdfRegistryClose(key);
        }

        if (subkey != NULL)
        {
            WdfRegistryClose(subkey);
        }

        pDevice->ConnectInterrupt = (connectInterrupt == 1);
    }

exit:

    //FuncExit(TRACE_FLAG_WDFLOADING);

    return status;
}
Example #22
0
File: device.c Project: MHesham/bsp
VCHIQ_PAGED_SEGMENT_BEGIN

/*++

Routine Description:

     Worker routine called to create a device and its software resources.

Arguments:

     DeviceInitPtr - Pointer to an opaque init structure. Memory for this
          structure will be freed by the framework when the WdfDeviceCreate
          succeeds. So don't access the structure after that point.

Return Value:

     NTSTATUS

--*/
_Use_decl_annotations_
NTSTATUS VchiqCreateDevice (
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInitPtr
    )
{
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    DEVICE_CONTEXT* deviceContextPtr;
    WDFDEVICE device;
    NTSTATUS status;
    WDF_IO_TYPE_CONFIG ioConfig;
    DECLARE_CONST_UNICODE_STRING(vchiqSymbolicLink, VCHIQ_SYMBOLIC_NAME);

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    {
        WDF_FILEOBJECT_CONFIG fileobjectConfig;
        WDF_FILEOBJECT_CONFIG_INIT(
            &fileobjectConfig,
            WDF_NO_EVENT_CALLBACK,
            VchiqFileClose,
            WDF_NO_EVENT_CALLBACK);

        fileobjectConfig.FileObjectClass = WdfFileObjectWdfCanUseFsContext;

        WdfDeviceInitSetFileObjectConfig(
            DeviceInitPtr,
            &fileobjectConfig,
            WDF_NO_OBJECT_ATTRIBUTES);
    }

    WDF_IO_TYPE_CONFIG_INIT(&ioConfig);
    ioConfig.ReadWriteIoType = WdfDeviceIoDirect;
    ioConfig.DeviceControlIoType = WdfDeviceIoDirect;
    ioConfig.DirectTransferThreshold = 0;

    WdfDeviceInitSetIoTypeEx(DeviceInitPtr, &ioConfig);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = 
        VchiqPrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware =
        VchiqReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = 
        VchiqInitOperation;
    WdfDeviceInitSetPnpPowerEventCallbacks(
        DeviceInitPtr, 
        &pnpPowerCallbacks);

    WdfDeviceInitSetIoInCallerContextCallback(
        DeviceInitPtr,
        VchiqInCallerContext);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
        &deviceAttributes, 
        DEVICE_CONTEXT);

    status = WdfDeviceCreate(
        &DeviceInitPtr,
        &deviceAttributes,
        &device);
    if (!NT_SUCCESS(status)) {
        VCHIQ_LOG_ERROR(
            "WdfDeviceCreate fail %!STATUS!", status);
        goto End;
    }

    {
        WDF_OBJECT_ATTRIBUTES attributes;
        WDF_IO_QUEUE_CONFIG queueConfig;
        WDFQUEUE queue;

        deviceContextPtr = VchiqGetDeviceContext(device);
        deviceContextPtr->Device = device;
        deviceContextPtr->VersionMajor = VCHIQ_VERSION_MAJOR;
        deviceContextPtr->VersionMinor = VCHIQ_VERSION_MINOR;

        deviceContextPtr->PhyDeviceObjectPtr =
            WdfDeviceWdmGetPhysicalDevice(device);

        WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
            &queueConfig,
            WdfIoQueueDispatchParallel);
        queueConfig.EvtIoDeviceControl = VchiqIoDeviceControl;
        queueConfig.EvtIoStop = VchiqIoStop;

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ExecutionLevel = WdfExecutionLevelPassive;

        status = WdfIoQueueCreate(
            device,
            &queueConfig,
            &attributes,
            &queue);
        if (!NT_SUCCESS(status)) {
            VCHIQ_LOG_ERROR(
                "WdfIoQueueCreate fail %!STATUS!", status);
            goto End;
        }
    }

    // Create symbolic and device interface
    status = WdfDeviceCreateSymbolicLink(
        device,
        &vchiqSymbolicLink);
    if (!NT_SUCCESS(status)) {
        VCHIQ_LOG_ERROR(
            "Fail to register symbolic link %!STATUS!",
            status);
        goto End;
    }

End:
    VCHIQ_LOG_INFORMATION("Exit Status %!STATUS!", status);

    return status;
}
Example #23
0
///////////////////////////////////////////////////////////////////////////////
//
//  BasicUsbEvtDeviceAdd
//
//    This routine is called by the framework when a device of
//    the type we support is found in the system.
//
//  INPUTS:
//
//      DriverObject - Our WDFDRIVER object
//
//      DeviceInit   - The device iniitalization structure we'll
//                     be using to create our WDFDEVICE
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      STATUS_SUCCESS, otherwise an error indicating why the driver could not
//                      load.
//
//  IRQL:
//
//      This routine is called at IRQL == PASSIVE_LEVEL.
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
BasicUsbEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
{
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES objAttributes;
    WDFDEVICE device;
    WDF_IO_QUEUE_CONFIG queueConfig;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    PBASICUSB_DEVICE_CONTEXT  devContext;   
    

#if DBG
    DbgPrint("BasicUsbEvtDeviceAdd\n");
#endif
   
    
    //
    // Our "internal" (native) and user-accessible device names
    //
    DECLARE_CONST_UNICODE_STRING(nativeDeviceName, L"\\Device\\BasicUsb");
    DECLARE_CONST_UNICODE_STRING(userDeviceName, L"\\Global??\\BasicUsb");
    
    UNREFERENCED_PARAMETER(Driver);

    //
    // Life is a bit more complicated in this driver...
    //
    // We need an EvtPrepareHardware to configure our device. In addition, we
    // must handle EvtD0Entry and EvtD0Exit in order to manage our continuous
    // reader.
    //
    
    //
    // Prepare for WDFDEVICE creation
    //
    // Initialize standard WDF Object Attributes structure
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&objAttributes);

    //
    // Specify our device context
    //
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objAttributes,
                                        BASICUSB_DEVICE_CONTEXT);

    //
    // We want our device object NAMED, thank you very much
    //
    status = WdfDeviceInitAssignName(DeviceInit, &nativeDeviceName);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceInitAssignName failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // Set our I/O type to DIRECT, meaning that we want to receive
    // MDLs for both read and write requests.
    //
    // While we are not obligated to choose direct, USB drivers
    // typically do so because the USB bus driver needs MDLs to
    // actually perform the transfer. If we select DIRECT I/O, the
    // bus driver can just use the MDL that we're given as opposed
    // to creating his own.
    //
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
    
    //
    // In this driver we need to be notified of some Pnp/Power
    // events, so initialize a pnp power callbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // USB drivers configure their device within prepare hardware,
    // so register an EvtDevicePrepareHardware callback.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware 
                                     = BasicUsbEvtDevicePrepareHardware;

    //
    // Our driver uses a continuous reader on the interrupt pipe to
    // be notified asynchronously of changes to the OSRFX2's
    // switchpack. We need to start the reader in D0Entry and stop
    // it in D0Exit, so register for EvtDeviceD0Entry and
    // EvtDeviceD0Exit callbacks
    //
    pnpPowerCallbacks.EvtDeviceD0Entry = BasicUsbEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = BasicUsbEvtDeviceD0Exit;  

    //
    // Update the DeviceInit structure to contain the new callbacks.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, 
                                           &pnpPowerCallbacks);

    //
    // We want to send control transfers synchronously from within
    // EvtIoDeviceControl, so we'll apply a PASSIVE_LEVEL constraint
    // to our device
    //
    objAttributes.ExecutionLevel = WdfExecutionLevelPassive;

    //
    // Now let's create our device object
    //
    status = WdfDeviceCreate(&DeviceInit,
                            &objAttributes, 
                            &device);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreate failed 0x%0x\n", status);
#endif
        return status;
    }

    //
    // Create a symbolic link for the control object so that usermode can open
    // the device by name.
    //
    status = WdfDeviceCreateSymbolicLink(device, &userDeviceName);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreateSymbolicLink failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // ALSO create a device interface for the device
    // This allows usage of the lovely SetupApiXxxx functions to locate
    // the device
    //
    status = WdfDeviceCreateDeviceInterface(device,
                                    &GUID_DEVINTERFACE_BASICUSB,
                                    NULL);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreateDeviceInterface failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // Configure our queue of incoming requests
    //
    // We only use the default queue, and we set it for parallel processing.
    // We chose this because we may have, say, a bulk read hanging on the bus
    // driver that won't get completed until we send down a bulk write.
    //
    // If we chose a sequential queue we wouldn't be presented the write from
    // the user until the read completed, but the read wouldn't complete
    // until we were presented the write from the user - resulting in an "I/O
    // deadlock".
    //
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig,
                                           WdfIoQueueDispatchParallel);

    //
    // Declare our I/O Event Processing callbacks
    //
    // We handle, read, write, and device control requests.
    //
    // WDF will automagically handle Create and Close requests for us and will
    // will complete any OTHER request types with STATUS_INVALID_DEVICE_REQUEST.    
    //
    queueConfig.EvtIoRead = BasicUsbEvtRead;
    queueConfig.EvtIoWrite = BasicUsbEvtWrite;
    queueConfig.EvtIoDeviceControl = BasicUsbEvtDeviceControl;

    //
    // Because this is a queue for a real hardware
    // device, indicate that the queue needs to be
    // power managed
    //
    queueConfig.PowerManaged = WdfTrue;

    status = WdfIoQueueCreate(device,
                            &queueConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            NULL); // optional pointer to receive queue handle

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfIoQueueCreate for default queue failed 0x%0x\n", status);
#endif
        return(status);
    }

    devContext = BasicUsbGetContextFromDevice(device);

    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                             WdfIoQueueDispatchManual);

    status = WdfIoQueueCreate(device,
                              &queueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &devContext->SwitchPackStateChangeQueue);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfIoQueueCreate for manual queue failed 0x%0x\n", status);
#endif
        return(status);
    }

    return(STATUS_SUCCESS);
}
_Must_inspect_result_
NTSTATUS
FxLibraryCommonCommission(
    VOID
    )
{
    DECLARE_CONST_UNICODE_STRING(usName, L"RtlGetVersion");
    PFN_RTL_GET_VERSION pRtlGetVersion = NULL;
    NTSTATUS   status;

    __Print((LITERAL(WDF_LIBRARY_COMMISSION) "\n"));

    //
    // Commission this version's DLL globals.
    //
    status = FxLibraryGlobalsCommission();

    if (!NT_SUCCESS(status)) {
        __Print(("FxLibraryGlobalsCommission failed %X\n", status));
        return status;
    }

    //
    // register telemetry provider.
    //
    RegisterTelemetryProvider();

    //
    // Initialize internal WPP tracing.
    //
    status = FxTraceInitialize();
    if (NT_SUCCESS(status)) {
        FxLibraryGlobals.InternalTracingInitialized = TRUE;
    }
    else {
        __Print(("Failed to initialize tracing for WDF\n"));

        //
        // Failure to initialize is not critical enough to fail driver load.
        //
        status = STATUS_SUCCESS;
    }
    
    //
    // Attempt to load RtlGetVersion (works for > w2k).
    //
    pRtlGetVersion = (PFN_RTL_GET_VERSION) MmGetSystemRoutineAddress(
        (PUNICODE_STRING) &usName
        );

    //
    // Now attempt to get this OS's version.
    //
    if (pRtlGetVersion != NULL) {
        pRtlGetVersion(&gOsVersion);
    }

    __Print(("OsVersion(%d.%d)\n",
             gOsVersion.dwMajorVersion,
             gOsVersion.dwMinorVersion ));

    //
    // Init triage info for 9f bugcheck analysis.
    //
    GetTriageInfo();
    
    return STATUS_SUCCESS;
}
Example #25
0
File: wmi.c Project: uri247/wdk80
NTSTATUS
Bus_WmiRegistration(
    WDFDEVICE      Device
    )
/*++
Routine Description

    Registers with WMI as a data provider for this
    instance of the device

--*/
{
    WDF_WMI_PROVIDER_CONFIG providerConfig;
    WDF_WMI_INSTANCE_CONFIG instanceConfig;
    PFDO_DEVICE_DATA deviceData;
    NTSTATUS status;
    DECLARE_CONST_UNICODE_STRING(busRsrcName, BUSRESOURCENAME);

    PAGED_CODE();

    deviceData = FdoGetData(Device);

    //
    // Register WMI classes.
    // First specify the resource name which contain the binary mof resource.
    //
    status = WdfDeviceAssignMofResourceName(Device, &busRsrcName);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &ToasterBusInformation_GUID);
    providerConfig.MinInstanceBufferSize = sizeof(TOASTER_BUS_WMI_STD_DATA);

    //
    // You would want to create a WDFWMIPROVIDER handle separately if you are
    // going to dynamically create instances on the provider.  Since we are
    // statically creating one instance, there is no need to create the provider
    // handle.
    //

    WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig);

    //
    // By setting Regsiter to TRUE, we tell the framework to create a provider
    // as part of the Instance creation call. This eliminates the need to
    // call WdfWmiProviderRegister.
    //
    instanceConfig.Register = TRUE;
    instanceConfig.EvtWmiInstanceQueryInstance = Bus_EvtStdDataQueryInstance;
    instanceConfig.EvtWmiInstanceSetInstance = Bus_EvtStdDataSetInstance;
    instanceConfig.EvtWmiInstanceSetItem = Bus_EvtStdDataSetItem;

    status = WdfWmiInstanceCreate(
        Device,
        &instanceConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        WDF_NO_HANDLE
        );

    if (NT_SUCCESS(status)) {
        deviceData->StdToasterBusData.ErrorCount = 0;
    }

    return status;
}
NTSTATUS
XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
{
  NTSTATUS status;
  WDF_CHILD_LIST_CONFIG child_list_config;
  WDFDEVICE device;
  PXENUSB_DEVICE_DATA xudd;
  //UNICODE_STRING reference;
  WDF_OBJECT_ATTRIBUTES device_attributes;
  PNP_BUS_INFORMATION pbi;
  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
  WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
  WDF_IO_QUEUE_CONFIG queue_config;
  UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
  DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
  WDFSTRING symbolicname_value_wdfstring;
  WDFKEY device_key;
  UNICODE_STRING symbolicname_value;

  UNREFERENCED_PARAMETER(driver);

  FUNCTION_ENTER();

  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
  pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry;
  pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit;

  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);

  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
    IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
  WdfDeviceInitSetExclusive(device_init, FALSE);

  WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice);
  child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren;
  WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);

  WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);

  WdfDeviceInitSetPowerNotPageable(device_init);
  
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA);
  status = WdfDeviceCreate(&device_init, &device_attributes, &device);
  if (!NT_SUCCESS(status))
  {
    FUNCTION_MSG("Error creating device %08x\n", status);
    return status;
  }

  xudd = GetXudd(device);
  xudd->pdo = WdfDeviceWdmGetPhysicalDevice(device);
  xudd->child_list = WdfFdoGetDefaultChildList(device);
  KeInitializeEvent(&xudd->backend_event, SynchronizationEvent, FALSE);
  InitializeListHead(&xudd->partial_pvurb_queue);
  InitializeListHead(&xudd->partial_pvurb_ring);
  KeInitializeDpc(&xudd->event_dpc, XenUsb_HandleEventDpc, xudd);

  KeInitializeSpinLock(&xudd->urb_ring_lock);
  
  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl;
  queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating io_queue 0x%x\n", status);
      return status;
  }

  WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB;
  //queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating urb_queue 0x%x\n", status);
      return status;
  }

  WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
  power_capabilities.DeviceD1 = WdfTrue;
  power_capabilities.WakeFromD1 = WdfTrue;
  power_capabilities.DeviceWake = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
  power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  power_capabilities.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
  WdfDeviceSetPowerCapabilities(device, &power_capabilities);  

  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
  
  pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
  pbi.LegacyBusType = PNPBus;
  pbi.BusNumber = 0;
  WdfDeviceSetBusInformationForChildren(device, &pbi);

  status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n");
    return status;
  }

  /* USB likes to have a registry key with the symbolic link name in it */
  status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfStringCreate returned %08x\n");
    return status;
  }
  status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n");
    return status;
  }
  WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
  status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n");
    return status;
  }
  WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);

  FUNCTION_EXIT();
  return status;
}
Example #27
0
_Use_decl_annotations_
NTSTATUS OnDeviceAdd (WDFDRIVER /*WdfDriver*/, WDFDEVICE_INIT* DeviceInitPtr)
{
    PAGED_CODE();
    BCM_I2C_ASSERT_MAX_IRQL(PASSIVE_LEVEL);

    NTSTATUS status;

    //
    // Configure DeviceInit structure
    //
    status = SpbDeviceInitConfig(DeviceInitPtr);
    if (!NT_SUCCESS(status)) {
        BSC_LOG_ERROR(
            "SpbDeviceInitConfig() failed. (DeviceInitPtr = %p, status = %!STATUS!)",
            DeviceInitPtr,
            status);
        return status;
    }

    //
    // Setup PNP/Power callbacks.
    //
    {
        WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);

        pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware;
        pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware;
        pnpCallbacks.EvtDeviceD0Entry = OnD0Entry;
        pnpCallbacks.EvtDeviceD0Exit = OnD0Exit;

        WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInitPtr, &pnpCallbacks);
    }

    //
    // Create the device.
    //
    WDFDEVICE wdfDevice;
    BCM_I2C_DEVICE_CONTEXT* devicePtr;
    {
        WDF_OBJECT_ATTRIBUTES deviceAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &deviceAttributes,
            BCM_I2C_DEVICE_CONTEXT);

        status = WdfDeviceCreate(
            &DeviceInitPtr,
            &deviceAttributes,
            &wdfDevice);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to create WDFDEVICE. (DeviceInitPtr = %p, status = %!STATUS!)",
                DeviceInitPtr,
                status);
            return status;
        }

        devicePtr = GetDeviceContext(wdfDevice);
        NT_ASSERT(devicePtr);
        devicePtr->WdfDevice = wdfDevice;
    }

    //
    // Query registry for ClockStretchTimeout
    //
    {
        WDFKEY wdfKey;
        status = WdfDeviceOpenRegistryKey(
                wdfDevice,
                PLUGPLAY_REGKEY_DEVICE,
                KEY_QUERY_VALUE,
                WDF_NO_OBJECT_ATTRIBUTES,
                &wdfKey);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to open device parameters registry key. (status=%!STATUS!)",
                status);
            return status;
        }
        auto closeRegKey = Finally([&] {
            PAGED_CODE();
            WdfRegistryClose(wdfKey);
        });

        DECLARE_CONST_UNICODE_STRING(
            regValString,
            REGSTR_VAL_CLOCK_STRETCH_TIMEOUT);

        ULONG clockStretchTimeout;
        status = WdfRegistryQueryULong(
                wdfKey,
                &regValString,
                &clockStretchTimeout);
        if (NT_SUCCESS(status)) {
            if ((clockStretchTimeout & BCM_I2C_REG_CLKT_TOUT_MASK) !=
                 clockStretchTimeout) {

                BSC_LOG_ERROR(
                    "Clock stretch timeout value from registry is out of range. (clockStretchTimeout=0x%x, BCM_I2C_REG_CLKT_TOUT_MASK=0x%x)",
                    clockStretchTimeout,
                    BCM_I2C_REG_CLKT_TOUT_MASK);
                return STATUS_INVALID_PARAMETER;
            }

            BSC_LOG_INFORMATION(
                "Using ClockStretchTimeout value from registry. (clockStretchTimeout=0x%x)",
                clockStretchTimeout);

        } else {
            switch (status) {
            case STATUS_OBJECT_NAME_NOT_FOUND:
                clockStretchTimeout = BCM_I2C_REG_CLKT_TOUT_DEFAULT;
                status = STATUS_SUCCESS;
                break;
            default:
                BSC_LOG_ERROR(
                    "Failed to query clock stretch timeout from registry. (status=%!STATUS!, REGSTR_VAL_CLOCK_STRETCH_TIMEOUT=%S)",
                    status,
                    REGSTR_VAL_CLOCK_STRETCH_TIMEOUT);
                return status;
            }
        }

        devicePtr->ClockStretchTimeout = clockStretchTimeout;
    }

    //
    // Ensure device is disable-able
    //
    {
        WDF_DEVICE_STATE deviceState;
        WDF_DEVICE_STATE_INIT(&deviceState);
        deviceState.NotDisableable = WdfFalse;
        WdfDeviceSetDeviceState(wdfDevice, &deviceState);
    }

    //
    // Bind a SPB controller object to the device.
    //
    {
        SPB_CONTROLLER_CONFIG spbConfig;
        SPB_CONTROLLER_CONFIG_INIT(&spbConfig);

        //
        // Register for target connect callback.  The driver
        // does not need to respond to target disconnect.
        //

        spbConfig.EvtSpbTargetConnect = OnTargetConnect;

        //
        // Register for IO callbacks.
        //

        spbConfig.ControllerDispatchType = WdfIoQueueDispatchSequential;
        spbConfig.EvtSpbIoRead = OnRead;
        spbConfig.EvtSpbIoWrite = OnWrite;
        spbConfig.EvtSpbIoSequence = OnSequence;

        status = SpbDeviceInitialize(wdfDevice, &spbConfig);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "SpbDeviceInitialize failed. (wdfDevice = %p, status = %!STATUS!)",
                wdfDevice,
                status);
            return status;
        }
    }

    //
    // Set target object attributes.
    //
    {
        WDF_OBJECT_ATTRIBUTES targetAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &targetAttributes,
            BCM_I2C_TARGET_CONTEXT);

        SpbControllerSetTargetAttributes(wdfDevice, &targetAttributes);
    }

    //
    // Create an interrupt object
    //
    BCM_I2C_INTERRUPT_CONTEXT* interruptContextPtr;
    {
        WDF_OBJECT_ATTRIBUTES interruptObjectAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &interruptObjectAttributes,
            BCM_I2C_INTERRUPT_CONTEXT);

        WDF_INTERRUPT_CONFIG interruptConfig;
        WDF_INTERRUPT_CONFIG_INIT(
            &interruptConfig,
            OnInterruptIsr,
            OnInterruptDpc);

        status = WdfInterruptCreate(
            wdfDevice,
            &interruptConfig,
            &interruptObjectAttributes,
            &devicePtr->WdfInterrupt);
        if (!NT_SUCCESS(status)) {
            BSC_LOG_ERROR(
                "Failed to create interrupt object. (wdfDevice = %p, status = %!STATUS!)",
                wdfDevice,
                status);
            return status;
        }

        interruptContextPtr = GetInterruptContext(devicePtr->WdfInterrupt);
        interruptContextPtr->WdfInterrupt = devicePtr->WdfInterrupt;
    }
    devicePtr->InterruptContextPtr = interruptContextPtr;

    NT_ASSERT(NT_SUCCESS(status));
    return STATUS_SUCCESS;
}
// Sets up a new device.
NTSTATUS
DeviceContext::DeviceAdd(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
    NTSTATUS status;

    NFC_CX_CLIENT_CONFIG nfcCxConfig;
    NFC_CX_CLIENT_CONFIG_INIT(&nfcCxConfig, NFC_CX_TRANSPORT_CUSTOM);
    nfcCxConfig.EvtNfcCxWriteNciPacket = WriteNciPacketCallback;
    nfcCxConfig.EvtNfcCxDeviceIoControl = DeviceIoCallback;
    nfcCxConfig.DriverFlags = NFC_CX_DRIVER_ENABLE_EEPROM_WRITE_PROTECTION |
        NFC_CX_DRIVER_POWER_AND_LINK_CONTROL_SUPPORTED;

    status = NfcCxDeviceInitConfig(DeviceInit, &nfcCxConfig);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "NfcCxDeviceInitConfig failed. %!STATUS!", status);
        return status;
    }

    WDF_OBJECT_ATTRIBUTES deviceObjectAttributes;
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceObjectAttributes, DeviceContext);
    deviceObjectAttributes.EvtCleanupCallback = ShutdownCallback;
    deviceObjectAttributes.EvtDestroyCallback = DestroyCallback;

    WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);
    pnpCallbacks.EvtDeviceD0Entry = D0EntryCallback;
    pnpCallbacks.EvtDeviceD0Exit = D0ExitCallback;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks);

    FileObjectContext::DeviceInit(DeviceInit);

    WDFDEVICE device;
    status = WdfDeviceCreate(&DeviceInit, &deviceObjectAttributes, &device);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "WdfDeviceCreate failed. %!STATUS!", status);
        return status;
    }

    // Initialize device context.
    DeviceContext* deviceContext = DeviceGetContext(device);
    new (deviceContext) DeviceContext();
    deviceContext->_Device = device;

    status = NfcCxDeviceInitialize(device);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "NfcCxDeviceInitialize failed. %!STATUS!", status);
        return status;
    }

    // Create lock for clients (and sequence handling).
    WDF_OBJECT_ATTRIBUTES lockAttributes;
    WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes);
    lockAttributes.ParentObject = device;

    status = WdfWaitLockCreate(&lockAttributes, &deviceContext->_ClientLock);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "WdfWaitLockCreate failed. %!STATUS!", status);
        return status;
    }

    // Initialize RF discovery config (enable everything).
    NFC_CX_RF_DISCOVERY_CONFIG discoveryConfig;
    NFC_CX_RF_DISCOVERY_CONFIG_INIT(&discoveryConfig);
    discoveryConfig.PollConfig = NFC_CX_POLL_NFC_A | NFC_CX_POLL_NFC_B | NFC_CX_POLL_NFC_F_212 | NFC_CX_POLL_NFC_F_424 | NFC_CX_POLL_NFC_15693 | NFC_CX_POLL_NFC_ACTIVE | NFC_CX_POLL_NFC_A_KOVIO;
    discoveryConfig.NfcIPMode = NFC_CX_NFCIP_NFC_A | NFC_CX_NFCIP_NFC_F_212 | NFC_CX_NFCIP_NFC_F_424 | NFC_CX_NFCIP_NFC_ACTIVE | NFC_CX_NFCIP_NFC_ACTIVE_A | NFC_CX_NFCIP_NFC_ACTIVE_F_212 | NFC_CX_NFCIP_NFC_ACTIVE_F_424;
    discoveryConfig.NfcIPTgtMode = NFC_CX_NFCIP_TGT_NFC_A | NFC_CX_NFCIP_TGT_NFC_F | NFC_CX_NFCIP_TGT_NFC_ACTIVE_A | NFC_CX_NFCIP_TGT_NFC_ACTIVE_F;
    discoveryConfig.NfcCEMode = NFC_CX_CE_NFC_A | NFC_CX_CE_NFC_B | NFC_CX_CE_NFC_F;

    status = NfcCxSetRfDiscoveryConfig(device, &discoveryConfig);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "NfcCxSetRfDiscoveryConfig failed. %!STATUS!", status);
        return status;
    }

    // Set the sequence handlers.
    for (int sequenceType = 0; sequenceType != SequenceMaximum; ++sequenceType)
    {
        status = NfcCxRegisterSequenceHandler(device, NFC_CX_SEQUENCE(sequenceType), SequenceHandlerCallback);
        if (!NT_SUCCESS(status))
        {
            TRACE_LINE(LEVEL_ERROR, "NfcCxRegisterSequenceHandler failed. %!STATUS!", status);
            return status;
        }
    }

    // Initialize callbacks manager.
    status = deviceContext->_ApiCallbacksManager.Initialize(device);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "CallbacksManager::Initialize failed. %!STATUS!", status);
        return status;
    }

    // Create device interface for NciSim
    DECLARE_CONST_UNICODE_STRING(interfaceName, FILE_NAMESPACE_NCI_SIMULATOR);
    status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_NCI_SIMULATOR, &interfaceName);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "WdfDeviceCreateDeviceInterface failed. %!STATUS!", status);
        return status;
    }

    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
    return STATUS_SUCCESS;
}
Example #29
0
NTSTATUS
Bus_DoStaticEnumeration(
    IN WDFDEVICE Device
    )
/*++
Routine Description:

    The routine enables you to statically enumerate child devices
    during start instead of running the enum.exe/notify.exe to
    enumerate toaster devices.

    In order to statically enumerate, user must specify the number
    of toasters in the Toaster Bus driver's device registry. The
    default value is zero.

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\SYSTEM\0002\
                    Device Parameters
                        NumberOfToasters:REG_DWORD:2

    You can also configure this value in the Toaster Bus Inf file.

--*/

{
    WDFKEY      hKey = NULL;
    NTSTATUS    status;
    ULONG       value, i;
    DECLARE_CONST_UNICODE_STRING(valueName, L"NumberOfToasters");

    //
    // If the registry value doesn't exist, we will use the
    // hardcoded default number.
    //
    value = DEF_STATICALLY_ENUMERATED_TOASTERS;

    //
    // Open the device registry and read the "NumberOfToasters" value.
    //
    status = WdfDeviceOpenRegistryKey(Device,
                                      PLUGPLAY_REGKEY_DEVICE,
                                      STANDARD_RIGHTS_ALL,
                                      NULL, // PWDF_OBJECT_ATTRIBUTES
                                      &hKey);

    if (NT_SUCCESS (status)) {

        status = WdfRegistryQueryULong(hKey,
                                  &valueName,
                                  &value);

        WdfRegistryClose(hKey);
        hKey = NULL; // Set hKey to NULL to catch any accidental subsequent use.

        if (NT_SUCCESS (status)) {
            //
            // Make sure it doesn't exceed the max. This is required to prevent
            // denial of service by enumerating large number of child devices.
            //
            value = min(value, MAX_STATICALLY_ENUMERATED_TOASTERS);
        }else {
            return STATUS_SUCCESS; // This is an optional property.
        }
    }

    KdPrint(("Enumerating %d toaster devices\n", value));

    for(i=1; i<= value; i++) {
        //
        // Value of i is used as serial number.
        //
        status = Bus_PlugInDevice(Device,
                         BUS_HARDWARE_IDS,
                         BUS_HARDWARE_IDS_LENGTH / sizeof(WCHAR),
                         i );
    }

    return status;
}
NTSTATUS PVPanicEvtDeviceAdd(IN WDFDRIVER Driver,
                             IN PWDFDEVICE_INIT DeviceInit)
{
    NTSTATUS status;
    WDFDEVICE device;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_FILEOBJECT_CONFIG fileConfig;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDF_IO_QUEUE_CONFIG queueConfig;
    PDEVICE_CONTEXT context;
    DECLARE_CONST_UNICODE_STRING(dosDeviceName, PVPANIC_DOS_DEVICE_NAME);

    UNREFERENCED_PARAMETER(Driver);

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

    PAGED_CODE();

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware = PVPanicEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = PVPanicEvtDeviceReleaseHardware;
	pnpPowerCallbacks.EvtDeviceD0Entry = PVPanicEvtDeviceD0Entry;
	pnpPowerCallbacks.EvtDeviceD0Exit = PVPanicEvtDeviceD0Exit;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

	WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PVPanicEvtDeviceFileCreate,
		WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK);

	WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig,
		WDF_NO_OBJECT_ATTRIBUTES);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfDeviceCreate failed: %!STATUS!", status);
        return status;
    }

    status = WdfDeviceCreateSymbolicLink(device, &dosDeviceName);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfDeviceCreateSymbolicLink failed: %!STATUS!", status);
        return status;
    }

    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);
    queueConfig.EvtIoDeviceControl = PVPanicEvtQueueDeviceControl;

    context = GetDeviceContext(device);
    status = WdfIoQueueCreate(device,
                              &queueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &context->IoctlQueue);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfIoQueueCreate failed: %!STATUS!", status);
        return status;
    }

    status = WdfDeviceConfigureRequestDispatching(device,
                                                  context->IoctlQueue,
                                                  WdfRequestTypeDeviceControl);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
            "WdfDeviceConfigureRequestDispatching failed: %!STATUS!", status);
        return status;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %!FUNC!");

    return status;
}