summaryrefslogtreecommitdiff
path: root/pofx/WDF/Driver/MultiComp/driver
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /pofx/WDF/Driver/MultiComp/driver
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'pofx/WDF/Driver/MultiComp/driver')
-rw-r--r--pofx/WDF/Driver/MultiComp/driver/HwSim.c251
-rw-r--r--pofx/WDF/Driver/MultiComp/driver/HwSim.h83
-rw-r--r--pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.c1036
-rw-r--r--pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.h114
-rw-r--r--pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.inx79
-rw-r--r--pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj188
-rw-r--r--pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj.Filters37
7 files changed, 1788 insertions, 0 deletions
diff --git a/pofx/WDF/Driver/MultiComp/driver/HwSim.c b/pofx/WDF/Driver/MultiComp/driver/HwSim.c
new file mode 100644
index 00000000..b3c04d86
--- /dev/null
+++ b/pofx/WDF/Driver/MultiComp/driver/HwSim.c
@@ -0,0 +1,251 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ HwSim.c
+
+Abstract:
+ This module implements a simple hardware simulator that simulates reading of
+ data from the device's components. In this sample, the "data" that is read
+ is simply the bitwise complement of the component number. In other words,
+ the data for component number 'X' is simply '~X'.
+
+ The hardware simulator also verifies that when a component is read, the
+ device is in D0 and the component is in F0. If not, it breaks into the
+ debugger.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "HwSim.h"
+#include "HwSim.tmh"
+
+NTSTATUS
+HwSimInitialize(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine initializes the hardware simulator
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES objectAttributes;
+ PHWSIM_CONTEXT devCtx;
+
+ //
+ // Allocate our context for this device
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes,
+ HWSIM_CONTEXT);
+ status = WdfObjectAllocateContext((WDFOBJECT) Device,
+ &objectAttributes,
+ (PVOID*) &devCtx);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfObjectAllocateContext failed with %!status!",
+ status);
+ goto exit;
+ }
+
+ devCtx->FirstD0Entry = TRUE;
+
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+VOID
+HwSimD0Entry(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine simulates the device entering D0
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ None
+
+--*/
+{
+ PHWSIM_CONTEXT devCtx;
+ ULONG i;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ if (devCtx->FirstD0Entry) {
+ devCtx->FirstD0Entry = FALSE;
+
+ //
+ // Put all components in F0
+ //
+ for (i=0; i < COMPONENT_COUNT; i++) {
+ devCtx->ComponentFState[i] = 0;
+ }
+ }
+
+ devCtx->DevicePoweredOn = TRUE;
+
+ return;
+}
+
+VOID
+HwSimD0Exit(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine simulates the device exiting D0
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ None
+
+--*/
+{
+ PHWSIM_CONTEXT devCtx;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ devCtx->DevicePoweredOn = FALSE;
+
+ return;
+}
+
+VOID
+HwSimFStateChange(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG Component,
+ _In_ ULONG State
+ )
+/*++
+Routine Description:
+
+ This routine simulates a component changing its F-state
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ Component - Index of the component whose F-state is changing
+
+ State - New F-state for the component
+
+Return Value:
+
+ None
+
+--*/
+{
+ PHWSIM_CONTEXT devCtx;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ //
+ // The caller should have ensured that this routine is called only when the
+ // device is powered on. Verify this. If false, we'll generate a verifier
+ // breakpoint.
+ //
+ if (FALSE == devCtx->DevicePoweredOn) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - Expected device to be powered on, but it was not.");
+ WdfVerifierDbgBreakPoint();
+ }
+
+ //
+ // Put the component in the requested F-state
+ //
+ devCtx->ComponentFState[Component] = State;
+ return;
+}
+
+ULONG
+HwSimReadComponent(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG Component
+ )
+/*++
+Routine Description:
+
+ This routine simulates the reading of data from a component
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ Component - Component from which data is being read
+
+Return Value:
+
+ A ULONG value representing the data that was read from the component
+
+--*/
+{
+ ULONG componentData;
+ PHWSIM_CONTEXT devCtx;
+
+ devCtx = HwSimGetDeviceContext(Device);
+
+ //
+ // The caller should have ensured that this routine is called only when the
+ // device is powered on. Verify this. If false, we'll generate a verifier
+ // breakpoint.
+ //
+ if (FALSE == devCtx->DevicePoweredOn) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - Expected device to be powered on, but it was not.");
+ WdfVerifierDbgBreakPoint();
+ }
+
+ //
+ // The caller should have ensured that this routine is called only when the
+ // component is in F0. Verify this. If false, we'll generate a verifier
+ // breakpoint.
+ //
+ if (0 != devCtx->ComponentFState[Component]) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - Expected component %d to be in F0, but it was in F%d.",
+ Component,
+ devCtx->ComponentFState[Component]);
+ WdfVerifierDbgBreakPoint();
+ }
+
+ //
+ // In this sample, component data is just a bit-wise complement of the
+ // component number.
+ //
+ componentData = ~Component;
+ return componentData;
+}
diff --git a/pofx/WDF/Driver/MultiComp/driver/HwSim.h b/pofx/WDF/Driver/MultiComp/driver/HwSim.h
new file mode 100644
index 00000000..f23395a3
--- /dev/null
+++ b/pofx/WDF/Driver/MultiComp/driver/HwSim.h
@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ HwSim.h
+
+Abstract:
+ Header file for the hardware simulation module of the KMDF sample driver for
+ a multi-component device.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "WdfMultiComp.h"
+
+#if !defined(_HWSIM_H_)
+#define _HWSIM_H_
+
+NTSTATUS
+HwSimInitialize(
+ _In_ WDFDEVICE Device
+ );
+
+VOID
+HwSimD0Entry(
+ _In_ WDFDEVICE Device
+ );
+
+VOID
+HwSimD0Exit(
+ _In_ WDFDEVICE Device
+ );
+
+VOID
+HwSimFStateChange(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG Component,
+ _In_ ULONG State
+ );
+
+ULONG
+HwSimReadComponent(
+ _In_ WDFDEVICE Device,
+ _In_ ULONG Component
+ );
+
+//
+// This structure represents the hardware simulation module's device context
+// space
+//
+typedef struct _HWSIM_CONTEXT {
+ //
+ // The following array tracks the F-state for each of the device's
+ // components. It is used for verification purposes only.
+ //
+ ULONG ComponentFState[COMPONENT_COUNT];
+
+ //
+ // The following member tracks whether or not the device is in D0. It is
+ // used for verification purposes only.
+ //
+ BOOLEAN DevicePoweredOn;
+
+ //
+ // The following member tracks whether or not we have previously entered the
+ // D0 state for this device
+ //
+ BOOLEAN FirstD0Entry;
+} HWSIM_CONTEXT, *PHWSIM_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HWSIM_CONTEXT, HwSimGetDeviceContext)
+
+#endif // _HWSIM_H_
diff --git a/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.c b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.c
new file mode 100644
index 00000000..f424c6b7
--- /dev/null
+++ b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.c
@@ -0,0 +1,1036 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ WdfMultiComp.c
+
+Abstract:
+ This module implements a KMDF sample driver for a multi-component device.
+ The driver uses the power framework to manage the power state of the
+ components of its device.
+
+ The device used in this sample is a root-enumerated device whose components
+ are simulated entirely in software. The simulation of the components is
+ implemented in HwSim.h and HwSim.c.
+
+ The driver's interaction with the power framework is encapsulated in a
+ separate library named WdfPoFx.lib. The driver statically links to this
+ library.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "WdfMultiComp.h"
+#include "HwSim.h"
+#include "WdfMultiComp.tmh"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text (INIT, DriverEntry)
+#pragma alloc_text (PAGE, MCompEvtDriverCleanup)
+#pragma alloc_text (PAGE, MCompEvtDeviceAdd)
+#pragma alloc_text (PAGE, MCompEvtDeviceD0Exit)
+#endif
+
+NTSTATUS
+DriverEntry(
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+
+ Driver initialization entry point. This entry point is called directly by
+ the I/O system.
+
+Arguments:
+
+ DriverObject - pointer to the driver object
+
+ RegistryPath - pointer to a unicode string representing the path to the
+ driver-specific key in the registry.
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ WDF_DRIVER_CONFIG config;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ NTSTATUS status;
+ WDFDRIVER hDriver;
+
+ WPP_INIT_TRACING(DriverObject, RegistryPath);
+
+ //
+ // Create a framework driver object to represent our driver.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.EvtCleanupCallback = MCompEvtDriverCleanup;
+ WDF_DRIVER_CONFIG_INIT(
+ &config,
+ MCompEvtDeviceAdd
+ );
+
+ status = WdfDriverCreate(DriverObject,
+ RegistryPath,
+ &attributes,
+ &config,
+ &hDriver);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDriverCreate failed with %!status!",
+ status);
+ WPP_CLEANUP(DriverObject);
+ }
+
+ return status;
+}
+
+VOID
+MCompEvtDriverCleanup(
+ _In_ WDFOBJECT Driver
+ )
+/*++
+
+Routine Description:
+
+ This routine is invoked when the framework driver object that was created in
+ DriverEntry is about to be deleted.
+
+Arguments:
+
+ Driver - Handle to the framework driver object created in DriverEntry
+
+Return Value:
+
+ None
+
+--*/
+{
+ PAGED_CODE();
+
+ WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER) Driver));
+}
+
+NTSTATUS
+InitializePowerFrameworkSettings(
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine initializes the power framework helper.
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ PO_FX_DEVICE_MCOMP_EXT poFxDevice;
+ PPO_FX_DEVICE poFxDevicePtr;
+ PO_FX_COMPONENT_IDLE_STATE idleState[2]; // F0 and F1 only
+ ULONG i;
+
+ RtlZeroMemory(&poFxDevice, sizeof(poFxDevice));
+ RtlZeroMemory(idleState, sizeof(idleState));
+
+ //
+ // Specify callbacks and context
+ //
+ poFxDevicePtr = (PPO_FX_DEVICE) &poFxDevice;
+ poFxDevicePtr->Version = PO_FX_VERSION_V1;
+ poFxDevicePtr->ComponentIdleStateCallback =
+ MCompComponentIdleStateCallback;
+ poFxDevicePtr->ComponentActiveConditionCallback = NULL;
+ poFxDevicePtr->ComponentIdleConditionCallback = NULL;
+ poFxDevicePtr->DevicePowerRequiredCallback = NULL;
+ poFxDevicePtr->DevicePowerNotRequiredCallback = NULL;
+ poFxDevicePtr->DeviceContext = Device;
+ poFxDevicePtr->ComponentCount = COMPONENT_COUNT;
+
+ //
+ // Initialize F-state-related information
+ // NOTE: We're making the F1 specification be the same for all components,
+ // but it does not have to be that way.
+ //
+
+ //
+ // Transition latency should be 0 for F0
+ //
+ idleState[0].TransitionLatency = 0;
+
+ //
+ // Residency requirement should be 0 for F0
+ //
+ idleState[0].ResidencyRequirement = 0;
+
+ //
+ // Nominal power for F0
+ //
+ idleState[0].NominalPower = PO_FX_UNKNOWN_POWER;
+
+ //
+ // Transition latency for F1
+ //
+ idleState[1].TransitionLatency = TRANSITION_LATENCY_F1;
+
+ //
+ // Residency requirement for F1
+ //
+ idleState[1].ResidencyRequirement = RESIDENCY_REQUIREMENT_F1;
+
+ //
+ // Nominal power for F1
+ //
+ idleState[1].NominalPower = PO_FX_UNKNOWN_POWER;
+
+ for (i=0; i < COMPONENT_COUNT; i++) {
+ //
+ // We're declaring that each of components support only F0 and F1
+ //
+ poFxDevicePtr->Components[i].IdleStateCount = 2;
+
+ //
+ // Specify the F-state information
+ //
+ poFxDevicePtr->Components[i].IdleStates = idleState;
+ }
+
+ //
+ // Provide the power framework settings to the power framework helper
+ //
+ status = PfhInitializePowerFrameworkSettings(Device, poFxDevicePtr);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+NTSTATUS
+CreateDevice(
+ _In_ WDFOBJECT PfhInitializer,
+ _In_ PWDFDEVICE_INIT DeviceInit,
+ _Out_ WDFDEVICE * Device
+ )
+/*++
+Routine Description:
+
+ This routine creates the KMDF device object and also initializes the power
+ framework helper's settings for this device object.
+
+Arguments:
+
+ PfhInitializer - Handle to the initializer object for initializing the power
+ framework helper.
+
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
+
+ Device - Handle to the KMDF device object created by this routine.
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES objectAttributes;
+ WDFDEVICE device = NULL;
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks;
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS s0IdleSettings;
+
+ //
+ // Register the PNP/power callbacks
+ //
+ // Note: This is the function driver for the device, so the framework
+ // automatically enables power policy ownership.
+ //
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks);
+ pnpCallbacks.EvtDeviceD0Entry = MCompEvtDeviceD0Entry;
+ pnpCallbacks.EvtDeviceD0Exit = MCompEvtDeviceD0Exit;
+
+ //
+ // Get the power framework helper to override our PNP/power callbacks
+ //
+ PfhInterceptWdfPnpPowerEventCallbacks(PfhInitializer, &pnpCallbacks);
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks);
+
+ //
+ // Give the power framework helper an opportunity to register WDM IRP
+ // preprocess callbacks for power IRPs
+ //
+ status = PfhAssignWdmPowerIrpPreProcessCallback(
+ PfhInitializer,
+ DeviceInit,
+ NULL, // EvtDeviceWdmPowerIrpPreprocess
+ NULL, // MinorFunctions
+ 0 // NumMinorFunctions
+ );
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ //
+ // Specify the context for the device
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes,
+ DEVICE_EXTENSION);
+
+ //
+ // Create a framework device object
+ //
+ status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceCreate failed with %!status!",
+ status);
+ goto exit;
+ }
+
+ //
+ // Specify the POHANDLE availability callbacks
+ //
+ PfhSetPoHandleAvailabilityCallbacks(PfhInitializer,
+ MCompPoHandleAvailable,
+ MCompPoHandleUnavailable);
+
+ //
+ // Enable S0-idle power management
+ //
+ // Note:
+ // * We set IdleTimeoutType = DriverManagedIdleTimeout to make sure KMDF
+ // doesn't register with the power framework on our behalf, because we
+ // will be directly registering with the power framework ourselves.
+ // * We set PowerUpIdleDeviceOnSystemWake = TRUE because when we register
+ // with power framework, we'd like to return to D0 immediately after the
+ // system returns to S0. It is a power framework requirement that once
+ // the system returns to S0, then device must return to D0 and the
+ // driver must invoke PoFxReportDevicePoweredOn (the power framework
+ // helper library does this on our behalf).
+ // * We pick a really small idle timeout value so that KMDF can power down
+ // the device almost immediately after the power framework allows it to
+ // do so.
+ //
+ // If S0-idle power management support is not required, then the following
+ // modifications should be made:
+ // 1. Recompile the power framework helper library with the value of the
+ // WDFPOFX_S0IDLE_SUPPORTED compiler switch set to 0. This omits the
+ // code that is specific to S0-idle power management, thereby reducing
+ // the size of the library.
+ // 2. Remove the calls to PfhSetS0IdleConfiguration and
+ // WdfDeviceAssignS0IdleSettings below.
+ //
+ PfhSetS0IdleConfiguration(PfhInitializer, PfhS0IdleSupportedPowerPageable);
+
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&s0IdleSettings,
+ IdleCannotWakeFromS0);
+ s0IdleSettings.IdleTimeoutType = DriverManagedIdleTimeout;
+ s0IdleSettings.PowerUpIdleDeviceOnSystemWake = WdfTrue;
+ s0IdleSettings.IdleTimeout = 1; // 1 millisecond
+ status = WdfDeviceAssignS0IdleSettings(device, &s0IdleSettings);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceAssignS0IdleSettings failed with %!status!",
+ status);
+ goto exit;
+ }
+
+ //
+ // Get the power framework helper to initialize its settings for this device
+ //
+ status = PfhInitializeDeviceSettings(device, PfhInitializer);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ *Device = device;
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+NTSTATUS
+CreateComponentQueues(
+ _In_ WDFOBJECT PfhInitializer,
+ _In_ WDFDEVICE Device
+ )
+/*++
+Routine Description:
+
+ This routine creates the component queues and also initializes the power
+ framework helper's settings for each of them.
+
+Arguments:
+
+ PfhInitializer - Handle to the initializer object for initializing the power
+ framework helper.
+
+ Device - Handle to the framework device object
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ PDEVICE_EXTENSION devExt;
+ ULONG i;
+ WDF_IO_QUEUE_CONFIG ioQueueConfig;
+
+ //
+ // Get the device extension
+ //
+ devExt = DeviceGetData(Device);
+
+ for (i=0; i < COMPONENT_COUNT; i++) {
+
+ //
+ // Create the component-specific queues
+ //
+ WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchParallel);
+ ioQueueConfig.EvtIoDeviceControl = MCompEvtIoDeviceControlSecondary;
+
+ //
+ // Get the power framework helper to override the configuration for our
+ // component-specific queue
+ //
+ PfhInterceptComponentQueueConfig(PfhInitializer, &ioQueueConfig);
+
+ //
+ // Associate the queue with a component
+ //
+ PfhSetComponentForComponentQueue(PfhInitializer, i);
+
+ //
+ // Create the queue
+ //
+
+ //
+ // 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,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &(devExt->Queue[i]));
+ __analysis_assume(ioQueueConfig.EvtIoStop == 0);
+
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfIoQueueCreate failed with %!status! when "
+ "creating queue for component %d",
+ status,
+ i);
+ goto exit;
+ }
+
+ //
+ // Get the power framework helper to initialize its settings for this
+ // component-specific queue
+ //
+ status = PfhInitializeComponentQueueSettings(devExt->Queue[i],
+ PfhInitializer);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+ }
+
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+NTSTATUS
+MCompEvtDeviceAdd(
+ _In_ WDFDRIVER Driver,
+ _Inout_ PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+Routine Description:
+
+ EvtDeviceAdd is called by the framework in response to AddDevice call from
+ the PnP manager.
+
+Arguments:
+
+ Driver - Handle to the framework driver object created in DriverEntry
+
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ NTSTATUS status;
+ WDFOBJECT pfhInitializer = NULL;
+ WDFDEVICE device = NULL;
+ WDF_IO_QUEUE_CONFIG ioQueueConfig;
+ WDFQUEUE sourceQueue = NULL;
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ //
+ // Create an initializer object for the power framework helper
+ //
+ status = PfhInitializerCreate(&pfhInitializer);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ //
+ // Create the device object
+ //
+ status = CreateDevice(pfhInitializer, DeviceInit, &device);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ //
+ // Create the source queue.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
+ WdfIoQueueDispatchParallel);
+ ioQueueConfig.EvtIoDeviceControl = MCompEvtIoDeviceControlPrimary;
+
+ //
+ // 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,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &sourceQueue);
+ __analysis_assume(ioQueueConfig.EvtIoStop == 0);
+
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfIoQueueCreate failed with %!status! when creating "
+ "source queue.",
+ status);
+ goto exit;
+ }
+
+ //
+ // Initialize power framework settings
+ //
+ status = InitializePowerFrameworkSettings(device);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ //
+ // Create the component queues
+ //
+ status = CreateComponentQueues(pfhInitializer, device);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ //
+ // Create a device interface so that applications can open a handle to this
+ // device.
+ //
+ status = WdfDeviceCreateDeviceInterface(device,
+ &GUID_DEVINTERFACE_POWERFX,
+ NULL /* ReferenceString */);
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfDeviceCreateDeviceInterface failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ //
+ // Initialize the hardware simulator
+ //
+ status = HwSimInitialize(device);
+ if (FALSE == NT_SUCCESS(status)) {
+ goto exit;
+ }
+
+ status = STATUS_SUCCESS;
+
+exit:
+ if (NULL != pfhInitializer) {
+ WdfObjectDelete(pfhInitializer);
+ }
+ return status;
+}
+
+NTSTATUS
+MCompPoHandleAvailable(
+ _In_ WDFDEVICE Device,
+ _In_ POHANDLE PoHandle
+ )
+{
+ PDEVICE_EXTENSION devExt = NULL;
+ ULONG i;
+
+ //
+ // Get the device extension
+ //
+ devExt = DeviceGetData(Device);
+
+ //
+ // Save the POHANDLE
+ //
+ devExt->PoHandle = PoHandle;
+
+ //
+ // Provide latency and residency hints to enable the power framework to
+ // select lower-powered F-states when we are idle.
+ //
+ for (i=0; i < COMPONENT_COUNT; i++) {
+ PoFxSetComponentLatency(
+ PoHandle,
+ i,
+ (TRANSITION_LATENCY_F1 + 1)
+ );
+ PoFxSetComponentResidency(
+ PoHandle,
+ i,
+ (RESIDENCY_REQUIREMENT_F1 + 1)
+ );
+ }
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+MCompPoHandleUnavailable(
+ _In_ WDFDEVICE Device,
+ _In_ POHANDLE PoHandle
+ )
+{
+ PDEVICE_EXTENSION devExt = NULL;
+
+ //
+ // Get the device extension
+ //
+ devExt = DeviceGetData(Device);
+
+ //
+ // Clear the POHANDLE. It is not guaranteed to remain valid after we return
+ // from this callback.
+ //
+ devExt->PoHandle = PoHandle;
+
+ return;
+}
+
+NTSTATUS
+MCompEvtDeviceD0Entry(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE PreviousState
+ )
+/*++
+Routine Description:
+
+ In this routine the driver enters D0
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ PreviousState - Previous device power state
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(PreviousState);
+
+ HwSimD0Entry(Device);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MCompEvtDeviceD0Exit(
+ _In_ WDFDEVICE Device,
+ _In_ WDF_POWER_DEVICE_STATE TargetState
+ )
+/*++
+Routine Description:
+
+ In this routine the driver leaves D0
+
+Arguments:
+
+ Device - Handle to the framework device object
+
+ TargetState - Device power state that the device is about to enter
+
+Return Value:
+
+ An NTSTATUS value representing success or failure of the function.
+
+--*/
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(TargetState);
+
+ HwSimD0Exit(Device);
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+MCompComponentIdleStateCallback(
+ _In_ PVOID Context,
+ _In_ ULONG Component,
+ _In_ ULONG State
+ )
+/*++
+Routine Description:
+
+ The power framework helper invokes this routine to change the F-state of one
+ of our components.
+
+Arguments:
+
+ Context - Context that we passed in to our power framework helper module
+ when we asked it to register with the power framework helper on our behalf
+
+ Component - Index of component for which the F-state change is to be made
+
+ State - The new F-state to transition the component to
+
+Return Value:
+
+ None
+
+--*/
+{
+ PDEVICE_EXTENSION devExt = NULL;
+ WDFDEVICE device = NULL;
+
+ //
+ // Get the device object handle
+ //
+ device = (WDFDEVICE) Context;
+
+ //
+ // Get the device extension
+ //
+ devExt = DeviceGetData(device);
+
+ //
+ // Change the F-state of the component
+ // This includes hardware-specific operations such as:
+ // * disabling/enabling DMA capabilities associated with the component
+ // * disabling/enabling interrupts associated with the component
+ // * saving/restoring component state
+ //
+ HwSimFStateChange(device, Component, State);
+
+ //
+ // F-state transition complete
+ //
+ PoFxCompleteIdleState(devExt->PoHandle, Component);
+ return;
+}
+
+VOID
+MCompEvtIoDeviceControlPrimary(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode
+ )
+/*++
+Routine Description:
+
+ This routine is the IOCTL handler for the device's primary queue
+
+Arguments:
+
+ Queue - Handle to the framework queue object for the primary queue
+
+ Request - Handle to the framework request object for IOCTL being dispatched
+
+ OutputBufferLength - Output buffer length for IOCTL
+
+ InputBufferLength - Input buffer length for IOCTL
+
+ IoControlCode - IOCTL code
+
+Return Value:
+
+ None
+
+--*/
+{
+ NTSTATUS status;
+ PPOWERFX_READ_COMPONENT_INPUT inputBuffer = NULL;
+ WDFDEVICE device = NULL;
+ PDEVICE_EXTENSION devExt = NULL;
+ WDFQUEUE componentQueue = NULL;
+ ULONG component;
+
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ switch (IoControlCode) {
+ case IOCTL_POWERFX_READ_COMPONENT:
+ {
+ //
+ // Validate input buffer length
+ //
+ if (InputBufferLength != sizeof(*inputBuffer)) {
+ status = STATUS_INVALID_PARAMETER;
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! -Invalid input buffer size. Expected: %d. "
+ "Actual: %I64u. %!status!.",
+ sizeof(*inputBuffer),
+ InputBufferLength,
+ status);
+ goto exit;
+ }
+
+ //
+ // Identify the component that we need to read in order to satisfy
+ // this request
+ //
+ status = WdfRequestRetrieveInputBuffer(Request,
+ sizeof(*inputBuffer),
+ (PVOID*) &inputBuffer,
+ NULL // Length
+ );
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfRequestRetrieveInputBuffer failed with "
+ "%!status!.",
+ status);
+ goto exit;
+ }
+ component = inputBuffer->ComponentNumber;
+
+ //
+ // Identify the queue corresponding to the above component
+ //
+ device = WdfIoQueueGetDevice(Queue);
+ devExt = DeviceGetData(device);
+ componentQueue = devExt->Queue[component];
+ }
+ break;
+
+ default:
+ {
+ status = STATUS_INVALID_PARAMETER;
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - Unexpected IOCTL code %d. %!status!.",
+ IoControlCode,
+ status);
+ goto exit;
+ }
+ }
+
+ //
+ // Forward the request to the appropriate queue. We do this via the power
+ // framework helper so that it can take a power reference on behalf of the
+ // request.
+ //
+ PfhForwardRequestToQueue(Request, componentQueue);
+
+ status = STATUS_SUCCESS;
+
+exit:
+ if (FALSE == NT_SUCCESS(status)) {
+ //
+ // Complete the request in case of failure. In case of success, we would
+ // have dispatched the request to the component-specific queue, so we
+ // don't need to complete it here.
+ //
+ PfhCompleteRequest(Request, status, 0 /* Information */);
+ }
+
+ return;
+}
+
+VOID
+MCompEvtIoDeviceControlSecondary(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode
+ )
+/*++
+Routine Description:
+
+ This routine is the IOCTL handler for the device's secondary queue (i.e.
+ component-specific queue).
+
+Arguments:
+
+ Queue - Handle to the framework queue object for the secondary queue
+
+ Request - Handle to the framework request object for IOCTL being dispatched
+
+ OutputBufferLength - Output buffer length for IOCTL
+
+ InputBufferLength - Input buffer length for IOCTL
+
+ IoControlCode - IOCTL code
+
+Return Value:
+
+ None
+
+--*/
+{
+ NTSTATUS status;
+ PPOWERFX_READ_COMPONENT_INPUT inputBuffer = NULL;
+ PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer = NULL;
+ WDFDEVICE device = NULL;
+ ULONG component;
+ ULONG componentData;
+ ULONG_PTR information = 0;
+
+ //
+ // When we complete the request, make sure we don't get the I/O manager to
+ // copy any more data to the client address space than what we write to the
+ // output buffer. The only data that we write to the output buffer is the
+ // component data and the C_ASSERT below ensures that the output buffer does
+ // not have room to contain anything other than that.
+ //
+ C_ASSERT(sizeof(componentData) == sizeof(*outputBuffer));
+
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(IoControlCode);
+
+ //
+ // The following ASSERTMSG checks should have already been made by the IOCTL
+ // dispatch routine for the primary queue. That routine should have
+ // completed the request with failure if the checks had failed. Therefore we
+ // only use ASSERTMSG here.
+ //
+ ASSERTMSG("Unexpected IOCTL code\n",
+ IOCTL_POWERFX_READ_COMPONENT == IoControlCode);
+ ASSERTMSG("Invalid input buffer size",
+ InputBufferLength == sizeof(*inputBuffer));
+
+ //
+ // Validate output buffer length
+ //
+ if (OutputBufferLength != sizeof(*outputBuffer)) {
+ status = STATUS_INVALID_PARAMETER;
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! -Invalid input buffer size. Expected: %d. Actual: %I64u."
+ " %!status!.",
+ sizeof(*outputBuffer),
+ OutputBufferLength,
+ status);
+ goto exit;
+ }
+
+ //
+ // Identify the component that we need to read in order to satisfy
+ // this request.
+ //
+ status = WdfRequestRetrieveInputBuffer(Request,
+ sizeof(*inputBuffer),
+ (PVOID*) &inputBuffer,
+ NULL // Length
+ );
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfRequestRetrieveInputBuffer failed with %!status!.",
+ status);
+ goto exit;
+ }
+ component = inputBuffer->ComponentNumber;
+
+ //
+ // Get the output buffer
+ //
+ status = WdfRequestRetrieveOutputBuffer(Request,
+ sizeof(*outputBuffer),
+ (PVOID*) &outputBuffer,
+ NULL // Length
+ );
+ if (FALSE == NT_SUCCESS(status)) {
+ Trace(TRACE_LEVEL_ERROR,
+ "%!FUNC! - WdfRequestRetrieveOutputBuffer failed with %!status!.",
+ status);
+ goto exit;
+ }
+
+ //
+ // Read the data from the component
+ //
+ device = WdfIoQueueGetDevice(Queue);
+ componentData = HwSimReadComponent(device, component);
+ outputBuffer->ComponentData = componentData;
+ information = sizeof(*outputBuffer);
+
+ status = STATUS_SUCCESS;
+
+exit:
+ //
+ // Complete the request
+ //
+ PfhCompleteRequest(Request, status, information);
+ return;
+}
diff --git a/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.h b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.h
new file mode 100644
index 00000000..0d56edc8
--- /dev/null
+++ b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.h
@@ -0,0 +1,114 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ WdfMultiComp.h
+
+Abstract:
+ Header file for the KMDF sample driver for a multi-component device.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#if !defined(_WDFMULTICOMP_H_)
+#define _WDFMULTICOMP_H_
+
+
+#include <ntddk.h>
+#include <wdf.h>
+#include "AppInterface.h"
+#include "WdfPoFx.h"
+
+//
+// Some dummy values
+//
+#define TRANSITION_LATENCY_F1 WDF_ABS_TIMEOUT_IN_MS(5) // 5 milliseconds
+#define RESIDENCY_REQUIREMENT_F1 WDF_ABS_TIMEOUT_IN_MS(50) // 50 milliseconds
+
+//
+// This structure contains the driver's power framework settings
+//
+typedef struct _PO_FX_DEVICE_MCOMP_EXT {
+ PO_FX_DEVICE PoFxDevice;
+ PO_FX_COMPONENT AdditionalComponents[COMPONENT_COUNT-1];
+} PO_FX_DEVICE_MCOMP_EXT, *PPO_FX_DEVICE_MCOMP_EXT;
+
+//
+// This structure represents the driver's device context space
+//
+typedef struct _DEVICE_EXTENSION {
+ //
+ // Array of component queues
+ //
+ WDFQUEUE Queue[COMPONENT_COUNT];
+
+ //
+ // POHANDLE representing the device's registration with the power framework
+ //
+ POHANDLE PoHandle;
+
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, DeviceGetData)
+
+//
+// Driver's KMDF callbacks
+//
+DRIVER_INITIALIZE DriverEntry;
+EVT_WDF_OBJECT_CONTEXT_CLEANUP MCompEvtDriverCleanup;
+EVT_WDF_DRIVER_DEVICE_ADD MCompEvtDeviceAdd;
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL MCompEvtIoDeviceControlPrimary;
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL MCompEvtIoDeviceControlSecondary;
+EVT_WDF_DEVICE_D0_ENTRY MCompEvtDeviceD0Entry;
+EVT_WDF_DEVICE_D0_EXIT MCompEvtDeviceD0Exit;
+
+//
+// Driver's power framework callbacks
+//
+PO_FX_COMPONENT_IDLE_STATE_CALLBACK MCompComponentIdleStateCallback;
+
+//
+// Driver's power framework helper callbacks
+//
+PFH_CALLBACK_POHANDLE_AVAILABLE MCompPoHandleAvailable;
+PFH_CALLBACK_POHANDLE_UNAVAILABLE MCompPoHandleUnavailable;
+
+//
+// Define the tracing flags.
+//
+// TODO: Use a different trace control GUID below
+//
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ WdfMCompTraceControl, (C3061C7C,5719,4700,BD4D,A12B40347632), \
+ WPP_DEFINE_BIT(WDFMCOMP_ALL_INFO) \
+ )
+
+#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
+ WPP_LEVEL_LOGGER(flag)
+
+#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
+ (WPP_LEVEL_ENABLED(flag) && \
+ WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
+
+//
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+// FUNC Trace{FLAG=WDFMCOMP_ALL_INFO}(LEVEL, MSG, ...);
+// end_wpp
+//
+
+
+#endif // _WDFMULTICOMP_H_
diff --git a/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.inx b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.inx
new file mode 100644
index 00000000..e6b93ed0
--- /dev/null
+++ b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.inx
@@ -0,0 +1,79 @@
+;
+; WdfMultiComp.inf
+;
+
+[Version]
+Signature="$Windows NT$"
+Class=Sample
+ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
+Provider=%MSFT%
+CatalogFile=KmdfSamples.cat
+DriverVer=03/27/2011,0.0.0.1
+
+[DestinationDirs]
+WdfMultiCompDriverCopy=12 ; copy to drivers
+CoInstaller_CopyFiles = 11; copy to system32
+
+[SourceDisksNames]
+1 = %MediaDescription%
+
+[SourceDisksFiles]
+WdfMultiComp.sys=1
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1
+
+; =================== Class install ==================================
+
+[ClassInstall32]
+AddReg=SampleClassReg
+
+[SampleClassReg]
+HKR,,,,%ClassName%
+HKR,,Icon,,-5
+
+; =================== KMDF Multi-Component Device ==================================
+
+[Manufacturer]
+%MSFT%=Microsoft,NT$ARCH$
+
+[Microsoft.NT$ARCH$]
+%WdfMultiCompDeviceName%=WdfMultiComp_Install,WDF\WdfMultiComp
+
+[WdfMultiComp_Install.NT]
+CopyFiles=WdfMultiCompDriverCopy
+
+[WdfMultiCompDriverCopy]
+WdfMultiComp.sys
+
+[WdfMultiComp_Install.NT.Services]
+AddService=WdfMultiComp,0x000001fa,WdfMultiComp_ServiceInstall
+
+[WdfMultiComp_ServiceInstall]
+ServiceType=1
+StartType=3
+ErrorControl=1
+ServiceBinary=%12%\WdfMultiComp.sys
+
+[WdfMultiComp_Install.NT.CoInstallers]
+AddReg=CoInstaller_AddReg
+CopyFiles=CoInstaller_CopyFiles
+
+[CoInstaller_AddReg]
+HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
+
+[CoInstaller_CopyFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
+
+[WdfMultiComp_Install.NT.Wdf]
+KmdfService = WdfMultiComp, WdfMultiComp_wdfsect
+
+[WdfMultiComp_wdfsect]
+KmdfLibraryVersion=$KMDFVERSION$
+
+; =================== Generic ==================================
+
+[Strings]
+MSFT="Microsoft"
+MediaDescription="KMDF Multi-Component Device Driver Installation Media"
+ClassName="Sample Device"
+WdfMultiCompDeviceName="KMDF Multi-Component Device"
+
diff --git a/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj
new file mode 100644
index 00000000..c0905b5a
--- /dev/null
+++ b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{45DBDC5F-2109-432B-8149-29D3693D57E1}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{5F84F53D-DFA0-47A1-9759-FC7CFFC9599C}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="WdfMultiComp.c; HwSim.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppScanConfigurationData>WdfMultiComp.h</WppScanConfigurationData>
+ </ClCompile>
+ <Inf Include="WdfMultiComp.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\WdfMultiComp.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>WdfMultiComp</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>WdfMultiComp</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>WdfMultiComp</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>WdfMultiComp</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\lib\$(IntDir)\WdfPoFx.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\lib\$(IntDir)\WdfPoFx.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\lib\$(IntDir)\WdfPoFx.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);.\..\lib\$(IntDir)\WdfPoFx.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj.Filters b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj.Filters
new file mode 100644
index 00000000..dfe3aac9
--- /dev/null
+++ b/pofx/WDF/Driver/MultiComp/driver/WdfMultiComp.vcxproj.Filters
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{A5B06A84-D70F-4D83-B76D-FEA4F09EE4FC}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{B738D047-A23C-43C1-9D52-3E0AC54B5C3D}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{9A02D86B-B4BE-4C57-BD3E-ADD87EE33EE9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{000E9CB4-5A60-438C-8F77-72AE7E890BB8}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="HwSim.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="WdfMultiComp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\WdfMultiComp.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include="WdfMultiComp.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+</Project> \ No newline at end of file