summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShantanu Gupta <[email protected]>2020-04-29 10:39:01 -0700
committerGitHub <[email protected]>2020-04-29 10:39:01 -0700
commitbee1573a5ba8d82f089e0dcb2b8113b12d4b60ba (patch)
treeb98da7a083d37b36e8270713d3d8dce7ac879759
parent8fb512ac674df5ba129a69906d450f2a1361136d (diff)
parent5408da620e6039f06de4bc68383ca29bcc209ed2 (diff)
Merge with microsoft/master
Merge with upstream
-rw-r--r--avstream/avscamera/Package/package.VcxProj4
-rw-r--r--avstream/avscamera/mft0/MFT0Impl.cpp4
-rw-r--r--avstream/avscamera/mft0/stdafx.h5
-rw-r--r--avstream/avscamera/sys/AvsCamera.cpp25
-rw-r--r--avstream/avscamera/sys/AvsCamera.vcxproj4
-rw-r--r--avstream/avscamera/sys/AvsCameraFilter.cpp11
-rw-r--r--avstream/avscamera/sys/Capture.cpp17
-rw-r--r--avstream/avscamera/sys/Common.h6
-rw-r--r--avstream/avscamera/sys/Device.cpp22
-rw-r--r--avstream/avscamera/sys/Device.h13
-rw-r--r--avstream/avscamera/sys/PreviewHwSim.cpp32
-rw-r--r--avstream/avscamera/sys/PreviewHwSim.h4
-rw-r--r--avstream/avscamera/sys/Sensor.cpp49
-rw-r--r--avstream/avscamera/sys/Sensor.h14
-rw-r--r--avstream/avscamera/sys/SensorSimulation.cpp82
-rw-r--r--avstream/avscamera/sys/SensorSimulation.h8
-rw-r--r--avstream/avscamera/sys/VideoHwSim.cpp49
-rw-r--r--avstream/avscamera/sys/VideoHwSim.h4
-rw-r--r--avstream/avscamera/sys/avscamera.inx (renamed from avstream/avscamera/sys/avscamera.inf)bin26816 -> 25260 bytes
-rw-r--r--avstream/avscamera/sys/filter.cpp183
-rw-r--r--avstream/avscamera/sys/filter.h8
-rw-r--r--avstream/avscamera/sys/hwsim.cpp46
-rw-r--r--avstream/avscamera/sys/imagecapture.cpp4
-rw-r--r--avstream/avshws/README.md11
-rw-r--r--avstream/avshws/avshws.inf173
-rw-r--r--avstream/avshws/avshws.inxbin0 -> 5974 bytes
-rw-r--r--avstream/avshws/avshws.sln5
-rw-r--r--avstream/avshws/avshws.vcxproj4
-rw-r--r--avstream/avshws/capture.cpp2
-rw-r--r--avstream/avshws/device.cpp25
-rw-r--r--avstream/avshws/hwsim.cpp2
-rw-r--r--avstream/avshws/makefile15
-rw-r--r--avstream/avssamp/Filter.cpp6
-rw-r--r--avstream/avssamp/avssamp.cpp16
-rw-r--r--avstream/avssamp/avssamp.inf93
-rw-r--r--avstream/avssamp/avssamp.inxbin0 -> 3226 bytes
-rw-r--r--avstream/avssamp/avssamp.vcxproj2
-rw-r--r--avstream/avssamp/makefile15
-rw-r--r--avstream/avssamp/video.cpp10
-rw-r--r--avstream/avssamp/wave.cpp2
-rw-r--r--avstream/sampledevicemft/basepin.cpp171
-rw-r--r--avstream/sampledevicemft/basepin.h64
-rw-r--r--avstream/sampledevicemft/common.h11
-rw-r--r--avstream/sampledevicemft/contosodevice.h28
-rw-r--r--avstream/sampledevicemft/custompin.cpp2
-rw-r--r--avstream/sampledevicemft/dllmain.cpp24
-rw-r--r--avstream/sampledevicemft/multipinmft.cpp60
-rw-r--r--avstream/sampledevicemft/multipinmft.h20
-rw-r--r--avstream/sampledevicemft/multipinmft.vcxproj8
-rw-r--r--avstream/sampledevicemft/multipinmft.vcxproj.Filters1
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.cpp396
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.h211
-rw-r--r--avstream/sampledevicemft/multipinmftutils.cpp86
-rw-r--r--avstream/sampledevicemft/packages.config4
-rw-r--r--avstream/sampledevicemft/stdafx.h7
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inxbin10266 -> 4248 bytes
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj2
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj2
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj2
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp74
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp856
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h155
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp192
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h144
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp1217
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h328
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp254
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h187
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp794
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h423
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp375
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h56
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h80
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp156
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h111
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inxbin3190 -> 0 bytes
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj30
-rw-r--r--general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h26
-rw-r--r--gpio/samples/simdevice/umdf/simdeviceumdf.inxbin3958 -> 1929 bytes
-rw-r--r--tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c3
-rw-r--r--video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj150
-rw-r--r--video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters22
-rw-r--r--video/IndirectDisplay/IddSampleApp/main.cpp93
-rw-r--r--video/IndirectDisplay/IddSampleDriver.sln53
-rw-r--r--video/IndirectDisplay/IddSampleDriver/Driver.cpp686
-rw-r--r--video/IndirectDisplay/IddSampleDriver/Driver.h103
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.infbin0 -> 4580 bytes
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc10
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj319
-rw-r--r--video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters39
-rw-r--r--video/IndirectDisplay/IddSampleDriver/Trace.h63
-rw-r--r--video/IndirectDisplay/README.md48
92 files changed, 4793 insertions, 4328 deletions
diff --git a/avstream/avscamera/Package/package.VcxProj b/avstream/avscamera/Package/package.VcxProj
index 5b8aa6ef..92690b1a 100644
--- a/avstream/avscamera/Package/package.VcxProj
+++ b/avstream/avscamera/Package/package.VcxProj
@@ -42,22 +42,18 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/avstream/avscamera/mft0/MFT0Impl.cpp b/avstream/avscamera/mft0/MFT0Impl.cpp
index 992be0e9..26d40f99 100644
--- a/avstream/avscamera/mft0/MFT0Impl.cpp
+++ b/avstream/avscamera/mft0/MFT0Impl.cpp
@@ -1950,14 +1950,14 @@ HRESULT CSocMft0::ParseMetadata_FaceDetection(
}
PMETADATA_FACEDATA pFaceData = (PMETADATA_FACEDATA)(pFaceHeader + 1);
UINT32 cbRectSize = sizeof(FaceRectInfoBlobHeader) + (sizeof(FaceRectInfo) * (pFaceHeader->Count));
- BYTE *pRectBuf = new BYTE[cbRectSize];
+ BYTE *pRectBuf = new (std::nothrow) BYTE[cbRectSize];
if (pRectBuf == NULL)
{
return E_OUTOFMEMORY;
}
UINT32 cbCharSize = sizeof(FaceCharacterizationBlobHeader) + (sizeof(FaceCharacterization) * (pFaceHeader->Count));
- BYTE *pCharBuf = new BYTE[cbCharSize];
+ BYTE *pCharBuf = new (std::nothrow) BYTE[cbCharSize];
if (pCharBuf == NULL)
{
delete[] pRectBuf;
diff --git a/avstream/avscamera/mft0/stdafx.h b/avstream/avscamera/mft0/stdafx.h
index 037376ec..6d784805 100644
--- a/avstream/avscamera/mft0/stdafx.h
+++ b/avstream/avscamera/mft0/stdafx.h
@@ -16,7 +16,12 @@
#endif
#include "targetver.h"
+#if (NTDDI_VERSION >= NTDDI_WIN10_VB)
+#pragma message("MFT0 is deprecated for this target Windows version and beyond- Change project settings to target an older version of Windows")
+#endif
+
#if (NTDDI_VERSION <= NTDDI_WIN7)
+// TODO: disable the MFT0 conditional to the target system version
#pragma message("MFT0 is in not supported in this target Windows version - Change project settings to target a newer version of Windows")
#endif
diff --git a/avstream/avscamera/sys/AvsCamera.cpp b/avstream/avscamera/sys/AvsCamera.cpp
index 3563b3dd..3c51323f 100644
--- a/avstream/avscamera/sys/AvsCamera.cpp
+++ b/avstream/avscamera/sys/AvsCamera.cpp
@@ -29,13 +29,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -48,13 +42,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
PVOID
@@ -67,14 +55,7 @@ operator new[](
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag);
-
- if (result)
- {
- RtlZeroMemory(result, iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType, iSize, tag);
}
/*++
diff --git a/avstream/avscamera/sys/AvsCamera.vcxproj b/avstream/avscamera/sys/AvsCamera.vcxproj
index 326b1848..81d0078b 100644
--- a/avstream/avscamera/sys/AvsCamera.vcxproj
+++ b/avstream/avscamera/sys/AvsCamera.vcxproj
@@ -232,7 +232,7 @@
<ResourceCompile Include="AvsCamera.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
@@ -244,4 +244,4 @@
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/avstream/avscamera/sys/AvsCameraFilter.cpp b/avstream/avscamera/sys/AvsCameraFilter.cpp
index af25b691..1a41997a 100644
--- a/avstream/avscamera/sys/AvsCameraFilter.cpp
+++ b/avstream/avscamera/sys/AvsCameraFilter.cpp
@@ -221,7 +221,7 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItems)
CCaptureFilter::SetRoiIspControl,
NULL, 0, NULL, NULL, 0
),
- DEFINE_PROP_ITEM(CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM, CExtendedVidProcSetting, Zoom),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM, CExtendedVidProcSetting, Zoom),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR, CExtendedProperty, VideoHDR ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VFR, CExtendedProperty, VFR ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED, CExtendedVidProcSetting, IsoAdvanced ),
@@ -230,7 +230,8 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItems)
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_OIS, CExtendedProperty, OpticalImageStabilization ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO, CExtendedProperty, AdvancedPhoto ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile ),
- DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING, CExtendedProperty, VideoTemporalDenoising)
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING, CExtendedProperty, VideoTemporalDenoising),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANELOPTIMIZATION, CExtendedProperty, RelativePanel)
};
// Front-facing cameras often have limited capabilities. One way to express that is to use a restricted automation table such as this one.
@@ -244,6 +245,7 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItemsFFC)
DEFINE_PROP_ITEM_NO_SET( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_MAXVIDFPS_PHOTORES, CExtendedMaxVideoFpsForPhotoRes, MaxVideoFpsForPhotoRes ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE, CExtendedProperty, SceneMode ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_TORCHMODE, CExtendedProperty, TorchMode ),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE, CExtendedVidProcSetting, IRTorch ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_OPTIMIZATIONHINT, CExtendedProperty, OptimizationHint ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE, CExtendedVidProcSetting, WhiteBalance ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE, CExtendedVidProcSetting, Exposure ),
@@ -258,11 +260,12 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItemsFFC)
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED, CExtendedVidProcSetting, IsoAdvanced ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOSTABILIZATION, CExtendedProperty, VideoStabilization ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO, CExtendedProperty, AdvancedPhoto ),
- DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile )
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile ),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANELOPTIMIZATION, CExtendedProperty, RelativePanel)
};
//--------------------------------------------------------------
-// Legacy Camera Contorl properties
+// Legacy Camera Control properties
DEFINE_KSPROPERTY_TABLE(CameraControlPropertyTable)
{
DEFINE_PROP_ITEM_WITH_VALUES(CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXPOSURE, KSPROPERTY_CAMERACONTROL_S, Exposure, &ExposureValues),
diff --git a/avstream/avscamera/sys/Capture.cpp b/avstream/avscamera/sys/Capture.cpp
index e5d43ddd..25e6a5f8 100644
--- a/avstream/avscamera/sys/Capture.cpp
+++ b/avstream/avscamera/sys/Capture.cpp
@@ -266,7 +266,7 @@ Return Value:
(m_Pin->ConnectionFormat))->ImageInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), ConnectionHeader->biSize + KS_SIZE_PREHEADER),
AVSHWS_POOLTAG
@@ -308,7 +308,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), KS_SIZE_VIDEOHEADER (ConnectionHeader)),
AVSHWS_POOLTAG
@@ -339,7 +339,7 @@ Return Value:
VideoInfoHeader2);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag(
+ ExAllocatePoolZero(
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), ConnectionHeader->bmiHeader.biSize + KS_SIZE_PREHEADER),
AVSHWS_POOLTAG
@@ -2100,7 +2100,18 @@ Return Value:
{
PAGED_CODE( );
+ // If the host process did not stop the pin, we need to do that before
+ // the CCapturePin object gets freed.
+ if (m_Pin->DeviceState != KSSTATE_STOP)
+ {
+ // Skip straight to the STOP state because our simulation doesn't
+ // really need the PAUSE and ACQUIRE transitions when stopping.
+ SetState(KSSTATE_STOP, m_Pin->DeviceState);
+ }
+
// Some reasonable default behavior.
+ GetFilter()->setPin(nullptr, m_Pin->Id);
+
return STATUS_SUCCESS;
}
diff --git a/avstream/avscamera/sys/Common.h b/avstream/avscamera/sys/Common.h
index fdcb1c48..7cde102f 100644
--- a/avstream/avscamera/sys/Common.h
+++ b/avstream/avscamera/sys/Common.h
@@ -23,11 +23,15 @@
#define _NO_SYS_GUID_OPERATOR_EQ_
+#ifdef NTDDI_VERSION
+#undef NTDDI_VERSION
+#endif //NTDDI_VERSION
+#define NTDDI_VERSION NTDDI_WIN10_VB
+
#include <stdio.h>
#include <stdlib.h>
#include <wdm.h>
-#include <wdmguid.h>
#include <windef.h>
#include <unknown.h>
#include <ks.h>
diff --git a/avstream/avscamera/sys/Device.cpp b/avstream/avscamera/sys/Device.cpp
index 99bc60ce..2741da08 100644
--- a/avstream/avscamera/sys/Device.cpp
+++ b/avstream/avscamera/sys/Device.cpp
@@ -33,6 +33,10 @@
#pragma code_seg("PAGE")
#endif // ALLOC_PRAGMA
+#ifndef DEVPKEY_Device_PanelId
+DEFINE_DEVPROPKEY(DEVPKEY_Device_PanelId, 0x8dbc9c86, 0x97a9, 0x4bff, 0x9b, 0xc6, 0xbf, 0xe9, 0x5d, 0x3e, 0x6d, 0xad, 2); // DEVPROP_TYPE_STRING
+#endif
+
CCaptureDevice::
CCaptureDevice (
_In_ PKSDEVICE Device
@@ -616,9 +620,12 @@ Return Value:
pld.Revision = 2;
pld.Panel = m_Context[i].AcpiPosition;
pld.Rotation = m_Context[i].AcpiRotation;
- static
- const
- GUID FFC_Filter = {STATIC_FrontCamera_Filter};
+ pld.CabinetNumber = 0;
+ WCHAR PanelId[MAX_PATH] = { 0 };
+ size_t cchDest = MAX_PATH;
+
+ IFFAILED_EXIT(
+ RtlStringCchPrintfW(PanelId, cchDest, L"{00000000-0000-0000-ffff-ffffffffffff}\\%04X\\%u", pld.CabinetNumber, PnpAcpiPanelSideMap[pld.Panel]));
IFFAILED_EXIT(
IoSetDeviceInterfacePropertyData(SymbolicLinkName,
@@ -629,6 +636,15 @@ Return Value:
sizeof(pld),
(PVOID)&pld)
);
+
+ // Also set Panel ID manually, because PnP does not do this for the interface currently
+ IoSetDeviceInterfacePropertyData(SymbolicLinkName,
+ &DEVPKEY_Device_PanelId,
+ LOCALE_NEUTRAL,
+ PLUGPLAY_PROPERTY_PERSISTENT,
+ DEVPROP_TYPE_STRING,
+ (ULONG)(wcslen(PanelId)+1)*sizeof(WCHAR),
+ (PVOID)PanelId);
}
// On a real device this object would be constructed whenever the sensor hardware is ready...
diff --git a/avstream/avscamera/sys/Device.h b/avstream/avscamera/sys/Device.h
index 95debada..c203f70e 100644
--- a/avstream/avscamera/sys/Device.h
+++ b/avstream/avscamera/sys/Device.h
@@ -34,6 +34,17 @@ struct CSensorContext
AcpiPldRotation AcpiRotation; // How the device is oriented with respect to the panel.
};
+static constexpr ULONG PnpAcpiPanelSideMap[]
+{
+ 1, // AcpiPldPanelTop
+ 2, // AcpiPldPanelBottom
+ 3, // AcpiPldPanelLeft
+ 4, // AcpiPldPanelRight
+ 5, // AcpiPldPanelFront
+ 6, // AcpiPldPanelBack
+ 0, // AcpiPldPanelUnknown
+};
+
class CCaptureDevice
{
protected:
@@ -393,7 +404,7 @@ public:
PDEVICE_OBJECT
GetDeviceObject();
- static IO_COMPLETION_ROUTINE CCaptureDevice::IrpSynchronousCompletion;
+ static IO_COMPLETION_ROUTINE IrpSynchronousCompletion;
virtual
NTSTATUS
diff --git a/avstream/avscamera/sys/PreviewHwSim.cpp b/avstream/avscamera/sys/PreviewHwSim.cpp
index 775c6b8d..f55ffa20 100644
--- a/avstream/avscamera/sys/PreviewHwSim.cpp
+++ b/avstream/avscamera/sys/PreviewHwSim.cpp
@@ -40,6 +40,7 @@ CPreviewHardwareSimulation::CPreviewHardwareSimulation(
_In_ LONG PinID
)
: CHardwareSimulation( Sensor, PinID )
+ , m_Illuminated(FALSE)
{
PAGED_CODE();
}
@@ -299,6 +300,11 @@ Return Value:
BytesLeft -= sizeof(CAMERA_METADATA_INTRINSICS);
}
+ // TODO: This metadata should only be exposed on a sensor category preview pin.
+ // It's possible I should derive a new preview sim to handle this; but for now
+ // we just populate the IR illumination state on every preview pin. Hopefully
+ // the app is smart enough to realize that this is meaningless if they have not
+ // selected an IR mediatype.
if (BytesLeft >= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION))
{
PKSCAMERA_METADATA_FRAMEILLUMINATION pPreviewIllumination =
@@ -308,7 +314,31 @@ Return Value:
pPreviewIllumination->Header.MetadataId = (ULONG)MetadataId_FrameIllumination;
pPreviewIllumination->Header.Size = sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
- pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ // Toggle the Illumination state for an IR frame.
+ CExtendedVidProcSetting State;
+ (void) m_Sensor->GetIRTorch(&State);
+
+ if (State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON)
+ {
+ m_Illuminated = TRUE;
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION))
+ {
+ m_Illuminated = !m_Illuminated;
+ if (m_Illuminated)
+ {
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ }
+ else
+ {
+ m_Illuminated = FALSE;
+ }
+
+ DBG_TRACE("Frame Illumination: Flags=0x%016llX, State=%s",
+ State.Flags,
+ (pPreviewIllumination->Flags==KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON ?"ON":"OFF"));
pMetadata->UsedSize += sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
BytesLeft -= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
diff --git a/avstream/avscamera/sys/PreviewHwSim.h b/avstream/avscamera/sys/PreviewHwSim.h
index e5a4f536..1d26f692 100644
--- a/avstream/avscamera/sys/PreviewHwSim.h
+++ b/avstream/avscamera/sys/PreviewHwSim.h
@@ -43,7 +43,6 @@ public:
protected:
METADATA_PREVIEWAGGREGATION
- CPreviewHardwareSimulation::
GetMetadata();
VOID GetCaptureStats(
@@ -57,5 +56,8 @@ protected:
_Inout_ PKSSTREAM_HEADER pStreamHeader
);
+private:
+ BOOLEAN m_Illuminated;
+
};
diff --git a/avstream/avscamera/sys/Sensor.cpp b/avstream/avscamera/sys/Sensor.cpp
index 9215f6b6..654ea666 100644
--- a/avstream/avscamera/sys/Sensor.cpp
+++ b/avstream/avscamera/sys/Sensor.cpp
@@ -188,7 +188,7 @@ Initialize()
m_InterruptTime[i] = 0;
m_LastMappingsCompleted[i] = 0;
}
- return STATUS_SUCCESS;
+ return m_Device ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
}
void
@@ -356,7 +356,7 @@ CreateSynthesizer(
if( NT_SUCCESS( Status ) )
{
- DBG_TRACE( "Setting Mounting Orientation to %d�", DbgRotation2Degrees(m_MountingOrientation) )
+ DBG_TRACE( "Setting Mounting Orientation to %d°", DbgRotation2Degrees(m_MountingOrientation) )
m_Synthesizer[ Pin->Id ]->SetRotation( m_MountingOrientation );
}
@@ -412,15 +412,17 @@ Return Value:
NTSTATUS Status = STATUS_SUCCESS;
LONG lPindex = Pin->Id;
+
+ // Hold off all image generation while we manipulate the capture pin and synthensizer arrays.
+ KScopedMutex Lock(m_SensorMutex);
+
//
// If we're the first pin to go into acquire (remember we can have
// a filter in another graph going simultaneously), grab the resources for Preview
//
- if( InterlockedCompareExchangePointer(
- (PVOID *) &m_CapturePin[lPindex],
- CapturePin,
- nullptr) == nullptr)
+ if (m_CapturePin[lPindex] == nullptr)
{
+ m_CapturePin[lPindex] = CapturePin;
m_VideoInfoHeader[lPindex] = VideoInfoHeader;
//
@@ -449,7 +451,6 @@ Return Value:
//
// If everything has succeeded thus far, set the capture pin.
//
- m_CapturePin[lPindex] = CapturePin;
*pSim = m_HardwareSimulation[lPindex];
}
@@ -460,6 +461,8 @@ Return Value:
// acquired.
//
ReleaseHardwareResources(Pin);
+ *pSim = nullptr;
+ m_CapturePin[lPindex] = nullptr;
}
}
else
@@ -1088,20 +1091,23 @@ Return Value:
void
CSensor::
-SetSynthesizerAttribute(
- CSynthesizer::Attribute Attrib,
- LONGLONG Info,
- LONG PinId
+SetSynthesizerAttributeList(
+ _In_ size_t Count,
+ _In_ SynthesizerAttributeEntry AttributeList[]
)
{
PAGED_CODE();
-
- for( ULONG Pin=0; IsValidIndex(Pin); Pin++ )
+ // Syncrhonize access to sensor.
+ KScopedMutex Lock(m_SensorMutex);
+ for (size_t item = 0; item < Count; item++)
{
- if( (Pin==(ULONG)PinId || IsStillIndex(Pin)) &&
- m_Synthesizer[Pin] )
+ for (ULONG Pin = 0; IsValidIndex(Pin); Pin++)
{
- m_Synthesizer[Pin]->Set( Attrib, Info );
+ if ((Pin == (ULONG)AttributeList[item].PinId || IsStillIndex(Pin)) &&
+ m_Synthesizer[Pin])
+ {
+ m_Synthesizer[Pin]->Set(AttributeList[item].Attrib, AttributeList[item].Info);
+ }
}
}
}
@@ -1140,11 +1146,15 @@ Return Value:
DBG_ENTER( "( Pin=%d )\n", Pin->Id ) ;
LONG lPindex = Pin->Id;
+
//
// Blow away the image synth.
//
m_HardwareSimulation[lPindex]->Reset();
+ // Hold off all image generation while we free the capture pin and synthensizer arrays.
+ KScopedMutex Lock(m_SensorMutex);
+
SAFE_DELETE( m_Synthesizer[lPindex] );
m_VideoInfoHeader[lPindex] = NULL;
@@ -1152,10 +1162,7 @@ Return Value:
// Release our "lock" on hardware resources. This will allow another
// pin (perhaps in another graph) to acquire them.
//
- InterlockedExchangePointer(
- (PVOID *) &(m_CapturePin[lPindex]),
- nullptr
- );
+ m_CapturePin[lPindex] = nullptr;
DBG_LEAVE( "( Pin=%d )\n", Pin->Id ) ;
}
@@ -1322,6 +1329,7 @@ DEFINE_NULL_PROPERTY_GET(CSensor, KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, TriggerTime)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, TorchMode)
+DEFINE_NULL_PROPERTY(CSensor, CExtendedVidProcSetting, IRTorch)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, ExtendedFlash)
DEFINE_NULL_PROPERTY_GET(CSensor, CExtendedProperty, PhotoFrameRate)
@@ -1352,6 +1360,7 @@ DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, OptimizationHint)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, AdvancedPhoto)
DEFINE_NULL_PROPERTY(CSensor, CExtendedVidProcSetting, FaceDetection)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, VideoTemporalDenoising)
+DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, RelativePanel)
DEFINE_NULL_PROPERTY(CSensor, KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode)
diff --git a/avstream/avscamera/sys/Sensor.h b/avstream/avscamera/sys/Sensor.h
index 327b860a..31b0f3a2 100644
--- a/avstream/avscamera/sys/Sensor.h
+++ b/avstream/avscamera/sys/Sensor.h
@@ -517,8 +517,18 @@ public:
m_MountingOrientation = Orientation;
}
+ struct SynthesizerAttributeEntry
+ {
+ CSynthesizer::Attribute Attrib;
+ LONGLONG Info;
+ LONG PinId;
+ };
+
void
- SetSynthesizerAttribute( CSynthesizer::Attribute Attrib, LONGLONG Info, LONG PinId );
+ SetSynthesizerAttributeList(
+ _In_ size_t Count,
+ _In_ SynthesizerAttributeEntry AttributeList[]
+ );
protected:
LONG
@@ -554,6 +564,7 @@ public:
DECLARE_PROPERTY( CExtendedProperty, TriggerTime );
DECLARE_PROPERTY( CExtendedProperty, TorchMode );
+ DECLARE_PROPERTY( CExtendedVidProcSetting, IRTorch );
DECLARE_PROPERTY_ASYNC( CExtendedVidProcSetting, Focus );
DECLARE_PROPERTY_ASYNC( CExtendedProperty, Iso );
@@ -576,6 +587,7 @@ public:
DECLARE_PROPERTY( CExtendedProperty, AdvancedPhoto );
DECLARE_PROPERTY( CExtendedVidProcSetting, FaceDetection );
DECLARE_PROPERTY( CExtendedProperty, VideoTemporalDenoising);
+ DECLARE_PROPERTY( CExtendedProperty, RelativePanel);
DECLARE_PROPERTY_VARSIZE_ASYNC( CRoiProperty, Roi );
diff --git a/avstream/avscamera/sys/SensorSimulation.cpp b/avstream/avscamera/sys/SensorSimulation.cpp
index 6ecd9007..e60372c1 100644
--- a/avstream/avscamera/sys/SensorSimulation.cpp
+++ b/avstream/avscamera/sys/SensorSimulation.cpp
@@ -331,6 +331,15 @@ Return Value:
}
m_TorchMode.Flags = KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF;
m_TorchMode = 50UL;
+ m_IRTorch.Flags = KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON;
+ m_IRTorch.Capability =
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_OFF |
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON |
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION;
+ m_IRTorch = 100UL;
+ m_IRTorch.Min() = 20;
+ m_IRTorch.Max() = 100;
+ m_IRTorch.Step() = 5;
m_OptimizationHint.Flags = KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO;
@@ -471,6 +480,14 @@ Return Value:
m_PowerLineFreq.Value = POWERLINEFREQ_DEFAULT;
m_PowerLineFreq.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ // Set up our relative panel.
+ m_RelativePanel.Capability =
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_DYNAMIC;
+ m_RelativePanel.Flags = KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF;
+ m_RelativePanel = (ULONG)AcpiPldPanelUnknown;
+
m_IsoResult = STATUS_SUCCESS;
m_EvCompResult = STATUS_SUCCESS;
m_WhiteBalanceResult= STATUS_SUCCESS;
@@ -1791,6 +1808,40 @@ SetOpticalImageStabilization(
return STATUS_SUCCESS;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CSensorSimulation::
+GetRelativePanel(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pProperty = m_RelativePanel;
+ pProperty->Flags = m_RelativePanel.Flags;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_DYNAMIC;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CSensorSimulation::
+SetRelativePanel(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ m_RelativePanel = *pProperty;
+ m_RelativePanel.Flags = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING.
NTSTATUS
CSensorSimulation::
@@ -3024,6 +3075,37 @@ SetTorchMode(
return STATUS_SUCCESS;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CSensorSimulation::
+GetIRTorch(
+ _Inout_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pTorch = m_IRTorch;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CSensorSimulation::
+SetIRTorch(
+ _In_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ // Only overwrite the IR Torch Flags and value.
+ m_IRTorch.Flags = pTorch->Flags;
+ m_IRTorch = pTorch->GetULONG();
+
+ return STATUS_SUCCESS;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE
NTSTATUS
CSensorSimulation::
diff --git a/avstream/avscamera/sys/SensorSimulation.h b/avstream/avscamera/sys/SensorSimulation.h
index a2dd1fe7..6124762c 100644
--- a/avstream/avscamera/sys/SensorSimulation.h
+++ b/avstream/avscamera/sys/SensorSimulation.h
@@ -50,6 +50,7 @@ protected:
ULONG m_FaceDetectionCurrentMax;
ULONGLONG m_SceneMode;
CExtendedProperty m_TorchMode;
+ CExtendedVidProcSetting m_IRTorch;
CExtendedProperty m_OptimizationHint;
CExtendedMetadata *m_MetadataInfo;
PKSCAMERA_PERFRAMESETTING_HEADER m_pPerFrameSettings;
@@ -61,7 +62,8 @@ protected:
ULONGLONG m_Histogram;
ULONGLONG m_OpticalImageStabilization;
ULONGLONG m_VideoTemporalDenoising;
- CExtendedProperty m_AdvancedPhoto;
+ CExtendedProperty m_RelativePanel;
+ CExtendedProperty m_AdvancedPhoto;
CWhiteBalanceRoiIspControl m_RoiWhiteBalance;
CExposureRoiIspControl m_RoiExposureMode;
@@ -207,6 +209,7 @@ public:
DECLARE_PROPERTY_GET( KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_S, PinDependence );
DECLARE_PROPERTY( CExtendedProperty, TriggerTime );
DECLARE_PROPERTY( CExtendedProperty, TorchMode );
+ DECLARE_PROPERTY( CExtendedVidProcSetting, IRTorch );
DECLARE_PROPERTY( CExtendedProperty, ExtendedFlash );
@@ -236,6 +239,7 @@ public:
DECLARE_PROPERTY_GET( CExtendedFieldOfView, FieldOfView );
DECLARE_PROPERTY_GET( CExtendedCameraAngleOffset, CameraAngleOffset );
DECLARE_PROPERTY( CExtendedProperty, VideoTemporalDenoising);
+ DECLARE_PROPERTY( CExtendedProperty, RelativePanel);
DECLARE_PROPERTY_VARSIZE_ASYNC_NOCANCEL( CRoiProperty, Roi );
@@ -288,4 +292,4 @@ const LONG WHITEBALANCE_DEF = 5000;
const LONG EXPOSURE_BILOG_MIN = -10;
const LONG EXPOSURE_BILOG_MAX = 9;
const LONG EXPOSURE_BILOG_STEP = 1;
-const LONG EXPOSURE_BILOG_DEF = -5; \ No newline at end of file
+const LONG EXPOSURE_BILOG_DEF = -5;
diff --git a/avstream/avscamera/sys/VideoHwSim.cpp b/avstream/avscamera/sys/VideoHwSim.cpp
index 33b6de90..839af530 100644
--- a/avstream/avscamera/sys/VideoHwSim.cpp
+++ b/avstream/avscamera/sys/VideoHwSim.cpp
@@ -27,6 +27,7 @@ CVideoHardwareSimulation::CVideoHardwareSimulation(
_In_ LONG PinID
)
: CHardwareSimulation( Sensor, PinID )
+ , m_Illuminated(FALSE)
{}
@@ -50,6 +51,54 @@ EmitMetadata(
if (0 != (pStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_METADATA))
{
+ PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO)(pStreamHeader + 1);
+ PKSSTREAM_METADATA_INFO pMetadata = (PKSSTREAM_METADATA_INFO)(pFrameInfo + 1);
+ ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize;
+
+ // TODO: This metadata should only be exposed on a sensor category preview pin.
+ // It's possible I should derive a new preview sim to handle this; but for now
+ // we just populate the IR illumination state on every preview pin. Hopefully
+ // the app is smart enough to realize that this is meaningless if they have not
+ // selected an IR mediatype.
+ if (BytesLeft >= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION))
+ {
+ PKSCAMERA_METADATA_FRAMEILLUMINATION pPreviewIllumination =
+ (PKSCAMERA_METADATA_FRAMEILLUMINATION)(((PBYTE)pMetadata->SystemVa) + pMetadata->UsedSize);
+ RtlZeroMemory(pPreviewIllumination, sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION));
+
+ pPreviewIllumination->Header.MetadataId = (ULONG)MetadataId_FrameIllumination;
+ pPreviewIllumination->Header.Size = sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+
+ // Toggle the Illumination state for an IR frame.
+ CExtendedVidProcSetting State;
+ (void)m_Sensor->GetIRTorch(&State);
+
+ if (State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON)
+ {
+ m_Illuminated = TRUE;
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION))
+ {
+ m_Illuminated = !m_Illuminated;
+ if (m_Illuminated)
+ {
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ }
+ else
+ {
+ m_Illuminated = FALSE;
+ }
+
+ DBG_TRACE("Frame Illumination: Flags=0x%016llX, State=%s",
+ State.Flags,
+ (pPreviewIllumination->Flags == KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON ? "ON" : "OFF"));
+
+ pMetadata->UsedSize += sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+ BytesLeft -= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+ }
+
CExtendedVidProcSetting FaceDetect;
m_Sensor->GetFaceDetection(&FaceDetect);
diff --git a/avstream/avscamera/sys/VideoHwSim.h b/avstream/avscamera/sys/VideoHwSim.h
index 40b0b24b..a576d9a1 100644
--- a/avstream/avscamera/sys/VideoHwSim.h
+++ b/avstream/avscamera/sys/VideoHwSim.h
@@ -38,5 +38,9 @@ public:
EmitMetadata(
_Inout_ PKSSTREAM_HEADER pStreamHeader
);
+
+private:
+ BOOLEAN m_Illuminated;
+
};
diff --git a/avstream/avscamera/sys/avscamera.inf b/avstream/avscamera/sys/avscamera.inx
index 2a17a764..f6f1e846 100644
--- a/avstream/avscamera/sys/avscamera.inf
+++ b/avstream/avscamera/sys/avscamera.inx
Binary files differ
diff --git a/avstream/avscamera/sys/filter.cpp b/avstream/avscamera/sys/filter.cpp
index 2680f503..dfb6ce1f 100644
--- a/avstream/avscamera/sys/filter.cpp
+++ b/avstream/avscamera/sys/filter.cpp
@@ -64,6 +64,7 @@ Return Value:
m_pCaptureDevice(NULL),
m_pPerFrameSettings(nullptr),
m_pinArray(nullptr),
+ m_pMinimumRequestedFrames(nullptr),
m_PhotoModeNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE ),
m_PhotoMaxFrameRateNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE) ,
m_FocusNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE ),
@@ -141,10 +142,12 @@ Return Value:
IFFAILED_EXIT( m_Sensor->AddFilter(m_pKSFilter) );
IFNULL_EXIT(m_pinArray = new (PagedPool, 'sniP') CCapturePin *[m_Sensor->GetPinCount()]);
+ IFNULL_EXIT(m_pMinimumRequestedFrames = new (PagedPool, 'sniP') ULONG[m_Sensor->GetPinCount()]);
for( ULONG i=0; i<m_Sensor->GetPinCount(); i++ )
{
m_pinArray[i] = nullptr;
+ m_pMinimumRequestedFrames[i] = IMAGE_CAPTURE_PIN_MINIMUM_FRAMES;
}
done:
@@ -209,6 +212,7 @@ CCaptureFilter::~CCaptureFilter()
// may need to have some things reset.
m_Sensor->Reset();
+ delete [] m_pMinimumRequestedFrames;
delete [] m_pinArray;
DBG_LEAVE("(%S)", Name);
@@ -352,6 +356,11 @@ Return Value:
// Take out a weak reference to the pin object.
m_pinArray[Id] = pPin;
+ if (m_pinArray[Id] != nullptr)
+ {
+ m_pinArray[Id]->SetDesiredFrames(m_pMinimumRequestedFrames[Id]);
+ (void)m_pinArray[Id]->UpdateAllocatorFraming();
+ }
}
CCapturePin *
@@ -391,7 +400,8 @@ Return Value:
NTSTATUS
CCaptureFilter::
UpdateAllocatorFraming(
- _In_ ULONG PinId
+ _In_ ULONG PinId,
+ _In_ ULONG DesiredFrames
)
/*++
@@ -412,15 +422,20 @@ Return Value:
{
PAGED_CODE();
- NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ NTSTATUS Status = STATUS_SUCCESS;
// Acquire the lock and update the Pin's allocator framing.
LockFilter Lock(m_pKSFilter);
if( m_pinArray[PinId] )
{
+ m_pinArray[PinId]->SetDesiredFrames(DesiredFrames);
Status = m_pinArray[PinId]->UpdateAllocatorFraming();
}
+ else
+ {
+ m_pMinimumRequestedFrames[PinId] = DesiredFrames;
+ }
DBG_LEAVE("()=0x%08X",Status);
return Status;
@@ -636,6 +651,7 @@ SetPhotoMode(
PAGED_CODE();
NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ ULONG TotalFrames = IMAGE_CAPTURE_PIN_MINIMUM_FRAMES;
DBG_ENTER( "()" );
@@ -645,10 +661,6 @@ SetPhotoMode(
{
CExtendedPhotoMode Caps(*pMode);
Status = m_Sensor->GetPhotoMode( &Caps );
- CCapturePin *pPin = getPin(pMode->PinId);
-
- // Should always be valid.
- NT_ASSERT(pPin);
if( NT_SUCCESS(Status) )
{
@@ -686,7 +698,7 @@ SetPhotoMode(
// Assume the normal photo sequence case.
// For normal photo sequence, we provide history frames +1 or at least a minimum of 3 frames.
- ULONG TotalFrames = pMode->RequestedHistoryFrames() + 1;
+ TotalFrames = pMode->RequestedHistoryFrames() + 1;
// Modify TotalFrames for the VPS case.
// For VPS, we need LoopCount * FrameCount; but limit by the minimum(3) and maximum (20) frames.
@@ -708,14 +720,12 @@ SetPhotoMode(
DBG_TRACE( "Advertising Framing requirement: %d", TotalFrames );
- pPin->SetDesiredFrames(TotalFrames);
Status = STATUS_SUCCESS;
break;
}
case KSCAMERA_EXTENDEDPROP_PHOTOMODE_NORMAL:
{
// Set it back to the minimum number of frames.
- pPin->SetDesiredFrames(IMAGE_CAPTURE_PIN_MINIMUM_FRAMES);
Status = STATUS_SUCCESS;
break;
}
@@ -724,7 +734,7 @@ SetPhotoMode(
// Update allocator framing.
if( NT_SUCCESS( Status ) )
{
- Status = UpdateAllocatorFraming( pMode->PinId );
+ Status = UpdateAllocatorFraming( pMode->PinId, TotalFrames );
}
// Update the sensor object...
@@ -1118,13 +1128,13 @@ GetTorchMode(
NTSTATUS Status = STATUS_INVALID_PARAMETER;
- if( pTorchMode->isValid() &&
- pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE )
+ if (pTorchMode->isValid() &&
+ pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
{
- Status = m_Sensor->GetTorchMode( pTorchMode );
+ Status = m_Sensor->GetTorchMode(pTorchMode);
}
DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
- pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status );
+ pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status);
return Status;
}
@@ -1139,34 +1149,101 @@ SetTorchMode(
NTSTATUS Status = STATUS_INVALID_PARAMETER;
- if( !(pTorchMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
- pTorchMode->isValid() &&
- pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
- pTorchMode->m_Value.Value.ul <= 100 )
+ if (!(pTorchMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
+ pTorchMode->isValid() &&
+ pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pTorchMode->m_Value.Value.ul <= 100)
{
CExtendedProperty Caps(*pTorchMode);
Status = m_Sensor->GetTorchMode(&Caps);
- if( NT_SUCCESS(Status) )
+ if (NT_SUCCESS(Status))
{
// Assume an invalid parameter.
Status = STATUS_INVALID_PARAMETER;
- if( pTorchMode->Flags == (pTorchMode->Flags & Caps.Capability) )
+ if (pTorchMode->Flags == (pTorchMode->Flags & Caps.Capability))
{
- switch( pTorchMode->Flags )
+ switch (pTorchMode->Flags)
{
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF:
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON:
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON_ADJUSTABLEPOWER:
- Status = m_Sensor->SetTorchMode( pTorchMode );
+ Status = m_Sensor->SetTorchMode(pTorchMode);
break;
}
}
}
}
DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
- pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status );
+ pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status);
+ return Status;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CCaptureFilter::
+GetIRTorch(
+ _Inout_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (pTorch->isValid() &&
+ pTorch->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
+ {
+ Status = m_Sensor->GetIRTorch(pTorch);
+ }
+ DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
+ pTorch->PinId, pTorch->Flags, pTorch->Capability, Status);
+ return Status;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CCaptureFilter::
+SetIRTorch(
+ _In_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (!(pTorch->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
+ pTorch->isValid() &&
+ pTorch->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
+ {
+ CExtendedVidProcSetting Caps(*pTorch);
+ Status = m_Sensor->GetIRTorch(&Caps);
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = Caps.BoundsCheck(pTorch->GetULONG());
+
+ if (NT_SUCCESS(Status))
+ {
+ // Assume an invalid parameter.
+ Status = STATUS_INVALID_PARAMETER;
+
+ if (pTorch->Flags == (pTorch->Flags & Caps.Capability))
+ {
+ switch (pTorch->Flags)
+ {
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_OFF:
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON:
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION:
+ Status = m_Sensor->SetIRTorch(pTorch);
+ break;
+ }
+ }
+ }
+ }
+ }
+ DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
+ pTorch->PinId, pTorch->Flags, pTorch->Capability, Status);
return Status;
}
@@ -3494,6 +3571,66 @@ SetOpticalImageStabilization(
return Status;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CCaptureFilter::
+GetRelativePanel(
+ _Inout_ CExtendedProperty *pRelativePanel
+)
+{
+ PAGED_CODE();
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (pRelativePanel->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pRelativePanel->isValid())
+ {
+ //Get the current state
+ Status = m_Sensor->GetRelativePanel(pRelativePanel);
+ }
+
+ DBG_TRACE("pRelativePanel = %p, PinId = %u, Flags = %llu, Version = %u",
+ pRelativePanel, pRelativePanel->PinId, pRelativePanel->Flags, pRelativePanel->Version);
+
+ return Status;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CCaptureFilter::
+SetRelativePanel(
+ _In_ CExtendedProperty *pRelativePanel
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ // Call must be Filter and flags must be supported and version must be 1
+ if (pRelativePanel->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pRelativePanel->isValid() &&
+ (KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON == pRelativePanel->Flags ||
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF == pRelativePanel->Flags))
+ {
+ CExtendedProperty Caps(*pRelativePanel);
+ Status = m_Sensor->GetRelativePanel(&Caps);
+
+ if (NT_SUCCESS(Status))
+ {
+ // Assume an invalid parameter.
+ Status = STATUS_INVALID_PARAMETER;
+
+ if (pRelativePanel->Flags == (pRelativePanel->Flags & Caps.Capability))
+ {
+ Status = m_Sensor->SetRelativePanel(pRelativePanel);
+ }
+ }
+ }
+ DBG_TRACE("pOIS = %p, PinId = %u, Flags = %llu, Version = %u",
+ pRelativePanel, pRelativePanel->PinId, pRelativePanel->Flags, pRelativePanel->Version);
+
+ return Status;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO.
NTSTATUS
CCaptureFilter::
diff --git a/avstream/avscamera/sys/filter.h b/avstream/avscamera/sys/filter.h
index 292a6bc7..5b272a9d 100644
--- a/avstream/avscamera/sys/filter.h
+++ b/avstream/avscamera/sys/filter.h
@@ -58,6 +58,7 @@ private:
// The AVStream filter object associated with this CCaptureFilter.
//
CCapturePin **m_pinArray;
+ ULONG *m_pMinimumRequestedFrames;
protected:
//
@@ -331,7 +332,9 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, Thumbnail )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, TriggerTime )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, TorchMode )
+ DECLARE_PROPERTY_HANDLERS( CExtendedVidProcSetting, IRTorch )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, VideoTemporalDenoising)
+ DECLARE_PROPERTY_HANDLERS( CExtendedProperty, RelativePanel)
DECLARE_PROPERTY_HANDLERS( KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode )
DECLARE_PROPERTY_HANDLERS( KSPROPERTY_CAMERACONTROL_FLASH_S, Flash )
@@ -385,7 +388,7 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
// Make sure the PERFRAMESETTINGs passed to us are valid.
_Success_(return == 0)
NTSTATUS
- CCaptureFilter::ParsePFSBuffer(
+ ParsePFSBuffer(
_In_reads_bytes_(BufferLimit)
PKSCAMERA_PERFRAMESETTING_HEADER pPFS,
_In_ ULONG BufferLimit,
@@ -434,7 +437,8 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
// Update the pin's allocator to a specific frame count.
NTSTATUS
UpdateAllocatorFraming(
- _In_ ULONG PinId
+ _In_ ULONG PinId,
+ _In_ ULONG DesiredFrames
);
private:
diff --git a/avstream/avscamera/sys/hwsim.cpp b/avstream/avscamera/sys/hwsim.cpp
index 5322cff3..fdf7b367 100644
--- a/avstream/avscamera/sys/hwsim.cpp
+++ b/avstream/avscamera/sys/hwsim.cpp
@@ -1207,7 +1207,7 @@ Return Value:
{
PAGED_CODE();
- KScopedMutex Lock( m_ListLock );
+ KScopedMutex Lock(m_ListLock);
m_InterruptTime++;
@@ -1218,10 +1218,10 @@ Return Value:
//
if (m_PinState == PinRunning)
{
- LONGLONG Qpc = (LONGLONG) ConvertQPCtoTimeStamp(nullptr);
+ LONGLONG Qpc = (LONGLONG)ConvertQPCtoTimeStamp(nullptr);
LARGE_INTEGER Now;
- KeQuerySystemTimePrecise( &Now );
+ KeQuerySystemTimePrecise(&Now);
//
// Generate a "time stamp" just to overlay it onto the capture image.
// It makes it more exciting than bars that do nothing.
@@ -1230,12 +1230,16 @@ Return Value:
// the most recent streaming pin's index.
if (!m_Sensor->IsStillIndex(m_PinID))
{
+ CSensor::SynthesizerAttributeEntry AttributeList[] =
+ {
+ { CSynthesizer::FrameNumber, m_InterruptTime, m_PinID },
+ { CSynthesizer::RelativePts, (m_InterruptTime + 1) * m_TimePerFrame, m_PinID },
+ { CSynthesizer::QpcTime, Qpc, m_PinID }
+ };
DBG_TRACE("QPC=0x%016llX", Qpc);
// Broadcast the preview pin's info to all pin simulations.
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::FrameNumber, m_InterruptTime, m_PinID);
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::RelativePts, (m_InterruptTime + 1) * m_TimePerFrame, m_PinID);
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::QpcTime, Qpc, m_PinID);
+ m_Sensor->SetSynthesizerAttributeList(SIZEOF_ARRAY(AttributeList), AttributeList);
}
m_Synthesizer->DoSynthesize();
@@ -1243,13 +1247,13 @@ Return Value:
CHAR Text[64];
CExtendedProperty Control;
- m_Sensor->GetVideoStabilization( &Control );
+ m_Sensor->GetVideoStabilization(&Control);
RtlStringCbPrintfA(Text, sizeof(Text), "DVS: %s", DVS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-38, 1, Text, TRANSPARENT, TEXT_COLOR );
+ m_Synthesizer->OverlayText(0, m_Height - 38, 1, Text, TRANSPARENT, TEXT_COLOR);
- m_Sensor->GetOpticalImageStabilization( &Control );
+ m_Sensor->GetOpticalImageStabilization(&Control);
RtlStringCbPrintfA(Text, sizeof(Text), "OIS: %s", OIS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-48, 1, Text, TRANSPARENT, TEXT_COLOR );
+ m_Synthesizer->OverlayText(0, m_Height - 48, 1, Text, TRANSPARENT, TEXT_COLOR);
//
// Add the Missed frame count
@@ -1257,7 +1261,7 @@ Return Value:
size_t len = 0;
RtlStringCchLengthA(Text, sizeof(Text), &len);
m_Synthesizer->OverlayText(
- (m_Width - (((ULONG)len*8))), // right-adjust text.
+ (m_Width - (((ULONG)len * 8))), // right-adjust text.
(m_Height - 48),
1,
Text,
@@ -1268,12 +1272,12 @@ Return Value:
//
// Add the estimated FPS
LONGLONG Target = NANOSECONDS / m_TimePerFrame;
- LONGLONG FPS = ((LONGLONG)m_InterruptTime * NANOSECONDS) / ( (Now.QuadPart - m_StartTime.QuadPart) + (NANOSECONDS/2) );
+ LONGLONG FPS = ((LONGLONG)m_InterruptTime * NANOSECONDS) / ((Now.QuadPart - m_StartTime.QuadPart) + (NANOSECONDS / 2));
RtlStringCbPrintfA(Text, sizeof(Text), "%lld/%lld FPS", FPS, Target);
len = 0;
RtlStringCchLengthA(Text, sizeof(Text), &len);
- m_Synthesizer->OverlayText (
- (m_Width - (((ULONG)len*8))), // right-adjust text.
+ m_Synthesizer->OverlayText(
+ (m_Width - (((ULONG)len * 8))), // right-adjust text.
(m_Height - 38),
1,
Text,
@@ -1284,7 +1288,7 @@ Return Value:
//
// Fill scatter gather buffers
//
- if (!NT_SUCCESS (FillScatterGatherBuffers ()))
+ if (!NT_SUCCESS(FillScatterGatherBuffers()))
{
m_NumFramesSkipped++;
}
@@ -1294,28 +1298,28 @@ Return Value:
// Issue an interrupt to our hardware sink. This is a "fake" interrupt.
// It will occur at DISPATCH_LEVEL.
//
- m_Sensor -> Interrupt (m_PinID);
+ m_Sensor->Interrupt(m_PinID);
//
// Schedule the timer for the next interrupt time, if the pin is still running.
//
- if( m_PinState == PinRunning )
+ if (m_PinState == PinRunning)
{
LARGE_INTEGER NextTime;
NextTime.QuadPart = m_StartTime.QuadPart +
- (m_TimePerFrame * (m_InterruptTime + 1));
+ (m_TimePerFrame * (m_InterruptTime + 1));
#ifdef ENABLE_TRACING // To keep us from a tight spin when trying to debug this code...
LARGE_INTEGER Now;
KeQuerySystemTime(&Now);
- if( Now.QuadPart >= NextTime.QuadPart )
+ if (Now.QuadPart >= NextTime.QuadPart)
{
- NextTime.QuadPart = 0LL - m_TimePerFrame ;
+ NextTime.QuadPart = 0LL - m_TimePerFrame;
}
#endif
- m_IsrTimer.Set( NextTime );
+ m_IsrTimer.Set(NextTime);
}
}
diff --git a/avstream/avscamera/sys/imagecapture.cpp b/avstream/avscamera/sys/imagecapture.cpp
index 06d334d3..7ba53fa4 100644
--- a/avstream/avscamera/sys/imagecapture.cpp
+++ b/avstream/avscamera/sys/imagecapture.cpp
@@ -121,9 +121,11 @@ Close(
{
PAGED_CODE();
+ // Reset the image sim's counts and queues.
Reset();
- return STATUS_SUCCESS;
+ // Call the base Close operation.
+ return CCapturePin::Close(Irp);
}
// ImageCapturePinDispatch:
diff --git a/avstream/avshws/README.md b/avstream/avshws/README.md
index 49bb9e04..9a222462 100644
--- a/avstream/avshws/README.md
+++ b/avstream/avshws/README.md
@@ -84,3 +84,14 @@ In the upper-left corner of the image, a counter counts the number of frames tha
| --- | --- |
| Avshws.h | Main header file for the sample |
| Avshws.inf | Sample installation file |
+Capture.cpp | Capture pin implementation for all capture pins on the sample filter.
+Capture.h | Capture pin level header for all capture pins on the sample filter.
+Device.cpp | Device level implementation of the simulated hardware.
+Device.h | Device level header for the simulated hardware.
+Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter.
+Filter.h | Filter level header for the filter-centric capture filter.
+HWSim.cpp | Hardware simulation implementation, including fake "DMA" transfers, scatter gather mapping handling, ISRs, etc.
+HWSim.h | Hardware simulation header.
+Image.cpp | Image synthesis and overlay code. These objects provide image synthesis (pixel, color-bar, etc) onto RGB24 and UYVY buffers as well as software string overlay into these buffers.
+Image.h | Image synthesis and overlay header.
+Purecall.h | _purecall stub necessary for virtual function usage in drivers.
diff --git a/avstream/avshws/avshws.inf b/avstream/avshws/avshws.inf
deleted file mode 100644
index 9bbbc42a..00000000
--- a/avstream/avshws/avshws.inf
+++ /dev/null
@@ -1,173 +0,0 @@
-;/*++
-;
-;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:
-;
-; AVSHWS.INF
-;
-;Abstract:
-;
-;
-;AVStream pin centric sample mini driver (AVSHWS.sys) installation file.
-;Supports x86, amd64, arm and arm64 platforms
-;
-;--*/
-
-[Version]
-signature="$WINDOWS NT$"
-Class=Camera
-ClassGuid={ca3e7ab9-b4c3-4ae6-8251-579ef933890f}
-Provider=%ProviderName%
-Catalogfile=avshws.cat
-DriverVer=08/31/2006,6.0.5600.0
-
-[SourceDisksNames]
-1000=%cdname%,,,
-
-[SourceDisksFiles]
-avshws.sys=1000
-
-[DestinationDirs]
-DefaultDestDir=12
-avshws.CopyFiles=12
-
-[avshws.CopyFiles]
-avshws.sys
-
-[Manufacturer]
-%ManufacturerName%=Standard,NTx86,NTamd64,ntarm,ntarm64
-
-[Standard.NTx86]
-%avshws.DeviceDesc%=avshws.NTx86,AVSHWS
-
-[Standard.NTamd64]
-%avshws.DeviceDesc%=avshws.NTamd64,AVSHWS
-
-[Standard.NTarm]
-%avshws.DeviceDesc%=avshws.NTarm,AVSHWS
-
-[Standard.NTarm64]
-%avshws.DeviceDesc%=avshws.NTarm64,AVSHWS
-
-;---------------------------------------------------------------
-; x 86 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTx86]
-Include=ks.inf, KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A M D 64 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTamd64]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A R M D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTarm]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A R M 64 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTarm64]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; I n t e r f a c e s
-;---------------------------------------------------------------
-
-[avshws.NTx86.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTamd64.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTarm.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTarm64.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[CaptureInterface.NT]
-AddReg=avshws.Reader.AddReg
-
-;---------------------------------------------------------------
-; A d d R e g
-;---------------------------------------------------------------
-
-[avshws.Reader.AddReg]
-HKR,,CLSID,,%Proxy.CLSID%
-HKR,,FriendlyName,,%avshws.Reader.FriendlyName%
-
-;---------------------------------------------------------------
-; S e r v i c e s
-;---------------------------------------------------------------
-
-[avshws.NTx86.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTamd64.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTarm.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTarm64.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.ServiceInstall]
-DisplayName=%avshws.DeviceDesc%
-ServiceType=%SERVICE_KERNEL_DRIVER%
-StartType=%SERVICE_DEMAND_START%
-ErrorControl=%SERVICE_ERROR_NORMAL%
-ServiceBinary=%12%\avshws.sys
-
-;---------------------------------------------------------------
-; S t r i n g s
-;---------------------------------------------------------------
-
-[Strings]
-; non-localizable
-Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
-KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
-KSCATEGORY_VIDEO="{6994AD05-93EF-11D0-A3CC-00A0C9223196}"
-KSCATEGORY_VIDEO_CAMERA="{E5323777-F976-4f5b-9B55-B94699C46E44}"
-
-SERVICE_KERNEL_DRIVER=1
-SERVICE_DEMAND_START=3
-SERVICE_ERROR_NORMAL=1
-REG_DWORD=0x00010001
-
-;localizable
-ProviderName="TODO-Set-Provider"
-ManufacturerName="TODO-Set-Manufacturer"
-avshws.DeviceDesc="AVStream Simulated Hardware Sample"
-avshws.Reader.FriendlyName="avshws Source"
-cdname="AVSHWS Installation Disk" \ No newline at end of file
diff --git a/avstream/avshws/avshws.inx b/avstream/avshws/avshws.inx
new file mode 100644
index 00000000..238ce187
--- /dev/null
+++ b/avstream/avshws/avshws.inx
Binary files differ
diff --git a/avstream/avshws/avshws.sln b/avstream/avshws/avshws.sln
index 877a4ca9..ba4ee493 100644
--- a/avstream/avshws/avshws.sln
+++ b/avstream/avshws/avshws.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.136
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29519.181
MinimumVisualStudioVersion = 12.0
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avshws", "avshws.vcxproj", "{77FA53EC-3637-411C-B708-C8EED64543A4}"
EndProject
@@ -45,4 +45,3 @@ Global
SolutionGuid = {5EBC439F-EC31-448F-B129-434D42485011}
EndGlobalSection
EndGlobal
- \ No newline at end of file
diff --git a/avstream/avshws/avshws.vcxproj b/avstream/avshws/avshws.vcxproj
index 115a05c9..7d9e015a 100644
--- a/avstream/avshws/avshws.vcxproj
+++ b/avstream/avshws/avshws.vcxproj
@@ -319,7 +319,7 @@
<ResourceCompile Include="avshws.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
@@ -331,4 +331,4 @@
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/avstream/avshws/capture.cpp b/avstream/avshws/capture.cpp
index d68ce1da..13ddbfc0 100644
--- a/avstream/avshws/capture.cpp
+++ b/avstream/avshws/capture.cpp
@@ -265,7 +265,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
KS_SIZE_VIDEOHEADER (ConnectionHeader),
AVSHWS_POOLTAG
diff --git a/avstream/avshws/device.cpp b/avstream/avshws/device.cpp
index 44fc9704..845e938f 100644
--- a/avstream/avshws/device.cpp
+++ b/avstream/avshws/device.cpp
@@ -31,13 +31,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -50,13 +44,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
PVOID
@@ -69,14 +57,7 @@ operator new[](
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag);
-
- if (result)
- {
- RtlZeroMemory(result, iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType, iSize, tag);
}
/*++
diff --git a/avstream/avshws/hwsim.cpp b/avstream/avshws/hwsim.cpp
index 1e813bc2..46d6be62 100644
--- a/avstream/avshws/hwsim.cpp
+++ b/avstream/avshws/hwsim.cpp
@@ -219,7 +219,7 @@ Return Value:
// Allocate a scratch buffer for the synthesizer.
//
m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
m_ImageSize,
AVSHWS_POOLTAG
diff --git a/avstream/avshws/makefile b/avstream/avshws/makefile
new file mode 100644
index 00000000..e8428c0d
--- /dev/null
+++ b/avstream/avshws/makefile
@@ -0,0 +1,15 @@
+!IF 0
+
+Copyright (C) Microsoft Corporation, 1999 - 1999
+
+Module Name:
+
+ makefile.
+
+!ENDIF
+
+!if "$(DDK_TARGET_OS)"=="Win2K"
+!message This sample is not intended to target the Windows 2000 platform.
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif \ No newline at end of file
diff --git a/avstream/avssamp/Filter.cpp b/avstream/avssamp/Filter.cpp
index 524d6ad8..b3b70c30 100644
--- a/avstream/avssamp/Filter.cpp
+++ b/avstream/avssamp/Filter.cpp
@@ -268,17 +268,17 @@ Return Value:
//
PKSDATARANGE_AUDIO DataRangeAudio =
reinterpret_cast <PKSDATARANGE_AUDIO> (
- ExAllocatePoolWithTag (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG)
);
PKSDATARANGE_AUDIO *DataRanges =
reinterpret_cast <PKSDATARANGE_AUDIO *> (
- ExAllocatePoolWithTag (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG)
);
PKSALLOCATOR_FRAMING_EX Framing =
reinterpret_cast <PKSALLOCATOR_FRAMING_EX> (
- ExAllocatePoolWithTag (PagedPool, sizeof (KSALLOCATOR_FRAMING_EX), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (KSALLOCATOR_FRAMING_EX), AVSSMP_POOLTAG)
);
if (DataRangeAudio && DataRanges && Framing) {
diff --git a/avstream/avssamp/avssamp.cpp b/avstream/avssamp/avssamp.cpp
index 68741c9e..1ba03089 100644
--- a/avstream/avssamp/avssamp.cpp
+++ b/avstream/avssamp/avssamp.cpp
@@ -38,13 +38,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -57,13 +51,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
/*++
diff --git a/avstream/avssamp/avssamp.inf b/avstream/avssamp/avssamp.inf
deleted file mode 100644
index 00003e78..00000000
--- a/avstream/avssamp/avssamp.inf
+++ /dev/null
@@ -1,93 +0,0 @@
-; Copyright (c) Microsoft Corporation. All rights reserved.
-;
-; avssamp.INF -- This file contains installation information for the filter-based
-; AVStream sample driver avssamp.sys
-;
-; Note:
-;
-; This INF expects the following hierarchy in the installation folder:
-;
-; \
-; avssamp.inf
-; avssamp.sys
-;
-
-[Version]
-Signature="$Windows NT$"
-Class=Camera
-ClassGuid={ca3e7ab9-b4c3-4ae6-8251-579ef933890f}
-Provider=%ProviderName%
-CatalogFile=avssamp.cat
-DriverVer=09/30/2004,1.0.0.0
-
-[SourceDisksNames]
-1000 = %cdname%,,,
-
-[SourceDisksFiles]
-avssamp.sys = 1000
-
-[ControlFlags]
-ExcludeFromSelect=*
-
-[DestinationDirs]
-avssamp.CopyFiles=12
-
-[Manufacturer]
-%ManufacturerName%=Standard,NTamd64,NTx86
-
-;---------------------------------------------------------------
-; The preferred method to install as a Root-enumerated device.
-; NOTE: DO NOT INCLUDE THIS FOR A HARDWARE DRIVER!
-;---------------------------------------------------------------
-
-[DeviceInstall32]
-AddDevice = ROOT\SW\{20698827-7099-4c4e-861A-4879D639A35F},,avssamp_RootEnumInstall
-
-[avssamp_RootEnumInstall]
-HardwareIds = SW\{20698827-7099-4c4e-861A-4879D639A35F}
-;---------------------------------------------------------------
-
-[Standard.NTx86]
-%avssamp.DeviceDesc%=avssamp,SW\{20698827-7099-4c4e-861A-4879D639A35F}
-
-[Standard.NTamd64]
-%avssamp.DeviceDesc%=avssamp,SW\{20698827-7099-4c4e-861A-4879D639A35F}
-
-[avssamp.NT]
-include=ks.inf,kscaptur.inf
-needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avssamp.CopyFiles
-
-[avssamp.CopyFiles]
-avssamp.sys
-
-[avssamp.NT.Services]
-AddService=avssamp, 0x00000002, avssamp.ServiceInstall
-
-[avssamp.ServiceInstall]
-DisplayName=%avssamp.DeviceDesc%
-ServiceType=%SERVICE_KERNEL_DRIVER%
-StartType=%SERVICE_DEMAND_START%
-ErrorControl=%SERVICE_ERROR_NORMAL%
-ServiceBinary=%12%\avssamp.sys
-
-[Strings]
-; non-localizable
-Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
-avssamp.DeviceId="{20698827-7099-4c4e-861A-4879D639A35F}"
-KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
-KSSTRING_Filter="{9B365890-165F-11D0-A195-0020AFD156E4}"
-
-SERVICE_KERNEL_DRIVER=1
-SERVICE_DEMAND_START=3
-SERVICE_ERROR_NORMAL=1
-REG_EXPAND_SZ=0x00020000
-REG_DWORD=0x00010001
-
-;localizable
-ProviderName="TODO-Set-Provider"
-ManufacturerName="TODO-Set-Manufacturer"
-avssamp.DeviceDesc="AVStream Filter-Centric Sample Driver"
-avssamp.Reader.FriendlyName="avssamp Source"
-
-cdname="Disk 1"
diff --git a/avstream/avssamp/avssamp.inx b/avstream/avssamp/avssamp.inx
new file mode 100644
index 00000000..bcb18baa
--- /dev/null
+++ b/avstream/avssamp/avssamp.inx
Binary files differ
diff --git a/avstream/avssamp/avssamp.vcxproj b/avstream/avssamp/avssamp.vcxproj
index 21c292d2..77567a8f 100644
--- a/avstream/avssamp/avssamp.vcxproj
+++ b/avstream/avssamp/avssamp.vcxproj
@@ -187,7 +187,7 @@
<ResourceCompile Include="avssamp.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
diff --git a/avstream/avssamp/makefile b/avstream/avssamp/makefile
new file mode 100644
index 00000000..ab62d10e
--- /dev/null
+++ b/avstream/avssamp/makefile
@@ -0,0 +1,15 @@
+!IF 0
+
+Copyright (C) Microsoft Corporation, 1999 - 1999
+
+Module Name:
+
+ makefile.
+
+!ENDIF
+
+!if "$(DDK_TARGET_OS)"=="Win2K"
+!message This sample is not intended to target the Windows 2000 platform.
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif
diff --git a/avstream/avssamp/video.cpp b/avstream/avssamp/video.cpp
index d2291a24..1be9b56e 100644
--- a/avstream/avssamp/video.cpp
+++ b/avstream/avssamp/video.cpp
@@ -1,4 +1,4 @@
-/**************************************************************************
+/**************************************************************************
AVStream Filter-Centric Sample
@@ -23,7 +23,7 @@
/**************************************************************************
PAGEABLE CODE
-
+
**************************************************************************/
#ifdef ALLOC_PRAGMA
@@ -210,7 +210,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPool,
KS_SIZE_VIDEOHEADER (ConnectionHeader),
AVSSMP_POOLTAG
@@ -557,7 +557,7 @@ Routine Description:
selected in order to change the format for the pin. In this case,
OldFormat will not be NULL.
- Validate that the format is acceptible and perform the actions necessary
+ Validate that the format is acceptable and perform the actions necessary
to change format if appropriate.
Arguments:
@@ -864,7 +864,7 @@ Return Value:
if (FromState == KSSTATE_STOP) {
m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPool,
m_VideoInfoHeader -> bmiHeader.biSizeImage,
AVSSMP_POOLTAG
diff --git a/avstream/avssamp/wave.cpp b/avstream/avssamp/wave.cpp
index 7af2f60a..de110e69 100644
--- a/avstream/avssamp/wave.cpp
+++ b/avstream/avssamp/wave.cpp
@@ -319,7 +319,7 @@ Return Value:
//
if (NT_SUCCESS (Status)) {
m_WaveData = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG)
+ ExAllocatePoolZero (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG)
);
if (!m_WaveData) {
diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp
index d4220397..563ff610 100644
--- a/avstream/sampledevicemft/basepin.cpp
+++ b/avstream/sampledevicemft/basepin.cpp
@@ -3,6 +3,7 @@
#include "multipinmft.h"
#include "multipinmfthelpers.h"
#include "basepin.h"
+#include "contosodevice.h"
#ifdef MF_WPP
#include "basepin.tmh" //--REF_ANALYZER_DONT_REMOVE--
@@ -323,7 +324,7 @@ STDMETHODIMP CInPin::WaitForSetInputPinMediaChange()
if ( dwWait != WAIT_OBJECT_0 )
{
- hr = E_FAIL;
+ hr = HRESULT_FROM_WIN32(GetLastError());
goto done;
}
done:
@@ -384,23 +385,79 @@ HRESULT CInPin::SetInputStreamState(
return hr;
}
-void CInPin::ReleaseConnectedPins()
+STDMETHODIMP_(VOID) CInPin::ShutdownPin()
{
m_spSourceTransform = nullptr;
m_outpin = nullptr;
}
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+//
+// ForwardSecureBuffer()
+//
+// Parameters:
+// sample - The sample to send out for secure processing
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// This helper function calls back to the AVstream driver for post-processing of a
+// secure buffer. This is done here as an example for simplicity. A more realistic
+// scenario might have you calling into an ISP driver that is not an AVstream driver.
+// To do that you would need to acquire a handle to that device and post an IOCTL.
+// That device would in turn need to have a secure companion driver (trustlet)
+// installed as part of the package to process the buffer.
+//
+HRESULT CInPin::ForwardSecureBuffer(
+ _In_ IMFSample *sample
+)
+{
+ DWORD bytesReturned = 0;
+ CONTOSODEVICE_PROCESSBUFFER_PAYLOAD payload = { 0 };
+ KSPROPERTY property = { 0 };
+
+ wil::com_ptr_nothrow<IMFMediaBuffer> mediaBuffer;
+ wil::com_ptr_nothrow<IMFSecureBuffer> secureBuffer;
+
+ // Set up our private KSPROPERTY to some sample avstream driver.
+ property.Set = PROPSETID_CONTOSODEVICE;
+ property.Id = KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER;
+ property.Flags = KSPROPERTY_TYPE_SET;
+ // Set up the payload for that property. Includes the secure buffer ID and buffer length.
+ RETURN_IF_FAILED(sample->GetBufferByIndex(0, &mediaBuffer));
+ // Forward the buffer if it is secure.
+ if (mediaBuffer.try_query_to(&secureBuffer))
+ {
+ RETURN_IF_FAILED(secureBuffer->GetIdentifier(&payload.identifier));
+ RETURN_IF_FAILED(mediaBuffer->GetMaxLength(&payload.size));
+
+ // Log the buffer's secure ID and size for debugging.
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! identifier=%!GUID!, length=%d", &payload.identifier, payload.size);
+
+ // Send the KSPROPERTY synchronously to the driver.
+ RETURN_IF_FAILED(KsProperty(&property, sizeof(property), &payload, sizeof(payload), &bytesReturned));
+ }
+ return S_OK;
+}
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
//
//Output Pin Implementation
//
COutPin::COutPin(
_In_ ULONG ulPinId,
_In_opt_ CMultipinMft *pparent,
- _In_ IKsControl* pIksControl
+ _In_ IKsControl* pIksControl
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , _In_ MFSampleAllocatorUsage allocatorUsage
+#endif
)
- : CBasePin( ulPinId, pparent ),
- m_firstSample( false ),
- m_queue(nullptr)
+ : CBasePin(ulPinId, pparent)
+ , m_firstSample(false)
+ , m_queue(nullptr)
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , m_allocatorUsage(allocatorUsage)
+#endif
{
HRESULT hr = S_OK;
ComPtr<IMFAttributes> spAttributes;
@@ -507,6 +564,14 @@ STDMETHODIMP_(VOID) COutPin::SetFirstSample(
m_firstSample = fisrtSample;
}
+STDMETHODIMP_(VOID) COutPin::SetAllocator(
+ _In_ IMFVideoSampleAllocator* pAllocator
+)
+{
+ CAutoLock Lock(lock());
+ m_spDefaultAllocator = pAllocator;
+}
+
/*++
COutPin::FlushQueues
Description:
@@ -524,7 +589,7 @@ HRESULT COutPin::FlushQueues()
/*++
COutPin::ChangeMediaTypeFromInpin
Description:
-called from the Device Transfrom When the input media type is changed. This will result in
+called from the Device Transform when the input media type is changed. This will result in
the xvp being possibly installed in the queue if the media types set on the input
and the output dont match
--*/
@@ -542,7 +607,11 @@ HRESULT COutPin::ChangeMediaTypeFromInpin(
SetState(DeviceStreamState_Disabled);
DMFTCHECKHR_GOTO(FlushQueues(),done);
DMFTCHECKNULL_GOTO(m_queue,done, E_UNEXPECTED); // The queue should alwaye be set
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ hr = m_queue->RecreateTeeByAllocatorMode(pInMediatype, pOutMediaType, m_spDxgiManager.Get(), m_allocatorUsage, m_spDefaultAllocator.get());
+#else
hr = m_queue->RecreateTee(pInMediatype, pOutMediaType, m_spDxgiManager.Get());
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
if ( SUCCEEDED( hr ) )
{
(VOID)setMediaType( pOutMediaType );
@@ -583,10 +652,10 @@ STDMETHODIMP COutPin::GetOutputStreamInfo(
/*++
COutPin::ProcessOutput
Description:
- called from the Device Transfrom when the transform manager demands output samples..
+ called from the Device Transform when the transform manager demands output samples..
If we have samples we forward it.
- If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have recieved the transform or not.
- If we have recieved the sample and we are passing out a sample we should reset the trigger set on the Device Transform
+ If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have received the transform or not.
+ If we have received the sample and we are passing out a sample we should reset the trigger set on the Device Transform
--*/
STDMETHODIMP COutPin::ProcessOutput(_In_ DWORD dwFlags,
@@ -663,18 +732,9 @@ STDMETHODIMP CAsyncInPin::SendSample(_In_ IMFSample *pSample)
{
HRESULT hr = S_OK;
CAutoLock Lock(lock());
- if (!m_bFlushing)
+ if (SUCCEEDED(Active()))
{
DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwWorkQueueId, static_cast<IMFAsyncCallback*>(m_asyncCallback.Get()), pSample), done);
- if (1 == InterlockedIncrement(&m_dwSamplesInFlight))
- {
- ResetEvent(m_hHandle);
- }
- }
- else
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! 0x%p Pin Flushing %d",this, streamId());
- // Let the sample fall through
}
done:
return hr;
@@ -682,18 +742,20 @@ done:
STDMETHODIMP CAsyncInPin::Init()
{
- m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CAsyncInPin, &CAsyncInPin::Invoke>(this);
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CAsyncInPin, &CAsyncInPin::Invoke>(this, m_dwWorkQueueId);
if (!m_asyncCallback)
throw bad_alloc();
return S_OK;
}
+// Pass a secure frame buffer to our AVstream driver.
HRESULT CAsyncInPin::Invoke( _In_ IMFAsyncResult* pResult )
{
HRESULT hr = S_OK;
ComPtr<IUnknown> spUnknown;
ComPtr<IMFSample> spSample;
+ DMFTCHECKHR_GOTO(Active(), done);
DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
DMFTCHECKHR_GOTO(pResult->GetState(&spUnknown), done);
@@ -701,46 +763,26 @@ HRESULT CAsyncInPin::Invoke( _In_ IMFAsyncResult* pResult )
DMFTCHECKNULL_GOTO(spSample.Get(), done, E_INVALIDARG);
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ //
+ // Do secure buffer post-processing.
+ //
+ RETURN_IF_FAILED(ForwardSecureBuffer(spSample.Get()));
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
COutPin *poPin = static_cast<COutPin*>(m_outpin.Get());
DMFTCHECKHR_GOTO(poPin->AddSample(spSample.Get(), this), done);
-
- if (0 == InterlockedDecrement(&m_dwSamplesInFlight))
- {
- // No samples in flight.. Set the Event
- SetEvent(m_hHandle);
- }
-
done:
return hr;
}
-
-
-STDMETHODIMP CAsyncInPin::FlushQueues()
+STDMETHODIMP_(VOID) CAsyncInPin::ShutdownPin()
{
- HRESULT hr = S_OK;
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Entering ");
- // Flush in async mode else it is a NOOP
- {
- CAutoLock Lock(lock());
- if (m_bFlushing)
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Pin %d Already Flushing ", streamId());
- goto done;
- }
- m_bFlushing = TRUE;
- }
- //
- // Wait for the IOs to drain
- //
- WaitForSingleObject(m_hHandle, INFINITE);
+ CAutoLock Lock(lock());
+ if (m_asyncCallback.Get())
{
- CAutoLock Lock(lock());
- m_bFlushing = FALSE;
+ (VOID)m_asyncCallback->Shutdown(); //Break reference with the parent
}
-done:
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
- return hr;
+ CInPin::ShutdownPin();
}
//
@@ -808,6 +850,7 @@ STDMETHODIMP CTranslateOutPin::AddMediaType(
done:
return hr;
}
+
STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
_In_ IMFMediaType *pMediaType,
_When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
@@ -824,9 +867,10 @@ STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
if (found != m_TranslatedMediaTypes.end())
{
+ ComPtr<IMFMediaType> spMediaType = (*found).second;
if (ppIMFMediaTypeFull)
{
- *ppIMFMediaTypeFull = (*found).second;
+ *ppIMFMediaTypeFull = spMediaType.Detach();
}
return true;
}
@@ -836,3 +880,24 @@ STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
return CBasePin::IsMediaTypeSupported(pMediaType,ppIMFMediaTypeFull);
}
}
+
+HRESULT CTranslateOutPin::ChangeMediaTypeFromInpin(
+ _In_ IMFMediaType *pInMediatype,
+ _In_ IMFMediaType* pOutMediaType,
+ _In_ DeviceStreamState state)
+{
+ CAutoLock Lock(lock());
+ //
+ // Set the state to disabled and while going out we will reset the state back to the requested state
+ // Flush so that we drop any samples we have in store!!
+ //
+ SetState(DeviceStreamState_Disabled);
+ RETURN_IF_FAILED(FlushQueues());
+ RETURN_HR_IF_NULL(E_UNEXPECTED, m_queue); // The queue should always be set
+ RETURN_IF_FAILED(m_queue->RecreateTee(pInMediatype, pOutMediaType, m_spDxgiManager.Get()));
+
+ (VOID)setMediaType(pOutMediaType);
+ (VOID)SetState(state);
+
+ return S_OK;
+}
diff --git a/avstream/sampledevicemft/basepin.h b/avstream/sampledevicemft/basepin.h
index faafd759..cce17d0b 100644
--- a/avstream/sampledevicemft/basepin.h
+++ b/avstream/sampledevicemft/basepin.h
@@ -369,7 +369,7 @@ public:
__requires_lock_held(m_lock)
__inline HRESULT Active()
{
- return (m_state == DeviceStreamState_Run)?S_OK:E_FAIL;
+ return (m_state == DeviceStreamState_Run)?S_OK:HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
}
__inline DWORD streamId()
{
@@ -511,7 +511,7 @@ public:
return m_preferredStreamState;
}
- void ReleaseConnectedPins();
+ STDMETHOD_( VOID, ShutdownPin)();
protected:
ComPtr<IMFTransform> m_spSourceTransform; /*Source Transform i.e. DevProxy*/
@@ -520,15 +520,27 @@ protected:
DeviceStreamState m_preferredStreamState;
ComPtr<IMFMediaType> m_spPrefferedMediaType;
HANDLE m_waitInputMediaTypeWaiter; /*Set when the input media type is changed*/
+
+ // Helper functions
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ HRESULT ForwardSecureBuffer(
+ _In_ IMFSample *sample
+ );
+#endif
};
class COutPin: public CBasePin{
public:
- COutPin( _In_ ULONG id = 0,
+ COutPin(
+ _In_ ULONG id = 0,
_In_opt_ CMultipinMft *pparent = NULL,
- _In_ IKsControl* iksControl=NULL);
+ _In_ IKsControl* iksControl=NULL
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , _In_ MFSampleAllocatorUsage allocatorUsage = MFSampleAllocatorUsage_DoesNotAllocate
+#endif
+ );
~COutPin();
STDMETHODIMP FlushQueues();
STDMETHODIMP AddPin(
@@ -541,7 +553,7 @@ public:
STDMETHODIMP GetOutputStreamInfo(
_Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo
);
- STDMETHODIMP ChangeMediaTypeFromInpin(
+ virtual STDMETHODIMP ChangeMediaTypeFromInpin(
_In_ IMFMediaType *pInMediatype,
_In_ IMFMediaType* pOutMediaType,
_In_ DeviceStreamState state );
@@ -560,6 +572,16 @@ public:
STDMETHODIMP_(VOID) SetFirstSample(
_In_ BOOL
);
+
+ STDMETHODIMP_(VOID) SetAllocator(
+ _In_ IMFVideoSampleAllocator* pAllocator
+ );
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ MFSampleAllocatorUsage GetSampleAllocatorUsage()
+ {
+ return m_allocatorUsage;
+ }
+#endif
UINT32 GetMediatypeCount()
{
return (UINT32)m_listOfMediaTypes.size();
@@ -568,13 +590,17 @@ public:
protected:
CPinQueue * m_queue; /* Queue where the sample will be stored*/
BOOL m_firstSample;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ MFSampleAllocatorUsage m_allocatorUsage;
+#endif
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> m_spDefaultAllocator;
+
};
class CAsyncInPin: public CInPin {
public:
- STDMETHODIMP FlushQueues();
STDMETHODIMP SendSample(
_In_ IMFSample *
);
@@ -587,30 +613,19 @@ public:
_In_ ULONG ulPinId,
_In_ CMultipinMft *pParent) : CInPin(pAttributes,
ulPinId, pParent)
- , m_dwSamplesInFlight(0)
- , m_hHandle(INVALID_HANDLE_VALUE)
- , m_bFlushing(FALSE)
, m_asyncCallback(nullptr)
{
- m_hHandle = CreateEvent(NULL, TRUE, TRUE, L"Async_Pin Event");
- if (m_hHandle == nullptr)
- throw bad_alloc();
Init();
-
}
+ STDMETHOD_(VOID, ShutdownPin)();
~CAsyncInPin()
{
FlushQueues();
- CloseHandle(m_hHandle);
- m_hHandle = INVALID_HANDLE_VALUE;
}
ComPtr<CDMFTAsyncCallback<CAsyncInPin,&CAsyncInPin::Invoke> > m_asyncCallback; // Callback object
- HANDLE m_hHandle; // Handles to keep flush state
- DWORD m_dwSamplesInFlight; // Samples in flight i.e. waiting for the callback functions to be called
- BOOL m_bFlushing;
////////////////////////////////////////////////////////////////////////////////////////
// End of Asynchronous callback definitions
////////////////////////////////////////////////////////////////////////////////////////
@@ -628,7 +643,12 @@ class CTranslateOutPin : public COutPin {
public:
CTranslateOutPin(_In_ ULONG id = 0,
_In_opt_ CMultipinMft *pparent = NULL,
- _In_ IKsControl* iksControl = NULL) : COutPin(id, pparent, iksControl)
+ _In_ IKsControl* iksControl = NULL)
+ : COutPin(id, pparent, iksControl
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , MFSampleAllocatorUsage_UsesCustomAllocator
+#endif
+ )
{
SetUINT32(MF_SD_VIDEO_SPHERICAL, TRUE);
}
@@ -639,8 +659,14 @@ public:
_In_ IMFMediaType *pMediaType,
_When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
IMFMediaType **ppIMFMediaTypeFull);
+ STDMETHOD(ChangeMediaTypeFromInpin)(
+ _In_ IMFMediaType *pInMediatype,
+ _In_ IMFMediaType* pOutMediaType,
+ _In_ DeviceStreamState state);
+
protected:
map<IMFMediaType*, IMFMediaType*> m_TranslatedMediaTypes;
};
+
diff --git a/avstream/sampledevicemft/common.h b/avstream/sampledevicemft/common.h
index 72242fa3..bc6bbf28 100644
--- a/avstream/sampledevicemft/common.h
+++ b/avstream/sampledevicemft/common.h
@@ -291,7 +291,7 @@ HRESULT ExceptionBoundary(Lambda&& lambda)
}
catch (...)
{
- return E_FAIL;
+ return E_UNEXPECTED;
}
}
@@ -581,7 +581,7 @@ public:
pcbBuffer);
if (dwHeightInPixels* abs(*plStride) > *pcbBuffer)
{
- hr = E_FAIL;
+ hr = E_UNEXPECTED;
}
} else if (m_sp2DBuffer)
{
@@ -652,6 +652,13 @@ HRESULT IsDXFormatSupported(
_Outptr_opt_ ID3D11Device** ppDevice,
_In_opt_ PUINT32 pSupportedFormat);
+HRESULT ConfigureAllocator(
+ _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &isDxAllocator,
+ _In_ IMFVideoSampleAllocator* pAllocator);
+
HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
_In_ GUID streamCategory,
_In_ IUnknown* pDeviceManagerUnk,
diff --git a/avstream/sampledevicemft/contosodevice.h b/avstream/sampledevicemft/contosodevice.h
new file mode 100644
index 00000000..66759f69
--- /dev/null
+++ b/avstream/sampledevicemft/contosodevice.h
@@ -0,0 +1,28 @@
+// 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.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// The Contoso device comes with an SDK
+// that defines various Contoso-specific types,
+// all of which have CONTOSO in their names.
+
+#pragma once
+
+// This payload is used when sending a KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER.
+struct CONTOSODEVICE_PROCESSBUFFER_PAYLOAD
+{
+ GUID identifier;
+ DWORD size;
+};
+
+// Define a custom property set for driver communications.
+// {C5175EE2-583E-43A2-8C26-765287BCEB9D}
+#define STATIC_PROPSETID_CONTOSODEVICE\
+ 0xc5175ee2, 0x583e, 0x43a2, 0x8c, 0x26, 0x76, 0x52, 0x87, 0xbc, 0xeb, 0x9d
+DEFINE_GUIDSTRUCT("C5175EE2-583E-43A2-8C26-765287BCEB9D", PROPSETID_CONTOSODEVICE);
+#define PROPSETID_CONTOSODEVICE DEFINE_GUIDNAMED(PROPSETID_CONTOSODEVICE)
+#define KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER 0 // Send a frame buffer ID to the driver.
+
diff --git a/avstream/sampledevicemft/custompin.cpp b/avstream/sampledevicemft/custompin.cpp
index 00edb329..edb5fadb 100644
--- a/avstream/sampledevicemft/custompin.cpp
+++ b/avstream/sampledevicemft/custompin.cpp
@@ -35,7 +35,7 @@ STDMETHODIMP CCustomPin::SendSample(
// Log sample and exit.. The pipeline will just keep on churning more samples till
// We go into the stop state
//
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Custom Pin %d recieved Sample %p", streamId(), pSample);
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Custom Pin %d received Sample %p", streamId(), pSample);
return S_OK;
}
diff --git a/avstream/sampledevicemft/dllmain.cpp b/avstream/sampledevicemft/dllmain.cpp
index 6978a9d5..88bfe6ab 100644
--- a/avstream/sampledevicemft/dllmain.cpp
+++ b/avstream/sampledevicemft/dllmain.cpp
@@ -196,13 +196,35 @@ STDMETHODIMP_(BOOL) WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
DisableThreadLibraryCalls(hInstance);
#ifdef MF_WPP
WPP_INIT_TRACING(L"MultiPinMft");
+
+ // Hook up WIL tracing to our trace provider.
+ wil::SetResultLoggingCallback(
+ [](const wil::FailureInfo &failure)
+ {
+ wchar_t debugString[2048];
+ if (SUCCEEDED(wil::GetFailureLogString(debugString, ARRAYSIZE(debugString), failure)))
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR, L"%S", debugString);
+ }
+ else
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR,
+ L"File: %s, Line: %u, Error: 0x%08X - %S\n",
+ failure.pszFile,
+ failure.uLineNumber,
+ failure.hr,
+ failure.pszMessage);
+ }
+ }
+ );
#endif
}
else
if (dwReason == DLL_PROCESS_DETACH)
{
#ifdef MF_WPP
- WPP_CLEANUP();
+ wil::SetResultLoggingCallback(nullptr);
+ WPP_CLEANUP();
#endif
}
return TRUE;
diff --git a/avstream/sampledevicemft/multipinmft.cpp b/avstream/sampledevicemft/multipinmft.cpp
index 3467870b..f4fe3d27 100644
--- a/avstream/sampledevicemft/multipinmft.cpp
+++ b/avstream/sampledevicemft/multipinmft.cpp
@@ -1322,6 +1322,54 @@ done:
}
#endif
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+//
+// IMFSampleAllocatorControl Inferface function declarations
+//
+
+STDMETHODIMP CMultipinMft::SetDefaultAllocator(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown *pAllocator
+)
+{
+ CAutoLock Lock(m_critSec);
+
+ // SetAllocator will be called on the streamId that returns MFSampleAllocatorMode_Default
+ wil::com_ptr_nothrow<COutPin> outPin = GetOutPin(dwOutputStreamID);
+ RETURN_HR_IF_NULL(E_INVALIDARG, outPin);
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator);
+
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> defaultAllocator;
+ RETURN_IF_FAILED(pAllocator->QueryInterface(&defaultAllocator));
+ outPin->SetAllocator(defaultAllocator.get());
+
+ return S_OK;
+}
+
+STDMETHODIMP CMultipinMft::GetAllocatorUsage(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage
+)
+{
+ CAutoLock Lock(m_critSec);
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, peUsage);
+
+ wil::com_ptr_nothrow<COutPin> outPin = GetOutPin(dwOutputStreamID);
+ RETURN_HR_IF_NULL(MF_E_INVALIDSTREAMNUMBER, outPin);
+ *peUsage = outPin->GetSampleAllocatorUsage();
+
+ if (*peUsage == MFSampleAllocatorUsage_DoesNotAllocate)
+ {
+ RETURN_HR_IF_NULL(E_INVALIDARG, pdwInputStreamID);
+ RETURN_IF_FAILED(GetConnectedInpin((ULONG)dwOutputStreamID, *(ULONG*)pdwInputStreamID));
+ }
+
+ return S_OK;
+}
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+
//
// HELPER FUNCTIONS
//
@@ -1513,7 +1561,7 @@ HRESULT CMultipinMft::BridgeInputPinOutputPin(
HRESULT hr = S_OK;
ULONG ulIndex = 0;
ULONG ulAddedMediaTypeCount = 0;
- ComPtr<IMFMediaType> pMediaType = nullptr;
+ ComPtr<IMFMediaType> spMediaType;
DMFTCHECKNULL_GOTO( piPin, done, E_INVALIDARG );
DMFTCHECKNULL_GOTO( poPin, done, E_INVALIDARG );
@@ -1523,19 +1571,17 @@ HRESULT CMultipinMft::BridgeInputPinOutputPin(
// sure any pin advertised supports at least one media type. The pipeline doesn't
// like pins with no media types
//
- while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, &pMediaType )))
+ while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, spMediaType.ReleaseAndGetAddressOf() )))
{
GUID subType = GUID_NULL;
- DMFTCHECKHR_GOTO( pMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done );
+ DMFTCHECKHR_GOTO( spMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done );
{
- DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, pMediaType.Get() ), done );
+ DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, spMediaType.Get() ), done );
if (hr == S_OK)
{
ulAddedMediaTypeCount++;
}
}
-
- pMediaType = nullptr;
}
if (ulAddedMediaTypeCount == 0)
{
@@ -1679,7 +1725,7 @@ STDMETHODIMP CMultipinMft::Shutdown(
CInPin *pInPin = static_cast<CInPin *>(m_InPins[ulIndex]);
// Deref on the connected outpins to break reference loop
- pInPin->ReleaseConnectedPins();
+ (VOID)pInPin->ShutdownPin();
}
#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)
for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++)
diff --git a/avstream/sampledevicemft/multipinmft.h b/avstream/sampledevicemft/multipinmft.h
index 080f4a7a..70367f1d 100644
--- a/avstream/sampledevicemft/multipinmft.h
+++ b/avstream/sampledevicemft/multipinmft.h
@@ -48,6 +48,9 @@ class CMultipinMft :
, public IMFGetService
#endif
, public CDMFTModuleLifeTimeManager
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , public IMFSampleAllocatorControl
+#endif
{
friend class CPinCreationFactory;
public:
@@ -275,7 +278,22 @@ public:
}
#endif
-
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ //
+ // IMFSampleAllocatorControl Inferface function declarations
+ //
+
+ STDMETHOD(SetDefaultAllocator)(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown *pAllocator
+ );
+
+ STDMETHOD(GetAllocatorUsage)(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage
+ );
+#endif
static STDMETHODIMP CreateInstance(
REFIID iid, void **ppMFT);
diff --git a/avstream/sampledevicemft/multipinmft.vcxproj b/avstream/sampledevicemft/multipinmft.vcxproj
index 0f560e2c..1a0716bb 100644
--- a/avstream/sampledevicemft/multipinmft.vcxproj
+++ b/avstream/sampledevicemft/multipinmft.vcxproj
@@ -262,9 +262,17 @@
<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" />
+ <None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
+ </Target>
</Project> \ No newline at end of file
diff --git a/avstream/sampledevicemft/multipinmft.vcxproj.Filters b/avstream/sampledevicemft/multipinmft.vcxproj.Filters
index e06f675d..36af8e37 100644
--- a/avstream/sampledevicemft/multipinmft.vcxproj.Filters
+++ b/avstream/sampledevicemft/multipinmft.vcxproj.Filters
@@ -42,5 +42,6 @@
<None Include="Source.def">
<Filter>Source Files</Filter>
</None>
+ <None Include="packages.config" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp
index 904625ad..34cebe8b 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.cpp
+++ b/avstream/sampledevicemft/multipinmfthelpers.cpp
@@ -16,8 +16,7 @@ class CMediaTypePrinter;
//
CPinQueue::CPinQueue( _In_ DWORD dwPinId ,
_In_ IMFDeviceTransform* pParent)
-: m_teer(0),
- m_dwInPinId(dwPinId),
+ :m_dwInPinId(dwPinId),
m_pTransform(pParent),
m_cRef(1)
@@ -30,6 +29,7 @@ CPinQueue::CPinQueue( _In_ DWORD dwPinId ,
}
CPinQueue::~CPinQueue( )
{
+ Ctee::ReleaseTee(m_spTeer);
}
/*++
@@ -59,10 +59,10 @@ STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
STDMETHODIMP CPinQueue::Insert( _In_ IMFSample *pSample )
//
-//m_teer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee which inserts an xvp into the queue etc
+//m_spTeer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee which inserts an xvp into the queue etc
//
{
- return m_teer->PassThrough( pSample );
+ return m_spTeer->PassThrough( pSample );
}
/*++
@@ -97,9 +97,9 @@ VOID CPinQueue::Clear( )
// Stop the tees
// Execute Flush
//
- if (m_teer)
+ if (m_spTeer)
{
- m_teer->Stop();
+ m_spTeer->Stop();
}
while ( !Empty() )
@@ -114,62 +114,99 @@ Description:
RecreateTee creates the underlying Tees in the queue. It accepts the input media type
which is the media type set on the input pin and the output mediatype, which (duh) is the
media type on the output pin
- It also takes an IUnknown which is the D3D Manager. if it is valid we might use it if we
+ It also takes an IUnknown which is the D3D Manager. if it is valid we might use it if we
have an xvp in the path i.e. inputMediatype =! outputMediatype
--*/
-STDMETHODIMP CPinQueue::RecreateTee( _In_ IMFMediaType *inMediatype,
+STDMETHODIMP CPinQueue::RecreateTee(_In_ IMFMediaType *inMediatype,
_In_ IMFMediaType *outMediatype,
- _In_opt_ IUnknown* punkManager )
+ _In_opt_ IUnknown* punkManager)
{
HRESULT hr = S_OK;
DMFT_conversion_type operation = DeviceMftTransformTypeIllegal;
-
- SAFE_DELETE(m_teer); // Should release the reference
- CNullTee *nulltee = new (std::nothrow) CNullTee(this);
- DMFTCHECKNULL_GOTO( nulltee, done, E_OUTOFMEMORY);
+ Ctee::ReleaseTee(m_spTeer);
+
+ ComPtr<CNullTee> spNulltee = new (std::nothrow) CNullTee(this);
+ DMFTCHECKNULL_GOTO(spNulltee.Get(), done, E_OUTOFMEMORY);
DMFTCHECKHR_GOTO(CompareMediaTypesForConverter(inMediatype, outMediatype, &operation), done);
if (operation == DeviceMftTransformTypeDecoder)
{
// Decoder needed
- CDecoderTee* pDecTee = new (std::nothrow) CDecoderTee(nulltee,
+ CDecoderTee* pDecTee = new (std::nothrow) CDecoderTee(spNulltee.Get(),
static_cast<CMultipinMft*>(m_pTransform)->GetQueueId(),
pinCategory());
DMFTCHECKNULL_GOTO(pDecTee, done, E_OUTOFMEMORY);
(void)pDecTee->SetD3DManager(punkManager);
- DMFTCHECKHR_GOTO(pDecTee->SetMediaTypes(inMediatype, outMediatype),done);
- m_teer = dynamic_cast<Ctee*>(pDecTee);
+ DMFTCHECKHR_GOTO(pDecTee->SetMediaTypes(inMediatype, outMediatype), done);
+ m_spTeer = pDecTee;
}
- else if (operation == DeviceMftTransformTypeXVP)
+ else if (operation == DeviceMftTransformTypeXVP)
{
- CXvptee* pXvptee = new (std::nothrow) CXvptee(nulltee, pinCategory());
+ CXvptee* pXvptee = new (std::nothrow) CXvptee(spNulltee.Get(), pinCategory());
DMFTCHECKNULL_GOTO(pXvptee, done, E_OUTOFMEMORY);
- (void)pXvptee->SetD3DManager( punkManager );
- DMFTCHECKHR_GOTO(pXvptee->SetMediaTypes( inMediatype, outMediatype ),done);
- m_teer = dynamic_cast< Ctee* >( pXvptee );
+ (void)pXvptee->SetD3DManager(punkManager);
+ DMFTCHECKHR_GOTO(pXvptee->SetMediaTypes(inMediatype, outMediatype), done);
+ m_spTeer = pXvptee;
}
else
{
- m_teer = nulltee; /*A simple passthrough*/
+ m_spTeer = spNulltee.Get(); /*A simple passthrough*/
}
done:
- DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr );
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
if (FAILED(hr))
{
- if (m_teer){
- delete(m_teer);
- m_teer = NULL;
+ Ctee::ReleaseTee(m_spTeer);
+ }
+ return hr;
+}
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+STDMETHODIMP CPinQueue::RecreateTeeByAllocatorMode(
+ _In_ IMFMediaType* inMediatype,
+ _In_ IMFMediaType* outMediatype,
+ _In_opt_ IUnknown* punkManager,
+ _In_ MFSampleAllocatorUsage allocatorUsage,
+ _In_opt_ IMFVideoSampleAllocator* pAllocator)
+{
+ HRESULT hr = S_OK;
+
+ Ctee::ReleaseTee(m_spTeer);// Should release the reference
+
+ wistd::unique_ptr<CNullTee> nulltee = wil::make_unique_nothrow<CNullTee>(this);
+ RETURN_IF_NULL_ALLOC(nulltee);
+
+ if (allocatorUsage == MFSampleAllocatorUsage_DoesNotAllocate)
+ {
+ m_spTeer.Attach(nulltee.release()); /*A simple passthrough*/
+ }
+ else
+ {
+ wistd::unique_ptr<CSampleCopytee> sampleCopytee;
+ RETURN_IF_NULL_ALLOC(sampleCopytee);
+ (void)sampleCopytee->SetD3DManager(punkManager);
+
+ if (allocatorUsage == MFSampleAllocatorUsage_UsesProvidedAllocator)
+ {
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator);
+ sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), pAllocator);
+ }
+ else
+ {
+ sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), nullptr);
}
+ RETURN_IF_FAILED(sampleCopytee->SetMediaTypes(inMediatype, outMediatype));
+ m_spTeer.Attach(sampleCopytee.release());
}
+
return hr;
}
-
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatype,
_In_ IMFMediaType *outMediatype,
@@ -183,7 +220,7 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp
DMFTCHECKHR_GOTO(CPinQueue::RecreateTee(inMediatype,
outMediatype,
punkManager),done);
- DMFTCHECKNULL_GOTO(m_teer, done, E_UNEXPECTED);
+ DMFTCHECKNULL_GOTO(m_spTeer, done, E_UNEXPECTED);
// Wrap the media type with Gray scale tee only if the input media type is a YUY2, UYVY, NV12 or RGB32
DMFTCHECKHR_GOTO(inMediatype->GetGUID(MF_MT_SUBTYPE, &gInputSubType), done);
if (IsEqualCLSID(gInputSubType, MFVideoFormat_NV12)
@@ -192,9 +229,9 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp
||IsEqualCLSID(gInputSubType, MFVideoFormat_RGB32))
{
CGrayTee *pTee = NULL;
- pTee = new (std::nothrow) CGrayTee(m_teer);
+ pTee = new (std::nothrow) CGrayTee(m_spTeer);
DMFTCHECKHR_GOTO(pTee->SetMediaTypes(inMediatype, outMediatype), done);
- m_teer = dynamic_cast< Ctee* >(pTee);
+ m_spTeer = dynamic_cast< Ctee* >(pTee);
}
else
{
@@ -251,9 +288,9 @@ STDMETHODIMP CWrapTee::PassThrough( _In_ IMFSample* pInSample )
DMFTCHECKNULL_GOTO(pInSample, done, S_OK); // pass through for no sample
DMFTCHECKHR_GOTO(Do(pInSample, &pOutSample,newSample),done);
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- if (SUCCEEDED(hr = m_objectWrapped->PassThrough( pOutSample )))
+ if (SUCCEEDED(hr = m_spObjectWrapped->PassThrough( pOutSample )))
{
//@@@@README There is a very bad bug in the pipeline that the device transform manager
// is not releasing the reference on the sample when it is passed to the device MFT so any
@@ -289,7 +326,7 @@ HRESULT CVideoProcTee::SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMe
ComPtr<IMFTransform> spTransform;
DMFTCHECKHR_GOTO(CWrapTee::SetMediaTypes(pInMediaType, pOutMediaType),done);
DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.GetAddressOf()), done);
- m_videoProcessor = spTransform.Detach();
+ m_spVideoProcessor = spTransform.Detach();
//
// Start streaming
//
@@ -298,6 +335,8 @@ done:
return hr;
}
+
+
HRESULT CVideoProcTee::CreateAllocator()
{
HRESULT hr = S_OK;
@@ -307,18 +346,37 @@ HRESULT CVideoProcTee::CreateAllocator()
return S_OK;
}
- if (m_spAllocator.Get())
+ if (m_spPrivateAllocator)
{
// Release what we have currently
- DMFTCHECKHR_GOTO(m_spAllocator->UninitializeSampleAllocator(), done);
- m_spAllocator = nullptr;
+ RETURN_IF_FAILED(m_spPrivateAllocator->UninitializeSampleAllocator());
+ m_spPrivateAllocator = nullptr;
+ }
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ if (m_spDefaultAllocator)
+ {
+ // Configure default allocator
+ m_spDefaultAllocator->UninitializeSampleAllocator();
+ RETURN_IF_FAILED(::ConfigureAllocator(
+ m_pOutputMediaType.Get(),
+ m_streamCategory,
+ m_spDeviceManagerUnk.Get(),
+ m_fSetD3DManager,
+ m_spDefaultAllocator.Get()));
+ }
+ else
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ {
+ // Create and configure private allocator
+ RETURN_IF_FAILED(MFCreateVideoSampleAllocatorEx(IID_PPV_ARGS(m_spPrivateAllocator.ReleaseAndGetAddressOf())));
+ RETURN_IF_FAILED(::ConfigureAllocator(
+ m_pOutputMediaType.Get(),
+ m_streamCategory,
+ m_spDeviceManagerUnk.Get(),
+ m_fSetD3DManager,
+ m_spPrivateAllocator.Get()));
}
- DMFTCHECKHR_GOTO(::CreateAllocator(m_pOutputMediaType.Get(),
- m_streamCategory, m_spDeviceManagerUnk.Get(),
- m_fSetD3DManager,
- m_spAllocator.GetAddressOf()), done);
-done:
return hr;
}
@@ -342,6 +400,7 @@ CXvptee::~CXvptee()
HRESULT CXvptee::StartStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_Lock);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done); // ulParam set to zero
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done); // ulParam set to zero
done:
@@ -351,6 +410,8 @@ done:
HRESULT CXvptee::StopStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), done); // Flush the stream
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0), done); // Notify end of stream
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0), done); // Notify end of streaming
@@ -374,17 +435,17 @@ STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSamp
MFT_OUTPUT_DATA_BUFFER outputSample;
ComPtr <IMFSample> spXVPOutputSample;
DWORD dwStatus = 0;
+ CAutoLock Lock(m_Lock);
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP ProcessOutput Processing Sample =%p", pSample);
DMFTCHECKNULL_GOTO(ppOutSample, done, E_INVALIDARG);
-
*ppOutSample = nullptr;
-
+ DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
DMFTCHECKHR_GOTO(Transform()->MFTProcessInput(0, pSample, 0),done);
outputSample.dwStreamID = 0;
outputSample.pSample = NULL;
- DMFTCHECKHR_GOTO(m_spAllocator->AllocateSample(&outputSample.pSample), done);
+ DMFTCHECKHR_GOTO(m_spPrivateAllocator->AllocateSample(&outputSample.pSample), done);
hr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
@@ -492,16 +553,18 @@ done:
CDecoderTee::~CDecoderTee()
{
(VOID)StopStreaming();
- if (m_spAllocator)
+ MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
+ if (m_spPrivateAllocator)
{
- m_spAllocator->UninitializeSampleAllocator();
- m_spAllocator = nullptr;
+ m_spPrivateAllocator->UninitializeSampleAllocator();
+ m_spPrivateAllocator = nullptr;
}
}
HRESULT CDecoderTee::StartStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(&m_Lock);
DMFTCHECKNULL_GOTO(Transform(), done, MF_E_UNEXPECTED);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done);
@@ -512,13 +575,11 @@ HRESULT CDecoderTee::StartStreaming()
HRESULT CDecoderTee::StopStreaming()
{
HRESULT hr = S_OK;
- ComPtr<IMFTransform> spTransform = Transform();
+ ComPtr<IMFTransform> spTransform;
{
- CAutoLock Lock(&m_critSec);
- if (m_hSyncHandle)
- {
- ResetEvent(m_hSyncHandle);
- }
+ CAutoLock Lock(&m_Lock);
+ spTransform = Transform();
+ SetAsyncStatus(MF_E_SHUTDOWN);
}
if (spTransform.Get())
{
@@ -531,15 +592,7 @@ HRESULT CDecoderTee::StopStreaming()
{
(void)spShutdown->Shutdown();
}
- m_critSec.Lock();
- SetAsyncStatus(MF_E_SHUTDOWN);
- MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
- if (m_ulProcessOutputsInFlight > 0)
- {
- m_critSec.Unlock();
- WaitForSingleObject(m_hSyncHandle, INFINITE);
-
- }
+
spTransform = nullptr;
}
done:
@@ -553,17 +606,12 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
HRESULT hr = S_OK;
ComPtr<IMFTransform> spTransform;
GUID gInSubType = GUID_NULL, gOutSubType = GUID_NULL;
+
DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO(inType, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO(outType, done, E_INVALIDARG);
*ppTransform = nullptr;
- SAFE_CLOSEHANDLE(m_hSyncHandle);
- m_hSyncHandle = CreateEvent(NULL,
- FALSE,
- TRUE,
- TEXT("SyncDecoderWaiter")
- );
if (!(SUCCEEDED(inType->GetGUID(MF_MT_SUBTYPE, &gInSubType))
&& SUCCEEDED(outType->GetGUID(MF_MT_SUBTYPE, &gOutSubType))))
{
@@ -592,11 +640,6 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
}
DMFTCHECKNULL_GOTO(spTransform.Get(), done, E_UNEXPECTED);
- if (m_D3daware && SUCCEEDED(IsDXFormatSupported(reinterpret_cast<IMFDXGIDeviceManager*>(m_spDeviceManagerUnk.Get()), gOutSubType, nullptr, nullptr)))
- {
- DMFTCHECKHR_GOTO(spTransform->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)m_spDeviceManagerUnk.Get()), done);
- }
-
DMFTCHECKHR_GOTO(spTransform->MFTGetOutputStreamInfo(m_dwMFTOutputId, &outputStreamInfo), done);
m_bProducesSamples = (outputStreamInfo.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES));
@@ -608,7 +651,7 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
}
// Create a callback for processoutputs to be called on
- m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke>(this);
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke>(this, m_dwQueueId);
DMFTCHECKNULL_GOTO(m_asyncCallback.Get(), done, E_OUTOFMEMORY);
if (m_fAsyncMFT)
@@ -636,9 +679,10 @@ STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppout
{
HRESULT hr = S_OK;
ComPtr<IMFSample> spOutputSample;
+ CAutoLock lock(m_Lock);
ComPtr<IMFTransform> spTransform = Transform();
+
newSample = false;
- CAutoLock lock(m_critSec);
DMFTCHECKNULL_GOTO(ppoutSample, done, E_INVALIDARG);
*ppoutSample = nullptr;
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
@@ -663,7 +707,6 @@ STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppout
spInputSample.Detach();
hr = S_OK;
// Queue a work item for process output
- m_ulProcessOutputsInFlight++;
DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwCameraStreamWorkQueueId, m_asyncCallback.Get(), nullptr), done);
break;
}
@@ -720,7 +763,7 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
ComPtr<IMFTransform> spDecoderTemp;
ComPtr<IMFSample> spOutputSample;
BOOL bSendSample = FALSE;
- CAutoLock lock(m_critSec);
+ CAutoLock lock(m_Lock);
spDecoderTemp = Transform();
@@ -748,12 +791,12 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
case METransformHaveOutput:
{
ComPtr<IMFSample> spDecodedSample;
- m_critSec.Unlock();
+ m_Lock.Unlock();
//
// The processoutput call blocks for H264 sometimes. This call back is serialized
//
hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
- m_critSec.Lock();
+ m_Lock.Lock();
// Did we error out when we released the lock?
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
if (SUCCEEDED(hr))
@@ -780,13 +823,12 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
{
// Synchronous mode. We only need it for processoutputs
ComPtr<IMFSample> spDecodedSample;
- m_ulProcessOutputsInFlight--;
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
DMFTCHECKHR_GOTO(pResult->GetStatus(), done);
- m_critSec.Unlock();
+ m_Lock.Unlock();
hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
- m_critSec.Lock();
+ m_Lock.Lock();
if (SUCCEEDED(hr))
{
// send the sample on its way
@@ -805,9 +847,9 @@ done:
if (bSendSample && spOutputSample.Get())
{
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- hr = m_objectWrapped->PassThrough(spOutputSample.Get());
+ hr = m_spObjectWrapped->PassThrough(spOutputSample.Get());
spOutputSample = nullptr;
}
}
@@ -823,11 +865,6 @@ done:
{
SetAsyncStatus(hr);
}
- if (m_StoppedAndWaiting)
- {
- // Stop is waiting on the threads to run
- SetEvent(m_hSyncHandle);
- }
return hr;
}
@@ -836,11 +873,11 @@ done:
// is holding on to the buffers, could be the xvp then this function will error
// out the pipeline. you should see the ALLOCATOR_E_EMPTY error pop up
//
-_Ret_maybenull_ HRESULT CDecoderTee::GetSample( IMFSample** ppSample )
+HRESULT CDecoderTee::GetSample( IMFSample** ppSample )
{
- if (!m_bProducesSamples && m_spAllocator.Get())
+ if (!m_bProducesSamples && m_spPrivateAllocator.Get())
{
- return m_spAllocator->AllocateSample(ppSample);
+ return m_spPrivateAllocator->AllocateSample(ppSample);
}
return S_OK;
}
@@ -890,7 +927,7 @@ HRESULT CDecoderTee::ProcessFormatChange()
// Also note, The platform doesn't support dynamic media type changes from the stream coming from the
// source.
//
- ComPtr<IMFTransform> spXvp;
+ ComPtr<CXvptee> spXvpTee;
DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidPreviousSubType), done);
for (DWORD i = 0; ; i++)
@@ -918,11 +955,11 @@ HRESULT CDecoderTee::ProcessFormatChange()
//
// Create the XVP and insert it into the chain manually. set the output to the mediatype requested by the platform
//
- CXvptee* pXvpTee = new (std::nothrow) CXvptee(m_objectWrapped ,m_streamCategory);
- DMFTCHECKNULL_GOTO(pXvpTee, done, E_OUTOFMEMORY);
- (VOID)pXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
- DMFTCHECKHR_GOTO(pXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done);
- m_objectWrapped = pXvpTee;
+ spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get() ,m_streamCategory);
+ DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY);
+ (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
+ DMFTCHECKHR_GOTO(spXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done);
+ m_spObjectWrapped = spXvpTee;
spDecoderOutputMediaType = nullptr;
@@ -946,6 +983,7 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
GUID guidMajorType;
GUID guidSubtype;
DWORD dwMediaTypeIndex = 0;
+ ComPtr<IMFDXGIDeviceManager> spDxgiManager;
UNREFERENCED_PARAMETER(guidSubType);
DMFTCHECKNULL_GOTO(pTransform, done, E_INVALIDARG);
@@ -973,12 +1011,22 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
(void)ConfigRealTimeMFT(pTransform);
(void)pTransform->MFTGetStreamIDs(1, &m_dwMFTInputId, 1, &m_dwMFTOutputId);
- // Try to set input mediatype on MJPG decoder.
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done);
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+
+ if (m_spDeviceManagerUnk.Get())
+ {
+ DMFTCHECKHR_GOTO(m_spDeviceManagerUnk.As(&spDxgiManager), done);
+ if (m_D3daware && SUCCEEDED(IsDXFormatSupported(spDxgiManager.Get(), guidSubtype, nullptr, nullptr)))
+ {
+ // Set the DXGI Manager here, before the input type is set
+ DMFTCHECKHR_GOTO(pTransform->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)m_spDeviceManagerUnk.Get()), done);
+ }
+ }
DMFTCHECKHR_GOTO(pTransform->MFTSetInputType(m_dwMFTInputId, m_pInputMediaType.Get(), 0), done);
// Find a matching output mediatype that has the same major/Subtype as pOutputType
- DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done);
- DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+
while (SUCCEEDED(pTransform->MFTGetOutputAvailableType(m_dwMFTOutputId, dwMediaTypeIndex, &spMediaType)))
{
GUID guidMajorType2;
@@ -1061,6 +1109,18 @@ HRESULT CDecoderTee::ProcessOutputSync(_COM_Outptr_opt_ IMFSample** ppSample)
return hr;
}
+VOID CDecoderTee::ShutdownTee()
+{
+ CAutoLock lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
+ if (m_asyncCallback.Get())
+ {
+ // Break the circular reference between the
+ // internal async callback and the decoder
+ m_asyncCallback->Shutdown();
+ }
+}
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
CGrayTee::CGrayTee(_In_ Ctee *tee) : CWrapTee(tee),m_transformfn(nullptr)
{
@@ -1174,6 +1234,122 @@ done:
}
#endif
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+// @@@@ README: Sample copy related functions below
+//
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+
+CSampleCopytee::CSampleCopytee(_In_ Ctee *tee, GUID category
+ , IMFVideoSampleAllocator* sampleAllocator
+) :
+ CVideoProcTee(tee, category
+ , sampleAllocator
+ )
+{
+
+}
+
+CSampleCopytee::~CSampleCopytee()
+{
+ (VOID)StopStreaming();
+ m_spDeviceManagerUnk = nullptr;
+}
+
+HRESULT CSampleCopytee::StartStreaming()
+{
+ CAutoLock lock(m_Lock);
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0));
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0));
+
+ return S_OK;
+}
+
+HRESULT CSampleCopytee::StopStreaming()
+{
+ CAutoLock lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0)); // Flush the stream
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0)); // Notify end of stream
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0)); // Notify end of streaming
+
+ return S_OK;
+}
+
+STDMETHODIMP CSampleCopytee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
+{
+
+ HRESULT hr = S_OK;
+ MFT_OUTPUT_DATA_BUFFER outputSample;
+ ComPtr <IMFSample> spXVPOutputSample;
+ DWORD dwStatus = 0;
+ CAutoLock lock(m_Lock);
+
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Processing Sample =%p", pSample);
+ RETURN_HR_IF_NULL(E_INVALIDARG, ppOutSample);
+
+ *ppOutSample = nullptr;
+ RETURN_IF_FAILED(GetAsyncStatus());
+ RETURN_IF_FAILED(Transform()->MFTProcessInput(0, pSample, 0));
+
+ outputSample.dwStreamID = 0;
+ outputSample.pSample = NULL;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ if (m_spDefaultAllocator)
+ {
+ RETURN_IF_FAILED(m_spDefaultAllocator->AllocateSample(&outputSample.pSample));
+ }
+ else
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ {
+ RETURN_IF_FAILED(m_spPrivateAllocator->AllocateSample(&outputSample.pSample));
+ }
+
+
+ hr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
+
+ if (SUCCEEDED(hr) && pSample)
+ {
+ spXVPOutputSample.Attach(outputSample.pSample);
+ }
+ else
+ {
+ SAFE_RELEASE(outputSample.pSample);
+ }
+
+ if (spXVPOutputSample.Get())
+ {
+ newSample = true;
+ *ppOutSample = spXVPOutputSample.Detach();
+ }
+
+ return hr;
+}
+
+STDMETHODIMP CSampleCopytee::Configure(
+ _In_opt_ IMFMediaType* inMediaType,
+ _In_opt_ IMFMediaType* outMediaType,
+ _Outptr_ IMFTransform **ppTransform
+)
+{
+ RETURN_HR_IF_NULL(E_INVALIDARG, ppTransform);
+
+ CMediaTypePrinter inType(inMediaType);
+ CMediaTypePrinter outType(outMediaType);
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Input MediaType %s", inType.ToString());
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Output MediaType %s", outType.ToString());
+
+ RETURN_IF_FAILED(MFCreateSampleCopierMFT(ppTransform));
+ RETURN_IF_FAILED(CreateAllocator());
+
+ if (m_fSetD3DManager)
+ {
+ RETURN_IF_FAILED((*ppTransform)->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<UINT_PTR>(m_spDeviceManagerUnk.Get())));
+ }
+
+ return S_OK;
+}
+
+
/*++
Descrtiption:
Handles events sent by the pipeline
@@ -1256,7 +1432,7 @@ HRESULT CDMFTEventHandler::KSEvent(
for (; it != m_RegularEventList.end(); it++)
{
PDMFTEventEntry pEntry = *it;
- DMFTCHECKNULL_GOTO(pEntry, done, E_FAIL);
+ DMFTCHECKNULL_GOTO(pEntry, done, E_UNEXPECTED);
if (pEntry->m_pEventData == pEventData)
{
break;
@@ -1547,7 +1723,11 @@ HRESULT CPinCreationFactory::CreatePin(_In_ ULONG ulInputStreamId, /* The Input
#if defined MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED
spOutPin = new (std::nothrow) CTranslateOutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
#else
- spOutPin = new (std::nothrow) COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
+ spOutPin = new (std::nothrow) COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , MFSampleAllocatorUsage_DoesNotAllocate
+#endif
+ ); // Create the output pin
#endif
DMFTCHECKNULL_GOTO(spOutPin.Get(), done, E_OUTOFMEMORY);
@@ -1621,14 +1801,10 @@ done:
return hr;
}
-HRESULT CheckImagePin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin )
+BOOL CheckImagePin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin )
{
- if ((SUCCEEDED(CheckPinType(pAttributes, PINNAME_IMAGE, pbIsImagePin)) && pbIsImagePin) ||
- (SUCCEEDED(CheckPinType(pAttributes, PINNAME_VIDEO_STILL, pbIsImagePin)) && pbIsImagePin))
- {
- return S_OK;
- }
- return E_FAIL;
+ return ((SUCCEEDED(CheckPinType(pAttributes, PINNAME_IMAGE, pbIsImagePin)) && pbIsImagePin) ||
+ (SUCCEEDED(CheckPinType(pAttributes, PINNAME_VIDEO_STILL, pbIsImagePin)) && pbIsImagePin));
}
HRESULT CheckPreviewPin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsPreviewPin)
diff --git a/avstream/sampledevicemft/multipinmfthelpers.h b/avstream/sampledevicemft/multipinmfthelpers.h
index bd3f0876..681ca071 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.h
+++ b/avstream/sampledevicemft/multipinmfthelpers.h
@@ -32,9 +32,9 @@ template< typename T , HRESULT ( __stdcall T::*Func) ( IMFAsyncResult* ) >
class CDMFTAsyncCallback : public IMFAsyncCallback
{
public:
- CDMFTAsyncCallback( T* parent ) :
- m_cRef(1),
- m_Parent(parent)
+ CDMFTAsyncCallback( T* parent , DWORD dwWorkQueueId = MFASYNC_CALLBACK_QUEUE_STANDARD) :
+ m_Parent(parent),
+ m_dwQueueId(dwWorkQueueId)
{ }
virtual ~CDMFTAsyncCallback() { }
@@ -77,25 +77,40 @@ public:
STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
{
- // Implementation of this method is optional.
- UNREFERENCED_PARAMETER(pdwFlags);
- UNREFERENCED_PARAMETER(pdwQueue);
+ *pdwFlags = 0;
+ *pdwQueue = m_dwQueueId;
return E_NOTIMPL;
}
STDMETHODIMP Invoke( IMFAsyncResult* pAsyncResult )
{
- return (m_Parent->*Func)(pAsyncResult);
+ ComPtr<T> spParent;
+ {
+ // Take a reference on the parent so that
+ // shutdown may not yank it from us
+ CAutoLock Lock(&m_Lock);
+ spParent = m_Parent;
+ }
+ if (spParent.Get())
+ {
+ return ((spParent.Get())->*Func)(pAsyncResult);
+ }
+ return MF_E_SHUTDOWN;
+ }
+ VOID Shutdown()
+ {
+ CAutoLock Lock(&m_Lock);
+ m_Parent = nullptr; //Break the reference
}
- // TODO: Implement this method.
-
T GetParent()
{
return m_Parent;
}
protected:
- T* m_Parent; // Weak reference to the parent
- long m_cRef;
+ CCritSec m_Lock;
+ ComPtr<T> m_Parent;
+ long m_cRef = 0;
+ DWORD m_dwQueueId = MFASYNC_CALLBACK_QUEUE_STANDARD;
};
@@ -107,7 +122,18 @@ public:
STDMETHODIMP_(VOID) InsertInternal ( _In_ IMFSample *pSample = nullptr );
STDMETHODIMP Insert ( _In_ IMFSample *pSample );
STDMETHODIMP Remove (_Outptr_result_maybenull_ IMFSample **pSample);
- virtual STDMETHODIMP RecreateTee ( _In_ IMFMediaType *inMediatype, _In_ IMFMediaType *outMediatype, _In_opt_ IUnknown* punkManager );
+ virtual STDMETHODIMP RecreateTee (
+ _In_ IMFMediaType *inMediatype,
+ _In_ IMFMediaType *outMediatype,
+ _In_opt_ IUnknown* punkManager);
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ STDMETHODIMP RecreateTeeByAllocatorMode(
+ _In_ IMFMediaType* inMediatype,
+ _In_ IMFMediaType* outMediatype,
+ _In_opt_ IUnknown* punkManager,
+ _In_ MFSampleAllocatorUsage allocatorUsage,
+ _In_opt_ IMFVideoSampleAllocator* pAllcoator);
+#endif
STDMETHODIMP_(VOID) Clear();
//
@@ -179,7 +205,7 @@ private:
GUID m_streamCategory;
ULONG m_cRef;
protected:
- Ctee* m_teer; /*Tee that acts as a passthrough or an XVP */
+ ComPtr<Ctee> m_spTeer; /*Tee that acts as a passthrough or an XVP */
};
@@ -197,8 +223,20 @@ public:
// The below classes are used to add the
// XVP and the Decoder components.
//
-class Ctee{
+class Ctee: public IUnknown{
public:
+ // This is a helper class to release the interface
+ // It will first call shutdowntee to break any circular
+ // references any components might have with their composed
+ // objects
+ static VOID ReleaseTee( _In_ ComPtr<Ctee> &tee)
+ {
+ if (tee)
+ {
+ tee->ShutdownTee();
+ tee = nullptr;
+ }
+ }
STDMETHOD(Start)()
{
return S_OK;
@@ -208,35 +246,85 @@ public:
return S_OK;
}
virtual STDMETHODIMP PassThrough( _In_ IMFSample * ) = 0;
+
+ STDMETHOD_(VOID, ShutdownTee)()
+ {
+ return; // NOOP
+ }
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
+ {
+ HRESULT hr = S_OK;
+ if (ppv != nullptr)
+ {
+ *ppv = nullptr;
+ if (riid == __uuidof(IUnknown))
+ {
+ AddRef();
+ *ppv = static_cast<IUnknown*>(this);
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ else
+ {
+ hr = E_POINTER;
+ }
+ return hr;
+ }
+ Ctee()
+ {
+ }
+ virtual ~Ctee()
+ {}
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+ STDMETHODIMP_(ULONG) Release()
+ {
+ long cRef = InterlockedDecrement(&m_cRef);
+ if (cRef == 0)
+ {
+ delete this;
+ }
+ return cRef;
+ }
+
+protected:
+ ULONG m_cRef = 0;
};
class CNullTee:public Ctee{
public:
- CNullTee(_In_ CPinQueue* q) :m_Queue(q) {}
+ CNullTee(_In_ CPinQueue* q)
+ : m_Queue(q)
+ {
+ }
STDMETHODIMP PassThrough( _In_ IMFSample* );
+
protected:
// Store the queue here for simplicity
ComPtr<CPinQueue> m_Queue;
};
-class CWrapTee : public Ctee{
+class CWrapTee : public Ctee
+{
public:
CWrapTee( _In_ Ctee *tee=nullptr )
-: m_objectWrapped(tee)
+ : m_spObjectWrapped(tee)
, m_pInputMediaType(nullptr)
, m_pOutputMediaType(nullptr)
{
}
- virtual ~CWrapTee()=0
+ virtual ~CWrapTee()
{
- if (m_objectWrapped)
- {
- delete(m_objectWrapped);
- }
}
+
STDMETHODIMP PassThrough ( _In_ IMFSample* );
virtual STDMETHODIMP Do ( _In_ IMFSample* pSample, _Out_ IMFSample ** , _Inout_ bool &newSample) = 0;
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
@@ -262,7 +350,7 @@ protected:
ComPtr< IMFMediaType > m_pInputMediaType;
ComPtr< IMFMediaType > m_pOutputMediaType;
- Ctee *m_objectWrapped;
+ ComPtr<Ctee> m_spObjectWrapped;
};
//
@@ -272,20 +360,26 @@ class CVideoProcTee: public CWrapTee
{
public:
- CVideoProcTee( _In_ Ctee* p, _In_ GUID category = PINNAME_PREVIEW ) :CWrapTee(p)
+ CVideoProcTee( _In_ Ctee* p, _In_ GUID category = PINNAME_PREVIEW
+ , _In_ IMFVideoSampleAllocator* sampleAllocator=nullptr
+ )
+ :CWrapTee(p)
, m_bProducesSamples(FALSE)
+ , m_asyncHresult(S_OK)
, m_streamCategory(category)
, m_fSetD3DManager(FALSE)
+ , m_spDefaultAllocator(sampleAllocator)
{}
__inline IMFTransform* Transform()
{
- return m_videoProcessor.Get();
+ return m_spVideoProcessor.Get();
}
VOID SetD3DManager( _In_opt_ IUnknown* pUnk )
{
- m_spDeviceManagerUnk = pUnk;
+ m_spDeviceManagerUnk = pUnk;
}
+
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
virtual STDMETHODIMP Configure(_In_ IMFMediaType *, _In_ IMFMediaType *, _Inout_ IMFTransform**) = 0;
STDMETHOD(CreateAllocator)();
@@ -294,19 +388,33 @@ public:
HRESULT hr = S_OK;
if (SUCCEEDED(hr = StopStreaming()))
{
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- hr = m_objectWrapped->Stop();
+ hr = m_spObjectWrapped->Stop();
}
}
return hr;
}
+ virtual ~CVideoProcTee()
+ {}
protected:
+ CCritSec m_Lock;
+ __inline VOID SetAsyncStatus(_In_ HRESULT hrStatus)
+ {
+ InterlockedCompareExchange(&m_asyncHresult, hrStatus, S_OK);
+ }
+ HRESULT GetAsyncStatus()
+ {
+ return InterlockedCompareExchange(&m_asyncHresult, S_OK, S_OK);
+ }
STDMETHOD(StartStreaming)() = 0;
STDMETHOD(StopStreaming)() = 0;
- ComPtr< IMFTransform > m_videoProcessor;
+ HRESULT m_asyncHresult;
+ ComPtr< IMFTransform > m_spVideoProcessor;
ComPtr<IUnknown> m_spDeviceManagerUnk;
- ComPtr<IMFVideoSampleAllocatorEx> m_spAllocator;
+ ComPtr<IMFVideoSampleAllocatorEx> m_spPrivateAllocator;
+ ComPtr<IMFVideoSampleAllocator> m_spDefaultAllocator;
+
BOOL m_bProducesSamples;
GUID m_streamCategory;
BOOL m_fSetD3DManager;
@@ -315,11 +423,12 @@ protected:
class CXvptee :public CVideoProcTee{
public:
CXvptee( _In_ Ctee *, _In_ GUID category = PINNAME_PREVIEW );
- ~CXvptee();
+ virtual ~CXvptee();
STDMETHOD(StartStreaming)();
STDMETHOD(StopStreaming)();
STDMETHODIMP Do ( _In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
STDMETHODIMP Configure ( _In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform** );
+
};
class CDecoderTee : public CVideoProcTee {
@@ -338,23 +447,11 @@ public:
, m_dwMFTInputId(0)
, m_dwMFTOutputId(0)
, m_dwQueueId(dwQueueId)
- ,m_dwCameraStreamWorkQueueId(0)
- , m_ulProcessOutputsInFlight(0)
- , m_hSyncHandle(INVALID_HANDLE_VALUE)
- , m_StoppedAndWaiting(FALSE)
+ , m_dwCameraStreamWorkQueueId(0)
{
m_streamCategory = category;
}
- ~CDecoderTee();
-
- __inline VOID SetAsyncStatus( _In_ HRESULT hrStatus )
- {
- InterlockedCompareExchange(&m_asyncHresult, hrStatus, S_OK);
- }
- HRESULT GetAsyncStatus()
- {
- return InterlockedCompareExchange(&m_asyncHresult, S_OK, S_OK);
- }
+ virtual ~CDecoderTee();
STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
@@ -362,16 +459,17 @@ public:
protected:
STDMETHODIMP StartStreaming();
STDMETHODIMP StopStreaming();
- _Ret_maybenull_ HRESULT CDecoderTee::GetSample( _Outptr_ IMFSample**);
+ HRESULT GetSample( _Outptr_result_maybenull_ IMFSample**);
HRESULT ConfigDecoder( _In_ IMFTransform* ,_In_ GUID guidSubType = GUID_NULL);
HRESULT ConfigRealTimeMFT(_In_ IMFTransform* );
HRESULT ProcessOutputSync( _COM_Outptr_opt_ IMFSample** );
HRESULT ProcessFormatChange();
+ STDMETHOD_(VOID, ShutdownTee)();
BOOL m_fAsyncMFT;
BOOL m_D3daware;
BOOL m_hwMFT;
- ComPtr<CDMFTAsyncCallback<CDecoderTee,&CDecoderTee::Invoke> > m_asyncCallback;
+ ComPtr<CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke> > m_asyncCallback;
HRESULT m_asyncHresult;
DWORD m_lNeedInputRequest;
GUID m_streamCategory; // Needed for bind flags
@@ -381,14 +479,22 @@ protected:
ComPtr<IMFSample> m_spUnprocessedSample;
DWORD m_dwQueueId;
DWORD m_dwCameraStreamWorkQueueId;
- CCritSec m_critSec;
std::deque<ComPtr<IMFSample> > m_InputSampleList;
- ULONG m_ulProcessOutputsInFlight;
- HANDLE m_hSyncHandle;
- BOOL m_StoppedAndWaiting;
};
+class CSampleCopytee :public CVideoProcTee {
+public:
+ CSampleCopytee(_In_ Ctee*, _In_ GUID category = PINNAME_PREVIEW
+ , _In_ IMFVideoSampleAllocator* sampleAllocator = nullptr
+ );
+ ~CSampleCopytee();
+ STDMETHOD(StartStreaming)();
+ STDMETHOD(StopStreaming)();
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
+ STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
+};
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
class CGrayTee : public CWrapTee {
public:
@@ -499,6 +605,7 @@ public:
DMFT_PIN_INPUT,
DMFT_PIN_OUTPUT,
DMFT_PIN_CUSTOM,
+ DMFT_PIN_ALLOCATOR_PIN,
DMFT_MAX
}type_pin;
HRESULT CreatePin( _In_ ULONG ulInputStreamId, _In_ ULONG ulOutStreamId, _In_ type_pin type,_Outptr_ CBasePin** ppPin, _In_ BOOL& isCustom);
@@ -506,7 +613,7 @@ public:
}
};
HRESULT CheckPinType(_In_ IMFAttributes* pAttributes, _In_ GUID pinType, _Out_ PBOOL pbIsImagePin);
-HRESULT CheckImagePin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin);
+BOOL CheckImagePin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin);
HRESULT CheckPreviewPin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsPreviewPin);
diff --git a/avstream/sampledevicemft/multipinmftutils.cpp b/avstream/sampledevicemft/multipinmftutils.cpp
index d056b364..e4a62d52 100644
--- a/avstream/sampledevicemft/multipinmftutils.cpp
+++ b/avstream/sampledevicemft/multipinmftutils.cpp
@@ -1301,6 +1301,83 @@ done:
const UINT32 ALLOCATOR_MIN_SAMPLES = 10;
const UINT32 ALLOCATOR_MAX_SAMPLES = 50;
+
+HRESULT ConfigureAllocator(
+ _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &bDxAllocator,
+ _In_ IMFVideoSampleAllocator* pAllocator)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IMFVideoSampleAllocatorEx> spPrivateAllocator;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ wil::com_ptr_nothrow<IMFVideoCaptureSampleAllocator> spDefaultAllocator;
+#endif
+ wil::com_ptr_nothrow<IMFAttributes> spAllocatorAttributes;
+ GUID guidMajorType = GUID_NULL;
+ GUID guidSubtype = GUID_NULL;
+ BOOL fDXAllocator = FALSE;
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator );
+ RETURN_HR_IF_NULL(E_INVALIDARG, pOutputMediaType );
+
+ RETURN_IF_FAILED(pOutputMediaType->GetMajorType(&guidMajorType));
+
+ if (!IsEqualGUID(guidMajorType, MFMediaType_Video))
+ {
+ RETURN_HR(MF_E_INVALIDMEDIATYPE);
+ }
+
+ RETURN_IF_FAILED(pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype));
+ //
+ // Set Attributes on the allocator we need. First get the Bind Flags.
+ //
+ RETURN_IF_FAILED(MFCreateAttributes(&spAllocatorAttributes, 8));
+ RETURN_IF_FAILED(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1));
+
+ if (pDeviceManagerUnk != nullptr)
+ {
+ if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.get(), streamCategory, guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk)))
+ {
+ fDXAllocator = TRUE;
+ }
+ }
+
+ if (fDXAllocator)
+ {
+ RETURN_IF_FAILED(pAllocator->SetDirectXManager(pDeviceManagerUnk));
+ }
+
+ if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spPrivateAllocator))))
+ {
+ RETURN_IF_FAILED(spPrivateAllocator->InitializeSampleAllocatorEx(
+ ALLOCATOR_MIN_SAMPLES,
+ ALLOCATOR_MAX_SAMPLES,
+ spAllocatorAttributes.get(),
+ pOutputMediaType));
+ }
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ else if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spDefaultAllocator))))
+ {
+ RETURN_IF_FAILED(spDefaultAllocator->InitializeCaptureSampleAllocator(
+ 0, /*use sample size by MediaType*/
+ 0, /*metadata size*/
+ 0, /*default alignment*/
+ ALLOCATOR_MIN_SAMPLES,
+ spAllocatorAttributes.get(),
+ pOutputMediaType));
+ }
+#endif
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ bDxAllocator = fDXAllocator;
+
+ return hr;
+}
//
//@@@@ README: Creating an Allocator.. Please don't allocate samples individually using MFCreateSample as that can lead to fragmentation and is
// extremely inefficent. Instead create an Allocator which will create a fixed number of samples which are recycled when the pipeline returns back
@@ -1337,7 +1414,7 @@ HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
DMFTCHECKHR_GOTO(MFCreateAttributes(&spAllocatorAttributes, 8), done);
DMFTCHECKHR_GOTO(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1), done);
- if (pDeviceManagerUnk != nullptr)
+ if (pDeviceManagerUnk != nullptr)
{
if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.Get(), streamCategory,guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk)))
{
@@ -1349,6 +1426,7 @@ HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
{
DMFTCHECKHR_GOTO(spVideoSampleAllocator->SetDirectXManager(pDeviceManagerUnk), done);
}
+
DMFTCHECKHR_GOTO(spVideoSampleAllocator->InitializeSampleAllocatorEx(ALLOCATOR_MIN_SAMPLES, ALLOCATOR_MAX_SAMPLES, spAllocatorAttributes.Get(), pOutputMediaType), done);
*ppAllocator = spVideoSampleAllocator.Detach();
@@ -1487,16 +1565,16 @@ done:
HRESULT MergeSampleAttributes( _In_ IMFSample* pInSample, _Inout_ IMFSample* pOutSample)
{
HRESULT hr = S_OK;
- DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
UINT32 cAttributes = 0;
GUID guidAttribute;
PROPVARIANT varAttribute;
PROPVARIANT varAttributeExists;
-
PropVariantInit(&varAttribute);
PropVariantInit(&varAttributeExists);
+ DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
+
DMFTCHECKHR_GOTO(pInSample->GetCount(&cAttributes), done);
for (UINT32 i = 0; i < cAttributes; i++)
{
diff --git a/avstream/sampledevicemft/packages.config b/avstream/sampledevicemft/packages.config
new file mode 100644
index 00000000..09cb1163
--- /dev/null
+++ b/avstream/sampledevicemft/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.190716.2" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/avstream/sampledevicemft/stdafx.h b/avstream/sampledevicemft/stdafx.h
index e2f5a6cd..657208cd 100644
--- a/avstream/sampledevicemft/stdafx.h
+++ b/avstream/sampledevicemft/stdafx.h
@@ -41,6 +41,11 @@ using namespace std;
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
+#include <wil\result.h>
+#include <wil\resource.h>
+#include <wil\com.h>
+#include <wil\result_macros.h>
+
// @@@@ README Please check / uncheck various hash defines to enable/ disable features
// MF_DEVICEMFT_ASYNCPIN_NEEDED will show how to use Asynchronous queues
// MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED will show how to decode a compressed mediatype.. it supports H264 and MJPG
@@ -49,7 +54,7 @@ using namespace Microsoft::WRL;
//
//#define MF_DEVICEMFT_ADD_GRAYSCALER_ 1
#define MF_DEVICEMFT_ASYNCPIN_NEEDED 1
-#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 1
+//#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 0
#define MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES 1
//#define MF_DEVICEMFT_ENUM_HW_DECODERS 1
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx
index 8271e39d..73b6d10e 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx
Binary files differ
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj
index 57439bd9..f78f16b4 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj
@@ -26,7 +26,7 @@
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<SampleGuid>{F915ED95-7BE9-4CDB-B09A-0D3F4C9657FE}</SampleGuid>
<ProjectName>osrfx2_DCHU_base</ProjectName>
- <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj
index 36d85583..09724ba5 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj
@@ -27,7 +27,7 @@
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<SampleGuid>{1A4A32BA-1596-4F52-BC48-B85A6D8D5D12}</SampleGuid>
- <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectName>osrfx2_DCHU_filter</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj
index 225dcde2..bc56feac 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj
@@ -25,7 +25,7 @@
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<SampleGuid>{F19E45AF-8B05-4204-A66B-9BDBFE333233}</SampleGuid>
<ProjectName>osrfx2_DCHU_testapp</ProjectName>
- <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp
deleted file mode 100644
index 98a3975c..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*++
-
-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:
-
- CppWindowsService.cpp
-
-Abstract:
-
- The file defines the entry point of the application. According to the
- arguments in the command line, the function installs or uninstalls or
- starts the service by calling into different routines.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma region Includes
-#include <stdio.h>
-#include <windows.h>
-#include "ServiceBase.h"
-#include "SampleService.h"
-#pragma endregion
-
-//
-// Settings of the service
-//
-
-//
-// Internal name of the service
-//
-#define SERVICE_NAME L"OsrUsbFx2UmUserSvc"
-
-
-/*++
-
-Routine Description:
-
- Entry point for the service.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-INT
-wmain(
- INT Argc,
- WCHAR *Argv[]
- )
-{
- CSampleService service(SERVICE_NAME);
-
- if (!CServiceBase::Run(service))
- {
- wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError());
- }
-
- return 0;
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp
new file mode 100644
index 00000000..318e0dd5
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp
@@ -0,0 +1,856 @@
+/*++
+
+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:
+
+ DeviceContext.cpp
+
+Abstract:
+
+ Implements the functions to create/destroy device context by
+ registering/unregistering for device notifications.
+
+Environment:
+
+ User mode
+
+--*/
+
+#include "stdafx.h"
+
+extern HANDLE SvcStopRequestEvent;
+extern HCMNOTIFICATION InterfaceNotificationHandle;
+extern DEVICE_LIST_ENTRY DeviceList;
+extern SRWLOCK DeviceListLock;
+
+//
+// Keep track of running theads for unregistering device notifications
+//
+DWORD RunningUnregistrations = 0;
+SRWLOCK RunningUnregistrationsLock = SRWLOCK_INIT;
+CONDITION_VARIABLE UnregistrationComplete = CONDITION_VARIABLE_INIT;
+
+/*++
+
+Routine Description:
+
+ Setup device interface context by registering for device interface
+ notifications
+
+Arguments:
+
+ NULL
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+SetupDeviceInterfaceContext(
+ VOID
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ CONFIGRET Cr = CR_SUCCESS;
+ PCWSTR DeviceInterface = NULL;
+ PWSTR DeviceInterfaceList = NULL;
+ DWORD DeviceInterfaceListSize = 0;
+
+ //
+ // Register for device interface events to open and close the handle to
+ // the interface.
+ //
+ Err = RegisterInterfaceNotifications(&InterfaceNotificationHandle);
+
+ if (Err != ERROR_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+ //
+ // The interface may already be present on the system. Retrieve a list of
+ // existing interfaces
+ //
+ do
+ {
+ Cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListSize,
+ (LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2,
+ NULL,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
+
+ if (Cr != CR_SUCCESS)
+ {
+ break;
+ }
+
+ if (DeviceInterfaceList != NULL)
+ {
+ free(DeviceInterfaceList);
+ }
+
+ DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListSize * sizeof(WCHAR));
+
+ if (DeviceInterfaceList == NULL)
+ {
+ Cr = CR_OUT_OF_MEMORY;
+ break;
+ }
+
+ Cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2,
+ NULL,
+ DeviceInterfaceList,
+ DeviceInterfaceListSize,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
+ } while (Cr == CR_BUFFER_SMALL);
+
+ if (Cr != CR_SUCCESS)
+ {
+ Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA);
+ goto cleanup;
+ }
+
+ //
+ // Register for notifications on existing device interfaces
+ //
+ for (DeviceInterface = DeviceInterfaceList;
+ *DeviceInterface != L'\0';
+ DeviceInterface += wcslen(DeviceInterface) + 1)
+ {
+ RegisterDeviceNotifications(DeviceInterface);
+ }
+
+cleanup:
+
+ if (DeviceInterfaceList != NULL)
+ {
+ free(DeviceInterfaceList);
+ }
+
+ return Err;
+}
+
+
+/*++
+
+Routine Description:
+
+ Clean up device interface context
+
+Arguments:
+
+ NULL
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+CleanupDeviceInterfaceContext(
+ VOID
+ )
+{
+ PDEVICE_CONTEXT Context = NULL;
+ BOOL NeedsUnregister = FALSE;
+
+ //
+ // Unregister from the interface first, so that re-appearance of the
+ // interface does not cause us to register device events again.
+ //
+ if (InterfaceNotificationHandle != NULL)
+ {
+ CM_Unregister_Notification(InterfaceNotificationHandle);
+ InterfaceNotificationHandle = NULL;
+ }
+
+ //
+ // Unregister notifications for device handles.
+ //
+ while (TRUE)
+ {
+ NeedsUnregister = FALSE;
+
+ AcquireSRWLockShared(&DeviceListLock);
+
+ if (IsDeviceListEmpty(&DeviceList))
+ {
+ ReleaseSRWLockShared(&DeviceListLock);
+ break;
+ }
+
+ //
+ // Get next device context
+ //
+ Context = CONTAINING_DEVICE_RECORD(DeviceList.Flink);
+
+ //
+ // The device context can be unregistered either within notification
+ // callbacks or cleanup routines. Synchronize these operations to only
+ // unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ ReleaseSRWLockShared(&DeviceListLock);
+
+ if (NeedsUnregister)
+ {
+ //
+ // Remove next device from device list
+ //
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(DeviceList.Flink);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ UnregisterDeviceNotifications(Context);
+ }
+ }
+
+ //
+ // Wait for all other unregistrations for device handle that is not in
+ // device list.
+ //
+ AcquireSRWLockShared(&RunningUnregistrationsLock);
+
+ while (RunningUnregistrations != 0)
+ {
+ SleepConditionVariableSRW(&UnregistrationComplete,
+ &RunningUnregistrationsLock,
+ INFINITE,
+ CONDITION_VARIABLE_LOCKMODE_SHARED);
+ }
+
+ ReleaseSRWLockShared(&RunningUnregistrationsLock);
+}
+
+
+/*++
+
+Routine Description:
+
+ Handles a device query remove notification.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+DeviceQueryRemoveAction(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ if (Context->DeviceHandle != INVALID_HANDLE_VALUE)
+ {
+ //
+ // Close open handles to allow the device to be query removed
+ //
+ CloseHandle(Context->DeviceHandle);
+
+ Context->DeviceHandle = INVALID_HANDLE_VALUE;
+ }
+}
+
+
+/*++
+
+Routine Description:
+
+ Handles a device query remove failed notification.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+DeviceQueryRemoveFailedAction(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ PWSTR DeviceInterfacePath = NULL;
+ BOOL NeedsUnregister = FALSE;
+
+ //
+ // Keep a record of device symbolic link since the callback context will
+ // be freed up during unregistration
+ //
+ DeviceInterfacePath = Context->SymbolicLink;
+ Context->SymbolicLink = NULL;
+
+ //
+ // The device context can be unregistered either within notification
+ // callbacks or cleanup routines. Synchronize these operations to only
+ // unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ //
+ // Remove device from device list if needed
+ //
+ if (NeedsUnregister)
+ {
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(&Context->ListEntry);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ //
+ // Unregister notifications for the old device handle from a deferred
+ // routine since CM_Unregister_Notification can not be called from a
+ // notification callback
+ //
+ AcquireSRWLockExclusive(&RunningUnregistrationsLock);
+ RunningUnregistrations++;
+ ReleaseSRWLockExclusive(&RunningUnregistrationsLock);
+
+ QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread,
+ Context,
+ WT_EXECUTEDEFAULT);
+ }
+
+ //
+ // Re-register for device notifications on a new device handle
+ //
+ RegisterDeviceNotifications(DeviceInterfacePath);
+
+ //
+ // Free memory that the callback context used to point at but was not freed
+ // during unregistration
+ //
+ free(DeviceInterfacePath);
+}
+
+/*++
+
+Routine Description:
+
+ Handles a device remove complete notification.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ NULL
+
+--*/
+VOID
+DeviceRemoveCompleteAction(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ BOOL NeedsUnregister = FALSE;
+
+ //
+ // The device context can be unregistered either within notification
+ // callbacks or cleanup routines. Synchronize these operations to only
+ // unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ //
+ // Remove device from device list if needed
+ //
+ if (NeedsUnregister)
+ {
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(&Context->ListEntry);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ //
+ // Unregister notifications for the old device handle from a deferred
+ // routine since CM_Unregister_Notification can not be called from a
+ // notification callback
+ //
+ AcquireSRWLockExclusive(&RunningUnregistrationsLock);
+ RunningUnregistrations++;
+ ReleaseSRWLockExclusive(&RunningUnregistrationsLock);
+
+ QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread,
+ Context,
+ WT_EXECUTEDEFAULT);
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Handles device notifications.
+
+Arguments:
+
+ hNotify - The notification that spurred this callback
+
+ hContext - The callback context
+
+ Action - The type of callback
+
+ EventData - Additional information about this callback
+
+ EventDataSize - The size of EventData
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+WINAPI
+DeviceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ )
+{
+ PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
+
+ UNREFERENCED_PARAMETER(EventData);
+ UNREFERENCED_PARAMETER(EventDataSize);
+
+ //
+ // In case this callback fires before the registration call returns, make
+ // sure the notification handle is properly set
+ //
+ Context->DeviceNotificationHandle = hNotify;
+
+ switch (Action)
+ {
+ case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE:
+ DeviceQueryRemoveAction(Context);
+ break;
+
+ case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED:
+ DeviceQueryRemoveFailedAction(Context);
+ break;
+
+ case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING:
+ case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE:
+ DeviceRemoveCompleteAction(Context);
+ break;
+
+ default:
+ break;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+ Register for device notifications.
+
+Arguments:
+
+ DeviceInterfacePath - The symbolic link path of the device interface
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+RegisterDeviceNotifications(
+ _In_ PCWSTR DeviceInterfacePath
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ CONFIGRET Cr = CR_SUCCESS;
+ PDEVICE_CONTEXT Context = NULL;
+ PDEVICE_LIST_ENTRY Link = NULL;
+ DWORD BufferSize = 0;
+ CM_NOTIFY_FILTER NotifyFilter = {0};
+
+ //
+ // Check whether the device interface has already been registered for device
+ // handle notifications since it can be done either in interface arrival
+ // callback routine or initial device interface setup routine
+ //
+ AcquireSRWLockExclusive(&DeviceListLock);
+
+ for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink)
+ {
+ Context = CONTAINING_DEVICE_RECORD(Link);
+
+ if (_wcsicmp(DeviceInterfacePath, Context->SymbolicLink) == 0)
+ {
+ break;
+ }
+ }
+
+ if (Link != &DeviceList)
+ {
+ Err = ERROR_SUCCESS;
+ goto cleanup;
+ }
+
+ //
+ // Create a new device context
+ //
+ Context = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT));
+
+ if (Context == NULL)
+ {
+ Err = ERROR_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ //
+ // Initialize device context
+ //
+ ZeroMemory(Context, sizeof(DEVICE_CONTEXT));
+ Context->DeviceHandle = INVALID_HANDLE_VALUE;
+ InitializeCriticalSection(&Context->ContextLock);
+
+ //
+ // Fill out the context and register device handle notifications
+ //
+ BufferSize = (DWORD)wcslen(DeviceInterfacePath) + 1;
+ Context->SymbolicLink = (PWSTR)malloc(BufferSize * sizeof(WCHAR));
+
+ if ((Context->SymbolicLink == NULL) ||
+ (FAILED(StringCchCopy(Context->SymbolicLink,
+ BufferSize,
+ DeviceInterfacePath))))
+ {
+ Err = ERROR_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ Context->DeviceHandle = CreateFile(Context->SymbolicLink,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL, // default security
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ if (Context->DeviceHandle == INVALID_HANDLE_VALUE)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ NotifyFilter.cbSize = sizeof(NotifyFilter);
+ NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE;
+ NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceHandle;
+
+ Cr = CM_Register_Notification(&NotifyFilter,
+ (PVOID)Context,
+ (PCM_NOTIFY_CALLBACK)DeviceCallback,
+ &Context->DeviceNotificationHandle);
+
+ if (Cr != CR_SUCCESS)
+ {
+ Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA);
+ goto cleanup;
+ }
+
+ //
+ // Add the device entry to device list
+ //
+ InsertTailDeviceListEntry(&DeviceList, &Context->ListEntry);
+ Context = NULL;
+
+cleanup:
+
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ //
+ // Clean up device context if an error occurred.
+ //
+ if (Context != NULL)
+ {
+ if (Context->SymbolicLink != NULL)
+ {
+ free(Context->SymbolicLink);
+ }
+
+ if (Context->DeviceHandle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(Context->DeviceHandle);
+ }
+
+ free(Context);
+ }
+
+ return Err;
+}
+
+
+VOID
+UnregisterDeviceNotifications(
+ _Inout_ PDEVICE_CONTEXT Context
+ )
+{
+ if (Context->DeviceNotificationHandle != NULL)
+ {
+ CM_Unregister_Notification(Context->DeviceNotificationHandle);
+ }
+
+ if (Context->DeviceHandle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(Context->DeviceHandle);
+ }
+
+ if (Context->SymbolicLink != NULL)
+ {
+ free(Context->SymbolicLink);
+ }
+
+ DeleteCriticalSection(&Context->ContextLock);
+
+ free(Context);
+}
+
+
+/*++
+
+Routine Description:
+
+ This worker thread avoids a deadlock when unregistering device notifications.
+ Rather than calling CM_Unregister_Notification from the callback, the
+ callback gives that work to a separate thread to avoid deadlock.
+
+Arguments:
+
+ lpThreadParameter - The thread data passed to the function
+
+Return Value:
+
+ Zero
+
+--*/
+DWORD
+WINAPI
+UnregisterDeviceNotificationsWorkerThread(
+ _In_ PVOID lpThreadParameter
+ )
+{
+ PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)lpThreadParameter;
+
+ UnregisterDeviceNotifications(Context);
+
+ //
+ // Decrease running unregistrations
+ //
+ AcquireSRWLockExclusive(&RunningUnregistrationsLock);
+ RunningUnregistrations--;
+ ReleaseSRWLockExclusive(&RunningUnregistrationsLock);
+
+ WakeAllConditionVariable(&UnregistrationComplete);
+
+ return 0;
+}
+
+
+/*++
+
+Routine Description:
+
+ Handles an interface arrival notification.
+
+Arguments:
+
+ hNotify - The notification that fired the callback
+
+ hContext - The callback context
+
+ Action - The type of notification
+
+ EventData - Additional information about the callback
+
+ EventDataSize - The size of EventData
+
+Return Value:
+
+ Notification callback should return ERROR_SUCCESS.
+
+--*/
+DWORD
+WINAPI
+InterfaceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ )
+{
+ PDEVICE_CONTEXT Context = NULL;
+ PDEVICE_LIST_ENTRY Link = NULL;
+ BOOL NeedsUnregister = FALSE;
+
+ UNREFERENCED_PARAMETER(hNotify);
+ UNREFERENCED_PARAMETER(hContext);
+ UNREFERENCED_PARAMETER(EventDataSize);
+
+ switch (Action)
+ {
+ case CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL:
+ //
+ // Register for device notifications
+ //
+ RegisterDeviceNotifications(EventData->u.DeviceInterface.SymbolicLink);
+ break;
+
+ case CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL:
+ //
+ // The device may still be running in the case where the driver disables
+ // its interfaces. Find whether it is still on the device list and clean
+ // it up.
+ //
+ AcquireSRWLockShared(&DeviceListLock);
+
+ for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink)
+ {
+ Context = CONTAINING_DEVICE_RECORD(Link);
+
+ if (_wcsicmp(EventData->u.DeviceInterface.SymbolicLink,
+ Context->SymbolicLink) == 0)
+ {
+ //
+ // The device context can be unregistered either within
+ // notification callbacks or cleanup routines. Synchronize these
+ // operations to only unregister once.
+ //
+ EnterCriticalSection(&Context->ContextLock);
+
+ if (!Context->Unregistered)
+ {
+ Context->Unregistered = TRUE;
+ NeedsUnregister = TRUE;
+ }
+
+ LeaveCriticalSection(&Context->ContextLock);
+
+ break;
+ }
+ }
+
+ ReleaseSRWLockShared(&DeviceListLock);
+
+ if (NeedsUnregister)
+ {
+ //
+ // Remove the device from device list
+ //
+ AcquireSRWLockExclusive(&DeviceListLock);
+ RemoveDeviceListEntry(&Context->ListEntry);
+ ReleaseSRWLockExclusive(&DeviceListLock);
+
+ UnregisterDeviceNotifications(Context);
+ }
+
+ //
+ // Notify service to stop if this is the last device interface
+ //
+ AcquireSRWLockShared(&DeviceListLock);
+
+ if (IsDeviceListEmpty(&DeviceList))
+ {
+ SetEvent(SvcStopRequestEvent);
+ }
+
+ ReleaseSRWLockShared(&DeviceListLock);
+ break;
+
+ default:
+ break;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+ Registers the service for interface notifications
+
+Arguments:
+
+ pInterfaceNotificationHandle - Pointer to receive the HCMNOTIFICATION handle
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+RegisterInterfaceNotifications(
+ _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ CONFIGRET Cr = CR_SUCCESS;
+ CM_NOTIFY_FILTER NotifyFilter = {0};
+
+ NotifyFilter.cbSize = sizeof(NotifyFilter);
+ NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
+ NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2;
+
+ //
+ // Register for device interface events to open and close the handle to
+ // the interface.
+ //
+ Cr = CM_Register_Notification(&NotifyFilter,
+ NULL,
+ (PCM_NOTIFY_CALLBACK)InterfaceCallback,
+ pInterfaceNotificationHandle);
+
+ if (Cr != CR_SUCCESS)
+ {
+ Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA);
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h
new file mode 100644
index 00000000..4d744989
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h
@@ -0,0 +1,155 @@
+/*++
+
+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.
+
+--*/
+
+#pragma once
+
+//
+// Device list
+//
+typedef struct _DEVICE_LIST_ENTRY {
+ struct _DEVICE_LIST_ENTRY *Flink;
+ struct _DEVICE_LIST_ENTRY *Blink;
+} DEVICE_LIST_ENTRY, *PDEVICE_LIST_ENTRY;
+
+FORCEINLINE
+VOID
+InitializeDeviceListHead(
+ _Out_ PDEVICE_LIST_ENTRY Head
+ )
+{
+ Head->Blink = Head->Flink = Head;
+}
+
+FORCEINLINE
+BOOL
+IsDeviceListEmpty(
+ _In_ const PDEVICE_LIST_ENTRY ListHead
+ )
+
+{
+ return (ListHead->Flink == ListHead);
+}
+
+FORCEINLINE
+VOID
+RemoveDeviceListEntry(
+ _In_ PDEVICE_LIST_ENTRY Entry
+ )
+{
+ PDEVICE_LIST_ENTRY Prev = Entry->Blink;
+ PDEVICE_LIST_ENTRY Next = Entry->Flink;
+
+ Prev->Flink = Next;
+ Next->Blink = Prev;
+}
+
+FORCEINLINE
+VOID
+InsertTailDeviceListEntry(
+ _Inout_ PDEVICE_LIST_ENTRY Head,
+ _Inout_ PDEVICE_LIST_ENTRY Entry
+ )
+{
+ PDEVICE_LIST_ENTRY Tail = Head->Blink;
+
+ Tail->Flink = Entry;
+ Entry->Blink = Tail;
+ Entry->Flink = Head;
+ Head->Blink = Entry;
+}
+
+//
+// Context for device handle
+//
+typedef struct _DEVICE_CONTEXT {
+ PWSTR SymbolicLink;
+ HANDLE DeviceHandle;
+ HCMNOTIFICATION DeviceNotificationHandle;
+ BOOL Unregistered;
+ CRITICAL_SECTION ContextLock;
+ DEVICE_LIST_ENTRY ListEntry;
+} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
+
+#define CONTAINING_DEVICE_RECORD(address) ((PDEVICE_CONTEXT)( \
+ (PCHAR)(address) - \
+ (ULONG_PTR)(&((PDEVICE_CONTEXT)0)->ListEntry)))
+
+//
+// Device interface context
+//
+DWORD
+SetupDeviceInterfaceContext(
+ VOID
+ );
+
+VOID
+CleanupDeviceInterfaceContext(
+ VOID
+ );
+
+//
+// Device notifications related
+//
+VOID
+DeviceQueryRemoveAction(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+VOID
+DeviceQueryRemoveFailedAction(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+VOID
+DeviceRemoveCompleteAction(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+DWORD
+WINAPI
+DeviceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ );
+
+DWORD
+RegisterDeviceNotifications(
+ _In_ PCWSTR DeviceInterfacePath
+ );
+
+VOID
+UnregisterDeviceNotifications(
+ _Inout_ PDEVICE_CONTEXT Context
+ );
+
+DWORD
+WINAPI
+InterfaceCallback(
+ _In_ HCMNOTIFICATION hNotify,
+ _In_ PVOID hContext,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_ PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize
+ );
+
+DWORD
+RegisterInterfaceNotifications(
+ _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle
+ );
+
+DWORD
+WINAPI
+UnregisterDeviceNotificationsWorkerThread(
+ _In_ PVOID lpThreadParameter
+ );
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp
new file mode 100644
index 00000000..ced895cc
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp
@@ -0,0 +1,192 @@
+/*++
+
+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:
+
+ DeviceControl.cpp
+
+Abstract:
+
+ Implements the functions to control the OSR USB FX2 device.
+
+Environment:
+
+ User mode
+
+--*/
+
+#include "stdafx.h"
+
+//
+// Keep track of where the OSRFX2 device's bar graph currently is.
+//
+INT CurrentBar;
+BAR_GRAPH_STATE BarGraphState;
+
+/*++
+
+Routine Description:
+
+ Initialize global variables for OSRFX2 device.
+
+Arguments:
+
+ VOID
+
+Return Value:
+
+ VOID
+
+--*/
+VOID
+OsrFx2InitializeDevice(
+ VOID
+ )
+{
+ CurrentBar = 0;
+}
+
+
+/*++
+
+Routine Description:
+
+ Turns off all of the bar graph lights on the OSR USB FX2 device.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ VOID
+
+--*/
+DWORD
+OsrFx2ClearAllBars(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ ULONG BytesReturned;
+
+ BarGraphState.BarsAsUChar = 0;
+
+ if (!DeviceIoControl(Context->DeviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &BarGraphState, // Pointer to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Pointer to OutBuffer
+ 0, // Length of OutBuffer
+ &BytesReturned, // BytesReturned
+ 0)) // Pointer to Overlapped structure
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
+
+
+/*++
+
+Routine Description:
+
+ Lights the next bar on the OSR USB FX2 device.
+
+Arguments:
+
+ Context - The callback context
+
+Return Value:
+
+ VOID
+
+--*/
+DWORD
+OsrFx2LightNextBar(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+ ULONG BytesReturned;
+
+ //
+ // Normalize to 0-7
+ //
+ CurrentBar += 1;
+
+ if (CurrentBar > 7)
+ {
+ CurrentBar = 0;
+ }
+
+ BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar;
+
+ if (!DeviceIoControl(Context->DeviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &BarGraphState, // Pointer to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Pointer to OutBuffer
+ 0, // Length of OutBuffer
+ &BytesReturned, // BytesReturned
+ 0)) // Pointer to Overlapped structure
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
+
+/*++
+
+Routine Description:
+
+ Lights the next bar on the OSRFX2 device.
+
+Arguments:
+
+ Context - The device context
+
+Return Value:
+
+ A Win32 error code.
+
+--*/
+DWORD
+OsrFx2ControlDevice(
+ _In_ PDEVICE_CONTEXT Context
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+
+ Err = OsrFx2ClearAllBars(Context);
+
+ if (Err != ERROR_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+ Err = OsrFx2LightNextBar(Context);
+
+ if (Err != ERROR_SUCCESS)
+ {
+ goto cleanup;
+ }
+
+cleanup:
+
+ return Err;
+}
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h
new file mode 100644
index 00000000..235e64ba
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h
@@ -0,0 +1,144 @@
+/*++
+
+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.
+
+--*/
+
+#pragma once
+#pragma warning(disable : 4201) // disable nameless struct/union warning
+
+//
+// {573E8C73-0CB4-4471-A1BF-FAB26C31D384}
+//
+DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2,
+ 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);
+
+//
+// Define the structures that will be used by the IOCTL interface to the driver
+//
+
+// BAR_GRAPH_STATE is a bit field structure with each bit corresponding to one
+// of the bar graph on the OSRFX2 Development Board
+//
+typedef struct _BAR_GRAPH_STATE {
+
+ union {
+
+ struct {
+ //
+ // Individual bars starting from the top of the stack of bars
+ //
+ // NOTE: There are actually 10 bars, but the very top two do not
+ // light and are not counted here
+ //
+ UCHAR Bar1 : 1;
+ UCHAR Bar2 : 1;
+ UCHAR Bar3 : 1;
+ UCHAR Bar4 : 1;
+ UCHAR Bar5 : 1;
+ UCHAR Bar6 : 1;
+ UCHAR Bar7 : 1;
+ UCHAR Bar8 : 1;
+ };
+
+ //
+ // The state of all the bar graph as a single
+ // UCHAR
+ //
+ UCHAR BarsAsUChar;
+ };
+
+} BAR_GRAPH_STATE, *PBAR_GRAPH_STATE;
+
+//
+// SWITCH_STATE is a bit field structure with each bit corresponding to one of
+// the switches on the OSRFX2 Development Board
+//
+typedef struct _SWITCH_STATE {
+
+ union {
+ struct {
+ //
+ // Individual switches starting from the left of the set of switches
+ //
+ UCHAR Switch1 : 1;
+ UCHAR Switch2 : 1;
+ UCHAR Switch3 : 1;
+ UCHAR Switch4 : 1;
+ UCHAR Switch5 : 1;
+ UCHAR Switch6 : 1;
+ UCHAR Switch7 : 1;
+ UCHAR Switch8 : 1;
+ };
+
+ //
+ // The state of all the switches as a single
+ // UCHAR
+ //
+ UCHAR SwitchesAsUChar;
+ };
+
+} SWITCH_STATE, *PSWITCH_STATE;
+
+DWORD
+OsrFx2ControlDevice(
+ _In_ PDEVICE_CONTEXT Context
+ );
+
+VOID
+OsrFx2InitializeDevice(
+ VOID
+ );
+
+#define IOCTL_INDEX 0x800
+#define FILE_DEVICE_OSRUSBFX2 65500U
+
+#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 1, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 3, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 4, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 5, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 6, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 7, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 8, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 9, \
+ METHOD_OUT_DIRECT, \
+ FILE_READ_ACCESS)
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp
deleted file mode 100644
index a02ac24a..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp
+++ /dev/null
@@ -1,1217 +0,0 @@
-/*++
-
-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:
-
- Main.cpp
-
-Abstract:
-
- Implements the functions to control the OSR USB FX2 device.
-
-Environment:
-
- User mode
-
---*/
-
-#include "Main.h"
-#include "Utils.h"
-
-//
-// Keep track of where the OSRFX2 device's bar graph currently is.
-//
-INT CurrentBar;
-BAR_GRAPH_STATE BarGraphState;
-
-/*++
-
-Routine Description:
-
- Sets the variables in this service to their default values.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-SetVariables()
-{
- CurrentBar = 0;
-}
-
-
-/*++
-
-Routine Description:
-
- Retrieves the device path of a given interface.
-
-Arguments:
-
- InterfaceGuid - The GUID of the interface to search for
-
- DevicePath - The resulting device path
-
- DevicePathLength - The length of DevicePath
-
-Return Value:
-
- TRUE if the function succeeded and FALSE otherwise. Errors
- are logged in the Application event log.
-
---*/
-_Success_(return)
-BOOL
-GetDevicePath(
- _In_ LPGUID InterfaceGuid,
- _Out_writes_z_(DevicePathLength) PWCHAR DevicePath,
- _In_ size_t DevicePathLength
- )
-{
- HRESULT hr = E_FAIL;
- CONFIGRET cr = CR_SUCCESS;
- PWSTR DeviceInterfaceList = NULL;
- ULONG DeviceInterfaceListLength = 0;
- PWSTR NextInterface;
-
- //
- // Determine if there are any interfaces that match the OSRFX2 device.
- //
- cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListLength,
- InterfaceGuid,
- NULL,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
-
- if (cr != CR_SUCCESS)
- {
- WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size",
- CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND));
- goto cleanup;
- }
-
- if (DeviceInterfaceListLength < 1)
- {
- WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size",
- CM_MapCrToWin32Err(cr, ERROR_EMPTY));
- goto cleanup;
- }
-
- DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListLength * sizeof(WCHAR));
-
- if (DeviceInterfaceList == NULL)
- {
- WriteToEventLog(L"Failed to allocate memory for the device interface list",
- TRACE_LEVEL_ERROR);
- goto cleanup;
- }
-
- cr = CM_Get_Device_Interface_List(InterfaceGuid,
- NULL,
- DeviceInterfaceList,
- DeviceInterfaceListLength,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
-
- if (cr != CR_SUCCESS)
- {
- WriteToErrorLog(L"CM_Get_Device_Interface_List",
- CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND));
- goto cleanup;
- }
-
- if (*DeviceInterfaceList == UNICODE_NULL)
- {
- WriteToEventLog(L"CM_Get_Device_Interface_List returned an empty list",
- TRACE_LEVEL_ERROR);
- }
-
- //
- // This sample only expects one interface for the OSRFX2 device. For other
- // devices, though, it maybe necessary to sift through the interfaces
- // from CM_Get_Device_Interface_List in order to find the correct device.
- //
- NextInterface = DeviceInterfaceList + wcslen(DeviceInterfaceList) + 1;
-
- if (*NextInterface != UNICODE_NULL)
- {
- WriteToEventLog(L"More than one device interface instance found. "
- "Selecting first matching device.",
- TRACE_LEVEL_WARNING);
- }
-
- hr = StringCchCopy(DevicePath, DevicePathLength, DeviceInterfaceList);
-
- if (FAILED(hr))
- {
- WriteToErrorLog(L"StringCchCopy", HRESULT_CODE(hr));
- goto cleanup;
- }
-
-cleanup:
-
- if (DeviceInterfaceList != NULL)
- {
- free(DeviceInterfaceList);
- }
-
- return (cr == CR_SUCCESS);
-}
-
-
-/*++
-
-Routine Description:
-
- Opens up the OSR USB FX2 device handle.
-
-Arguments:
-
- Synchronous - Whether or not this device should be opened for syncrhonous
- access
-
-Return Value:
-
- The handle to the OSR USB FX2 device.
-
---*/
-_Check_return_
-_Ret_notnull_
-_Success_(return != INVALID_HANDLE_VALUE)
-HANDLE
-OpenDevice(
- _In_ BOOL Synchronous
- )
-{
- HANDLE DeviceHandle = INVALID_HANDLE_VALUE;
- WCHAR DeviceName[MAX_DEVPATH_LENGTH];
-
- if (!GetDevicePath((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2,
- DeviceName,
- sizeof(DeviceName) / sizeof(DeviceName[0])))
- {
- goto cleanup;
- }
-
- //
- // Open a handle to the interface.
- //
- if (Synchronous)
- {
- DeviceHandle = CreateFile(DeviceName,
- GENERIC_WRITE | GENERIC_READ,
- FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, // default security
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- }
- else
- {
- DeviceHandle = CreateFile(DeviceName,
- GENERIC_WRITE | GENERIC_READ,
- FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, // default security
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
- NULL);
- }
-
- if (DeviceHandle == INVALID_HANDLE_VALUE)
- {
- WriteToErrorLog(L"CreateFile", GetLastError());
- }
- else
- {
- WriteToEventLog(L"Opened Device Successfully", TRACE_LEVEL_INFORMATION);
- }
-
-cleanup:
-
- return DeviceHandle;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles an interface arrival notification.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-InterfaceArrivalAction(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- //
- // Now that the interface has arrived, open a handle to it, and then
- // register that handle for device events.
- //
- EnterCriticalSection(&Context->Lock);
-
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- //
- // The handle was already retrieved.
- //
- Err = ERROR_SUCCESS;
- goto cleanup;
- }
-
- Context->DeviceInterfaceHandle = OpenDevice(FALSE);
-
- if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE)
- {
- Err = GetLastError();
- WriteToErrorLog(L"Could not open device interface", Err);
- goto cleanup;
- }
-
- Err = RegisterDeviceNotifications(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not register device notifications", Err);
- goto cleanup;
- }
-
-cleanup:
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles an interface arrival notification.
-
-Arguments:
-
- hNotify - The notification that fired the callback
-
- hContext - The callback context
-
- Action - The type of notification
-
- EventData - Additional information about the callback
-
- EventDataSize - The size of EventData
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-InterfaceCallback(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PVOID hContext,
- _In_ CM_NOTIFY_ACTION Action,
- _In_ PCM_NOTIFY_EVENT_DATA EventData,
- _In_ DWORD EventDataSize
- )
-{
- DWORD Err = ERROR_SUCCESS;
- PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
-
- //
- // Validate Context.
- //
- if (Context == NULL)
- {
- goto cleanup;
- }
-
- if (Action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL)
- {
- Err = InterfaceArrivalAction(Context);
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Registers the service for notifications using the notification handle in
- Context.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-RegisterInterfaceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- CONFIGRET cr;
- CM_NOTIFY_FILTER NotifyFilter = {0};
-
- if (Context == NULL)
- {
- goto cleanup;
- }
-
- ZeroMemory(&NotifyFilter, sizeof(NotifyFilter));
- NotifyFilter.cbSize = sizeof(NotifyFilter);
- NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
- NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2;
-
- cr = CM_Register_Notification(&NotifyFilter,
- (PVOID)Context,
- (PCM_NOTIFY_CALLBACK)InterfaceCallback,
- &Context->InterfaceNotificationHandle);
-
- if (cr != CR_SUCCESS)
- {
- Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
- WriteToErrorLog(L"CM_Register_Notification", Err);
- goto cleanup;
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Unregister for interface notifications. Note, this routine deadlocks
- when called from an interface callback.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-UnregisterInterfaceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- CONFIGRET cr;
-
- if (Context->InterfaceNotificationHandle != NULL)
- {
- cr = CM_Unregister_Notification(Context->InterfaceNotificationHandle);
-
- Context->InterfaceNotificationHandle = NULL;
- }
-
- return CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
-}
-
-
-/*++
-
-Routine Description:
-
- Callback for when a device is being query removed.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceQueryRemoveAction(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- //
- // Close open handles to allow the device to exit
- //
- CloseHandle(Context->DeviceInterfaceHandle);
-
- Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- This callback avoids a deadlock when unregistering device notifications.
- Rather than calling CM_Unregister_Notification from the callback, the
- callback gives that work to a separate thread to avoid deadlock.
-
-Arguments:
-
- Instance - The thread's callback instance
-
- hContext - The callback context
-
- pWork - The thread handle
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CALLBACK
-UnregisterWorkerThreadCallback(
- _Inout_ PTP_CALLBACK_INSTANCE Instance,
- _Inout_opt_ PVOID hContext,
- _Inout_ PTP_WORK pWork
- )
-{
- PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
-
- EnterCriticalSection(&Context->Lock);
-
- UnregisterDeviceNotifications(Context);
-
- //
- // Close the device handle.
- //
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- CloseHandle(Context->DeviceInterfaceHandle);
-
- Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- }
-
- LeaveCriticalSection(&Context->Lock);
-}
-
-
-/*++
-
-Routine Description:
-
- Handles a device query remove failed notification.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceQueryRemoveFailedAction(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- //
- // In case this callback fires before the registration call returns, make
- // sure the notification handle is properly set.
- //
- Context->InterfaceNotificationHandle = hNotify;
-
- //
- // Unregister the device callback, and then close the handle
- //
- if (!Context->Unregister)
- {
- Context->Unregister = TRUE;
- SubmitThreadpoolWork(Context->Work);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- //
- // Wait for the callback and then re-register the device
- //
- WaitForThreadpoolWorkCallbacks(Context->Work, FALSE);
-
- EnterCriticalSection(&Context->Lock);
-
- if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE)
- {
- Context->DeviceInterfaceHandle = OpenDevice(FALSE);
- }
-
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- RegisterDeviceNotifications(Context);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles a device remove pending notification.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceRemovePendingAction(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- //
- // In case this callback fires before the registration call returns, make
- // sure the notification handle is properly set.
- //
- Context->InterfaceNotificationHandle = hNotify;
-
- //
- // Unregister the device callback, and then close the handle
- //
- if (!Context->Unregister)
- {
- Context->Unregister = TRUE;
- SubmitThreadpoolWork(Context->Work);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles a device remove complete notification.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceRemoveCompleteAction(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- //
- // In case this callback fires before the registration call returns, make
- // sure the notification handle is properly set.
- //
- Context->InterfaceNotificationHandle = hNotify;
-
- //
- // Unregister the device callback, and then close the handle
- //
- if (!Context->Unregister)
- {
- Context->Unregister = TRUE;
- SubmitThreadpoolWork(Context->Work);
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Handles device notifications.
-
-Arguments:
-
- hNotify - The notification that spurred this callback
-
- hContext - The callback context
-
- Action - The type of callback
-
- EventData - Additional information about this callback
-
- EventDataSize - The size of EventData
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-DeviceCallback(
- _In_ HCMNOTIFICATION hNotify,
- _In_ PVOID hContext,
- _In_ CM_NOTIFY_ACTION Action,
- _In_ PCM_NOTIFY_EVENT_DATA EventData,
- _In_ DWORD EventDataSize
- )
-{
- DWORD Err = ERROR_SUCCESS;
- PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext;
-
- //
- // Validate Context.
- //
- if (Context == NULL)
- {
- goto cleanup;
- }
-
- switch (Action)
- {
- case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE:
- DeviceQueryRemoveAction(Context);
- break;
-
- case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED:
- DeviceQueryRemoveFailedAction(hNotify, Context);
- break;
-
- case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING:
- DeviceRemovePendingAction(hNotify, Context);
- break;
-
- case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE:
- DeviceRemoveCompleteAction(hNotify, Context);
- break;
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Register for device notifications.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-RegisterDeviceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- CONFIGRET cr;
- CM_NOTIFY_FILTER NotifyFilter = {0};
-
- NotifyFilter.cbSize = sizeof(NotifyFilter);
- NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE;
- NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceInterfaceHandle;
-
- cr = CM_Register_Notification(&NotifyFilter,
- (PVOID)Context,
- (PCM_NOTIFY_CALLBACK)DeviceCallback,
- &Context->DeviceNotificationHandle);
-
- if (cr != CR_SUCCESS)
- {
- Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
- WriteToEventLog(L"Could not register for notifications", TRACE_LEVEL_WARNING);
- goto cleanup;
- }
-
- Context->Unregister = FALSE;
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Unregister for device notifications.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-UnregisterDeviceNotifications(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- CONFIGRET cr;
-
- if (Context->DeviceNotificationHandle != NULL)
- {
- cr = CM_Unregister_Notification(Context->DeviceNotificationHandle);
-
- if (cr != CR_SUCCESS)
- {
- Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA);
- WriteToEventLog(L"Could not unregister notifications", TRACE_LEVEL_WARNING);
- }
-
- Context->DeviceNotificationHandle = NULL;
- }
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Initialize the given PDEVICE_CONTEXT.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-InitializeContext(
- _Out_ PDEVICE_CONTEXT *Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- BOOL LockInitialized = FALSE;
- BOOL LockEntered = FALSE;
- BOOL InterfaceNotificationsInitialized = FALSE;
- BOOL DeviceNotificationsInitialized = FALSE;
- PDEVICE_CONTEXT DeviceContext;
-
- DeviceContext = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT));
-
- if (DeviceContext == NULL)
- {
- Err = ERROR_OUTOFMEMORY;
- goto cleanup;
- }
-
- DeviceContext->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- DeviceContext->LockEnabled = FALSE;
- DeviceContext->InterfaceNotificationsEnabled = FALSE;
- DeviceContext->DeviceNotificationsEnabled = FALSE;
-
- InitializeCriticalSection(&DeviceContext->Lock);
- DeviceContext->LockEnabled = TRUE;
-
- DeviceContext->Work = CreateThreadpoolWork(UnregisterWorkerThreadCallback, (PVOID)DeviceContext, NULL);
-
- if (DeviceContext->Work == NULL)
- {
- Err = GetLastError();
- WriteToErrorLog(L"Could not create worker thread callback", Err);
- goto cleanup;
- }
-
- DeviceContext->DeviceNotificationHandle = NULL;
- DeviceContext->InterfaceNotificationHandle = NULL;
-
- //
- // Register for device interface events to open and close the handle to
- // the interface.
- //
- Err = RegisterInterfaceNotifications(DeviceContext);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not register notifications", Err);
- goto cleanup;
- }
-
- DeviceContext->InterfaceNotificationsEnabled = TRUE;
-
- EnterCriticalSection(&DeviceContext->Lock);
- LockEntered = TRUE;
-
- //
- // The interface may already have arrived while registering for
- // notifications. The lock could be moved earlier, but for sample
- // purposes this is the proper way to initialize notifications.
- //
- if (DeviceContext->DeviceInterfaceHandle == INVALID_HANDLE_VALUE)
- {
- DeviceContext->DeviceInterfaceHandle = OpenDevice(FALSE);
- }
-
- if (DeviceContext->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- Err = RegisterDeviceNotifications(DeviceContext);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not register device notifications", Err);
- goto cleanup;
- }
-
- DeviceContext->DeviceNotificationsEnabled = TRUE;
- }
-
- //
- // If OpenDevice ends up returning INVALID_HANDLE_VALUE, that's fine
- // since a notification for the interface will arrive later.
- //
-
-cleanup:
-
- if (LockEntered)
- {
- LeaveCriticalSection(&DeviceContext->Lock);
- }
-
- *Context = DeviceContext;
- DeviceContext = NULL;
-
- if (DeviceContext != NULL)
- {
- CloseContext(DeviceContext);
- }
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Clean up the given PDEVICE_CONTEXT.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-CloseContext(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- BOOL Unregister = FALSE;
-
- if (Context == NULL)
- {
- //
- // Nothing to remove.
- //
- goto cleanup;
- }
-
- EnterCriticalSection(&Context->Lock);
-
- if (!Context->Unregister)
- {
- //
- // Unregister from the callback here.
- //
- Unregister = TRUE;
- Context->Unregister = TRUE;
- }
-
- LeaveCriticalSection(&Context->Lock);
-
- //
- // Unregister from the interface first, so that re-appearance of the interface
- // doesn't cause us to register device events again.
- //
- if (Context->InterfaceNotificationsEnabled)
- {
- Err = UnregisterInterfaceNotifications(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not unregister interface notifications", Err);
- }
- }
-
- if (Unregister)
- {
- if (Context->DeviceNotificationsEnabled)
- {
- Err = UnregisterDeviceNotifications(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- WriteToErrorLog(L"Could not unregister device notifications", Err);
- }
- }
- }
- else
- {
- WaitForThreadpoolWorkCallbacks(Context->Work, FALSE);
- }
-
- //
- // No need to lock here, UnregisterDeviceNotifications will wait for all
- // outstanding callbacks before returning.
- //
- if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE)
- {
- CloseHandle(Context->DeviceInterfaceHandle);
-
- Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE;
- }
-
- if (Context->Work != NULL)
- {
- CloseThreadpoolWork(Context->Work);
- }
-
- DeleteCriticalSection(&Context->Lock);
-
- free(Context);
-
-cleanup:
-
- return Err;
-}
-
-/*++
-
-Routine Description:
-
- Turns off all of the bar graph lights on the OSR USB FX2 device.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- VOID
-
---*/
-DWORD
-ClearAllBars(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- ULONG BytesReturned;
-
- BarGraphState.BarsAsUChar = 0;
-
- if (!DeviceIoControl(Context->DeviceInterfaceHandle,
- IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
- &BarGraphState, // Pointer to InBuffer
- sizeof(BAR_GRAPH_STATE), // Length of InBuffer
- NULL, // Pointer to OutBuffer
- 0, // Length of OutBuffer
- &BytesReturned, // BytesReturned
- 0)) // Pointer to Overlapped structure
- {
- Err = GetLastError();
- WriteToErrorLog(L"DeviceIOControl", Err);
- goto cleanup;
- }
-
-cleanup:
-
- return Err;
-}
-
-
-/*++
-
-Routine Description:
-
- Lights the next bar on the OSR USB FX2 device.
-
-Arguments:
-
- Context - The callback context
-
-Return Value:
-
- VOID
-
---*/
-DWORD
-LightNextBar(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
- ULONG BytesReturned;
-
- //
- // Normalize to 0-7
- //
- CurrentBar += 1;
-
- if (CurrentBar > 7)
- {
- CurrentBar = 0;
- }
-
- BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar;
-
- if (!DeviceIoControl(Context->DeviceInterfaceHandle,
- IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
- &BarGraphState, // Pointer to InBuffer
- sizeof(BAR_GRAPH_STATE), // Length of InBuffer
- NULL, // Pointer to OutBuffer
- 0, // Length of OutBuffer
- &BytesReturned, // BytesReturned
- 0)) // Pointer to Overlapped structure
- {
- Err = GetLastError();
- WriteToErrorLog(L"DeviceIOControl", Err);
- goto cleanup;
- }
-
-cleanup:
-
- return Err;
-}
-
-/*++
-
-Routine Description:
-
- Lights the next bar on the OSRFX2 device.
-
-Arguments:
-
- Context - The device context
-
-Return Value:
-
- A Win32 error code.
-
---*/
-DWORD
-ControlDevice(
- _In_ PDEVICE_CONTEXT Context
- )
-{
- DWORD Err = ERROR_SUCCESS;
-
- EnterCriticalSection(&Context->Lock);
-
- Err = ClearAllBars(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- goto cleanup;
- }
-
- Err = LightNextBar(Context);
-
- if (Err != ERROR_SUCCESS)
- {
- goto cleanup;
- }
-
-cleanup:
-
- LeaveCriticalSection(&Context->Lock);
-
- return Err;
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h
deleted file mode 100644
index 3b8be711..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/*++
-
-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:
-
- Main.h
-
-Abstract:
-
- Implements the functions to control the OSR USB FX2 device.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include <Windows.h>
-#include <devioctl.h>
-#include <cfgmgr32.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <strsafe.h>
-#include <driverspecs.h>
-#include <basetyps.h>
-
-#include <initguid.h>
-
-// {573E8C73-0CB4-4471-A1BF-FAB26C31D384}
-DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2,
- 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);
-
-//
-// Most device interface paths will fit into a buffer of this size.
-// However, some could be longer, and a larger buffer or dynamically
-// allocated buffer may be needed for robust code.
-//
-#define MAX_DEVPATH_LENGTH 1024
-
-#pragma warning(push)
-#pragma warning(disable:4201) // nameless struct/union
-#pragma warning(disable:4214) // bit field types other than int
-
-typedef struct _DEVICE_CONTEXT {
- HANDLE DeviceInterfaceHandle;
- CRITICAL_SECTION Lock;
- BOOL LockEnabled;
- PTP_WORK Work;
- BOOL Unregister;
- HCMNOTIFICATION InterfaceNotificationHandle;
- BOOL InterfaceNotificationsEnabled;
- HCMNOTIFICATION DeviceNotificationHandle;
- BOOL DeviceNotificationsEnabled;
-} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
-
-//
-// Define the structures that will be used by the IOCTL
-// interface to the driver
-//
-
-//
-// BAR_GRAPH_STATE
-//
-// BAR_GRAPH_STATE is a bit field structure with each
-// bit corresponding to one of the bar graph on the
-// OSRFX2 Development Board
-//
-#include <pshpack1.h>
-typedef struct _BAR_GRAPH_STATE {
-
- union {
-
- struct {
- //
- // Individual bars starting from the
- // top of the stack of bars
- //
- // NOTE: There are actually 10 bars,
- // but the very top two do not light
- // and are not counted here
- //
- UCHAR Bar1 : 1;
- UCHAR Bar2 : 1;
- UCHAR Bar3 : 1;
- UCHAR Bar4 : 1;
- UCHAR Bar5 : 1;
- UCHAR Bar6 : 1;
- UCHAR Bar7 : 1;
- UCHAR Bar8 : 1;
- };
-
- //
- // The state of all the bar graph as a single
- // UCHAR
- //
- UCHAR BarsAsUChar;
-
- };
-
-}BAR_GRAPH_STATE, *PBAR_GRAPH_STATE;
-
-//
-// SWITCH_STATE
-//
-// SWITCH_STATE is a bit field structure with each
-// bit corresponding to one of the switches on the
-// OSRFX2 Development Board
-//
-typedef struct _SWITCH_STATE {
-
- union {
- struct {
- //
- // Individual switches starting from the
- // left of the set of switches
- //
- UCHAR Switch1 : 1;
- UCHAR Switch2 : 1;
- UCHAR Switch3 : 1;
- UCHAR Switch4 : 1;
- UCHAR Switch5 : 1;
- UCHAR Switch6 : 1;
- UCHAR Switch7 : 1;
- UCHAR Switch8 : 1;
- };
-
- //
- // The state of all the switches as a single
- // UCHAR
- //
- UCHAR SwitchesAsUChar;
-
- };
-
-
-}SWITCH_STATE, *PSWITCH_STATE;
-
-#include <poppack.h>
-
-#pragma warning(pop)
-
-#define IOCTL_INDEX 0x800
-#define FILE_DEVICE_OSRUSBFX2 65500U
-
-#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 1, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 3, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 4, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 5, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 6, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 7, \
- METHOD_BUFFERED, \
- FILE_READ_ACCESS)
-
-
-#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
- IOCTL_INDEX + 8, \
- METHOD_BUFFERED, \
- FILE_WRITE_ACCESS)
-
-#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
- IOCTL_INDEX + 9, \
- METHOD_OUT_DIRECT, \
- FILE_READ_ACCESS)
-
-/*++
-
-Routine Description:
-
-Lights the next bar on the OSRFX2 device.
-
-Arguments:
-
-Context - The device context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD
-ControlDevice(PDEVICE_CONTEXT Context);
-
-
-/*++
-
-Routine Description:
-
- Sets the variables in this service to their default values.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID SetVariables(VOID);
-
-
-/*++
-
-Routine Description:
-
- Opens up the OSR USB FX2 device handle.
-
-Arguments:
-
- Synchronous - Whether or not this device should be
- opened for synchronous access
-
-Return Value:
-
- The handle to the OSR USB FX2 device.
-
---*/
-HANDLE OpenDevice(_In_ BOOL Synchronous);
-
-
-/*++
-
-Routine Description:
-
-Register for device notifications.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD RegisterDeviceNotifications(PDEVICE_CONTEXT Context);
-
-
-/*++
-
-Routine Description:
-
-Unregister for device notifications.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD UnregisterDeviceNotifications(PDEVICE_CONTEXT Context);
-
-
-/*++
-
-Routine Description:
-
-Initialize the given PDEVICE_CONTEXT.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD InitializeContext(PDEVICE_CONTEXT* Context);
-
-
-/*++
-
-Routine Description:
-
-Clean up the given PDEVICE_CONTEXT.
-
-Arguments:
-
-Context - The callback context
-
-Return Value:
-
-A Win32 error code.
-
---*/
-DWORD CloseContext(PDEVICE_CONTEXT Context); \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp
deleted file mode 100644
index fd3d497f..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*++
-
-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:
-
- SampleService.cpp
-
-Abstract:
-
- Provides a sample service class that derives from the service base class -
- CServiceBase. The sample service logs the service start and stop
- information to the Application event log, and shows how to run the main
- function of the service in a thread pool worker thread.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma region Includes
-#include "SampleService.h"
-#include "ThreadPool.h"
-#pragma endregion
-
-/*++
-
-Routine Description:
-
- The constructor of CSampleService. It initializes a new instance
- of the CSampleService class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs. Inherits properties from the class CServiceBase.
-
-Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
-Return Value:
-
- VOID
-
---*/
-CSampleService::CSampleService(
- PWSTR ServiceName,
- BOOL CanStop,
- BOOL CanShutdown,
- BOOL CanPauseContinue
- )
-: CServiceBase(ServiceName, CanStop, CanShutdown, CanPauseContinue)
-{
- m_fStopping = FALSE;
-
- //
- // Create a manual-reset event that is not signaled at first to indicate
- // the stopped signal of the service.
- //
- m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- if (m_hStoppedEvent == NULL)
- {
- throw GetLastError();
- }
-}
-
-
-/*++
-
-Routine Description:
-
- The virtual destructor of CSampleService.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-CSampleService::~CSampleService()
-{
- if (m_hStoppedEvent)
- {
- CloseHandle(m_hStoppedEvent);
- m_hStoppedEvent = NULL;
- }
-}
-
-
-/*++
-
-Routine Description:
-
- This function is executed when a Start command is sent to the
- service by the SCM or when the operating system starts (for a service
- that starts automatically). It specifies actions to take when the
- service starts. In this code sample, OnStart logs a service-start
- message to the Application log, and queues the main service function for
- execution in a thread pool worker thread.
-
- NOTE: A service application is designed to be long running. Therefore,
- it usually polls or monitors something in the system. The monitoring is
- set up in the OnStart method. However, OnStart does not actually do the
- monitoring. The OnStart method must return to the operating system after
- the service's operation has begun. It must not loop forever or block. To
- set up a simple monitoring mechanism, one general solution is to create
- a timer in OnStart. The timer would then raise events in your code
- periodically, at which time your service could do its monitoring. The
- other solution is to spawn a new thread to perform the main service
- functions, which is demonstrated in this code sample.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CSampleService::OnStart(
- DWORD Argc,
- PWSTR *Argv
- )
-{
- __debugbreak();
-
- //
- // Log a service start message to the Application log.
- //
- WriteToEventLog(L"SampleService in OnStart",
- EVENTLOG_INFORMATION_TYPE);
-
- //
- // Set up any variables the service needs.
- //
- SetVariables();
-
- //
- // Set up the context, and register for notifications.
- //
- InitializeContext(&m_Context);
-
- //
- // Queue the main service function for execution in a worker thread.
- //
- CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);
-}
-
-
-/*++
-
-Routine Description:
-
- This method performs the main function of the service. It runs
- on a thread pool worker thread.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CSampleService::ServiceWorkerThread()
-{
- //
- // Periodically check if the service is stopping.
- //
- while (!m_fStopping)
- {
- //
- // Perform main service function here...
- //
-
- ControlDevice(m_Context);
-
- ::Sleep(2000); // Simulate some lengthy operations.
- }
-
- //
- // Signal the stopped event.
- //
- SetEvent(m_hStoppedEvent);
-}
-
-
-/*++
-
-Routine Description:
-
- This function is executed when a Stop command is sent to the service by SCM.
- It specifies actions to take when a service stops running. In this code
- sample, OnStop logs a service-stop message to the Application log, and
- waits for the finish of the main service function.
-
- Be sure to periodically call ReportServiceStatus() with
- SERVICE_STOP_PENDING if the procedure is going to take a long time.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CSampleService::OnStop()
-{
- //
- // Log a service stop message to the Application log.
- //
- WriteToEventLog(L"SampleService in OnStop",
- EVENTLOG_INFORMATION_TYPE);
-
- //
- // Indicate that the service is stopping and wait for the finish of the
- // main service function (ServiceWorkerThread).
- //
- m_fStopping = TRUE;
-
- if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
- {
- throw GetLastError();
- }
-
- //
- // Clean up the context after the worker thread has finished.
- //
- CloseContext(m_Context);
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h
deleted file mode 100644
index 73be42e9..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*++
-
-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:
-
- SampleService.h
-
-Abstract:
-
- Provides a sample service class that derives from the service base class -
- CServiceBase. The sample service logs the service start and stop
- information to the Application event log, and shows how to run the main
- function of the service in a thread pool worker thread.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include "ServiceBase.h"
-#include "Main.h"
-
-class CSampleService : public CServiceBase
-{
-public:
-
- /*++
-
- Routine Description:
-
- The constructor of CSampleService. It initializes a new instance
- of the CSampleService class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs. Inherits properties from the class CServiceBase.
-
- Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
- Return Value:
-
- VOID
-
- --*/
- CSampleService(PWSTR ServiceName,
- BOOL CanStop = TRUE,
- BOOL CanShutdown = TRUE,
- BOOL CanPauseContinue = FALSE);
-
- /*++
-
- Routine Description:
-
- The virtual destructor of CSampleService.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual ~CSampleService();
-
-protected:
-
- /*++
-
- Routine Description:
-
- This function is executed when a Start command is sent to the
- service by the SCM or when the operating system starts (for a service
- that starts automatically). It specifies actions to take when the
- service starts. In this code sample, OnStart logs a service-start
- message to the Application log, and queues the main service function for
- execution in a thread pool worker thread.
-
- NOTE: A service application is designed to be long running. Therefore,
- it usually polls or monitors something in the system. The monitoring is
- set up in the OnStart method. However, OnStart does not actually do the
- monitoring. The OnStart method must return to the operating system after
- the service's operation has begun. It must not loop forever or block. To
- set up a simple monitoring mechanism, one general solution is to create
- a timer in OnStart. The timer would then raise events in your code
- periodically, at which time your service could do its monitoring. The
- other solution is to spawn a new thread to perform the main service
- functions, which is demonstrated in this code sample.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStart(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- This function is executed when a Stop command is sent to the service by SCM.
- It specifies actions to take when a service stops running. In this code
- sample, OnStop logs a service-stop message to the Application log, and
- waits for the finish of the main service function.
-
- Be sure to periodically call ReportServiceStatus() with
- SERVICE_STOP_PENDING if the procedure is going to take a long time.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStop();
-
-
- /*++
-
- Routine Description:
-
- This method performs the main function of the service. It runs
- on a thread pool worker thread.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID ServiceWorkerThread();
-
-private:
-
- //
- // Determines if the service is currently stopping.
- //
- BOOL m_fStopping;
-
- //
- // The handle to wait for a stop event.
- //
- HANDLE m_hStoppedEvent;
-
- //
- // The device context to manage notifications with.
- //
- // NOTE:
- // Variables used for device notifications should normally be local. However,
- // we must use a global variable here since there is a potential race condition
- // when the service needs to restart during device installation that could
- // cause the service to prevent the device from being restarted. So, this
- // variable is global so that the service's OnStart and OnStart method can
- // handle its creation and destruction.
- //
- PDEVICE_CONTEXT m_Context;
-}; \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp
deleted file mode 100644
index 4c20af2e..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp
+++ /dev/null
@@ -1,794 +0,0 @@
-/*++
-
-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:
-
- ServiceBase.cpp
-
-Abstract:
-
- Provides a base class for a service that will exist as part of a service
- application. CServiceBase must be derived from when creating a new service
- class.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma region Includes
-#include "ServiceBase.h"
-#include "Main.h"
-#include "Utils.h"
-#include <assert.h>
-#include <strsafe.h>
-#pragma endregion
-
-
-#pragma region Static Members
-
-//
-// Initialize the singleton service instance.
-//
-CServiceBase *CServiceBase::s_service = NULL;
-
-
-/*++
-
-Routine Description:
-
- Register the executable for a service with the Service Control
- Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start
- command, which results in a call to the OnStart method in the service.
- This method blocks until the service has stopped.
-
-Arguments:
-
- Service - The reference to a CServiceBase object. It will become the
- singleton service instance of this service application.
-
-Return Value:
-
- If the function succeeds, the return value is TRUE. If the function
- fails, the return value is FALSE. To get extended error information,
- call GetLastError.
-
---*/
-BOOL
-CServiceBase::Run(
- CServiceBase &Service
- )
-{
- s_service = &Service;
-
- SERVICE_TABLE_ENTRY serviceTable[] =
- {
- { Service.m_name, ServiceMain },
- { NULL, NULL }
- };
-
- //
- // Connects the main thread of a service process to the service control
- // manager, which causes the thread to be the service control dispatcher
- // thread for the calling process. This call returns when the service has
- // stopped. The process should simply terminate when the call returns.
- //
- return StartServiceCtrlDispatcher(serviceTable);
-}
-
-
-/*++
-
-Routine Description:
-
- The entry point for the service. It registers the handler function
- for the service and starts the service.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WINAPI
-CServiceBase::ServiceMain(
- DWORD Argc,
- PWSTR *Argv
- )
-{
- assert(s_service != NULL);
-
- //
- // Register the handler function for the service.
- //
- s_service->m_statusHandle = RegisterServiceCtrlHandler(s_service->m_name,
- ServiceCtrlHandler);
-
- if (s_service->m_statusHandle == NULL)
- {
- throw GetLastError();
- }
-
- //
- // Start the service.
- //
- s_service->Start(Argc, Argv);
-}
-
-
-/*++
-
-Routine Description:
-
- Called by the SCM whenever a control code is sent to the service.
-
-Arguments:
-
- CtrlCode - The control code. This parameter can be one of
- the following values:
-
- SERVICE_CONTROL_CONTINUE
- SERVICE_CONTROL_INTERROGATE
- SERVICE_CONTROL_NETBINDADD
- SERVICE_CONTROL_NETBINDDISABLE
- SERVICE_CONTROL_NETBINDREMOVE
- SERVICE_CONTROL_PARAMCHANGE
- SERVICE_CONTROL_PAUSE
- SERVICE_CONTROL_SHUTDOWN
- SERVICE_CONTROL_STOP
-
- This parameter can also be a user-defined control
- code ranging from 128 to 255.
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WINAPI
-CServiceBase::ServiceCtrlHandler(
- DWORD Ctrl
- )
-{
- switch (Ctrl)
- {
- case SERVICE_CONTROL_STOP:
- s_service->Stop();
- break;
- case SERVICE_CONTROL_PAUSE:
- s_service->Pause();
- break;
- case SERVICE_CONTROL_CONTINUE:
- s_service->Continue();
- break;
- case SERVICE_CONTROL_SHUTDOWN:
- s_service->Shutdown();
- break;
- case SERVICE_CONTROL_INTERROGATE:
- break;
- default:
- break;
- }
-}
-
-#pragma endregion
-
-
-#pragma region Service Constructor and Destructor
-
-/*++
-
-Routine Description:
-
- The constructor of CServiceBase. It initializes a new instance
- of the CServiceBase class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs.
-
-Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
-Return Value:
-
- VOID
-
---*/
-CServiceBase::CServiceBase(
- PWSTR ServiceName,
- BOOL CanStop,
- BOOL CanShutdown,
- BOOL CanPauseContinue
- )
-{
- //
- // Service name must be a valid string and cannot be NULL.
- //
- m_name = (ServiceName == NULL) ? L"" : ServiceName;
-
- m_statusHandle = NULL;
-
- //
- // The service runs in its own process.
- //
- m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
-
- //
- // The service is starting.
- //
- m_status.dwCurrentState = SERVICE_START_PENDING;
-
- //
- // The accepted commands of the service.
- //
- DWORD dwControlsAccepted = 0;
-
- if (CanStop)
- {
- dwControlsAccepted |= SERVICE_ACCEPT_STOP;
- }
-
- if (CanShutdown)
- {
- dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
- }
-
- if (CanPauseContinue)
- {
- dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
- }
-
- m_status.dwControlsAccepted = dwControlsAccepted;
-
- m_status.dwWin32ExitCode = NO_ERROR;
- m_status.dwServiceSpecificExitCode = 0;
- m_status.dwCheckPoint = 0;
- m_status.dwWaitHint = 0;
-
- SetupEvents();
-}
-
-
-/*++
-
-Routine Description:
-
- The virtual destructor of CServiceBase.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-CServiceBase::~CServiceBase()
-{
- DestroyEvents();
-}
-
-#pragma endregion
-
-
-#pragma region Service Start, Stop, Pause, Continue, and Shutdown
-
-/*++
-
-Routine Description:
-
- This function starts the service. It calls the OnStart virtual function
- in which you can specify the actions to take when the service starts. If
- an error occurs during the startup, the error will be logged in the
- Application event log, and the service will be stopped.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Start(
- DWORD Argc,
- PWSTR *Argv
-)
-{
- try
- {
- //
- // Tell SCM that the service is starting.
- //
- SetServiceStatus(SERVICE_START_PENDING);
-
- //
- // Perform service-specific initialization.
- //
- OnStart(Argc, Argv);
-
- //
- // Tell SCM that the service is started.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Start", Error);
-
- //
- // Set the service status to be stopped.
- //
- SetServiceStatus(SERVICE_STOPPED, Error);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to start.", EVENTLOG_ERROR_TYPE);
-
- //
- // Set the service status to be stopped.
- //
- SetServiceStatus(SERVICE_STOPPED);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when a Start
- command is sent to the service by the SCM or when the operating system
- starts (for a service that starts automatically). Specifies actions to
- take when the service starts. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the
- procedure is going to take long time. You may also consider spawning a
- new thread in OnStart to perform time-consuming initialization tasks.
-
-Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnStart(
- DWORD Argc,
- PWSTR *Argv
-)
-{
- SetVariables();
-}
-
-
-/*++
-
-Routine Description:
-
- This function stops the service. It calls the OnStop virtual
- function in which you can specify the actions to take when the service
- stops. If an error occurs, the error will be logged in the Application
- event log, and the service will be restored to the original state.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Stop()
-{
- DWORD OriginalState = m_status.dwCurrentState;
-
- try
- {
- //
- // Tell SCM that the service is stopping.
- //
- SetServiceStatus(SERVICE_STOP_PENDING);
-
- //
- // Perform service-specific stop operations.
- //
- OnStop();
-
- //
- // Tell SCM that the service is stopped.
- //
- SetServiceStatus(SERVICE_STOPPED);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Stop", Error);
-
- //
- // Set the orginal service status.
- //
- SetServiceStatus(OriginalState);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to stop.", EVENTLOG_ERROR_TYPE);
-
- //
- // Set the orginal service status.
- //
- SetServiceStatus(OriginalState);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when a Stop
- command is sent to the service by the SCM. Specifies actions to take
- when a service stops running. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the
- procedure is going to take long time.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnStop()
-{
-}
-
-
-/*++
-
-Routine Description:
-
- The function pauses the service if the service supports pause
- and continue. It calls the OnPause virtual function in which you can
- specify the actions to take when the service pauses. If an error occurs,
- the error will be logged in the Application event log, and the service
- will become running.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Pause()
-{
- try
- {
- //
- // Tell SCM that the service is pausing.
- //
- SetServiceStatus(SERVICE_PAUSE_PENDING);
-
- //
- // Perform service-specific pause operations.
- //
- OnPause();
-
- //
- // Tell SCM that the service is paused.
- //
- SetServiceStatus(SERVICE_PAUSED);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Pause", Error);
-
- //
- // Tell SCM that the service is still running.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to pause.", EVENTLOG_ERROR_TYPE);
-
- //
- // Tell SCM that the service is still running.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when a Pause
- command is sent to the service by the SCM. Specifies actions to take
- when a service pauses.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnPause()
-{
-}
-
-
-/*++
-
-Routine Description:
-
- The function resumes normal functioning after being paused if
- the service supports pause and continue. It calls the OnContinue virtual
- function in which you can specify the actions to take when the service
- continues. If an error occurs, the error will be logged in the
- Application event log, and the service will still be paused.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Continue()
-{
- try
- {
- //
- // Tell SCM that the service is resuming.
- //
- SetServiceStatus(SERVICE_CONTINUE_PENDING);
-
- //
- // Perform service-specific continue operations.
- //
- OnContinue();
-
- //
- // Tell SCM that the service is running.
- //
- SetServiceStatus(SERVICE_RUNNING);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Continue", Error);
-
- //
- // Tell SCM that the service is still paused.
- //
- SetServiceStatus(SERVICE_PAUSED);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to resume.", EVENTLOG_ERROR_TYPE);
-
- //
- // Tell SCM that the service is still paused.
- //
- SetServiceStatus(SERVICE_PAUSED);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, OnContinue runs when a
- Continue command is sent to the service by the SCM. Specifies actions to
- take when a service resumes normal functioning after being paused.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnContinue()
-{
-}
-
-
-/*++
-
-Routine Description:
-
- The function executes when the system is shutting down. It
- calls the OnShutdown virtual function in which you can specify what
- should occur immediately prior to the system shutting down. If an error
- occurs, the error will be logged in the Application event log.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::Shutdown()
-{
- try
- {
- //
- // Perform service-specific shutdown operations.
- //
- OnShutdown();
-
- //
- // Tell SCM that the service is stopped.
- //
- SetServiceStatus(SERVICE_STOPPED);
- }
- catch (DWORD Error)
- {
- //
- // Log the error.
- //
- WriteToErrorLog(L"Service Shutdown", Error);
- }
- catch (...)
- {
- //
- // Log the error.
- //
- WriteToEventLog(L"Service failed to shut down.", EVENTLOG_ERROR_TYPE);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- When implemented in a derived class, executes when the system
- is shutting down. Specifies what should occur immediately prior to the
- system shutting down.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::OnShutdown()
-{
-}
-
-#pragma endregion
-
-
-#pragma region Helper Functions
-
-/*++
-
-Routine Description:
-
- The function sets the service status and reports the status to the SCM.
-
-Arguments:
-
- CurrentState - The current state of the service
-
- Win32ExitCode - The error code to report
-
- WaitHint - The estimated time for pending operation, in milliseconds
-
-Return Value:
-
- VOID
-
---*/
-VOID
-CServiceBase::SetServiceStatus(
- DWORD CurrentState,
- DWORD Win32ExitCode,
- DWORD WaitHint
- )
-{
- static DWORD CheckPoint = 1;
-
- //
- // Fill in the SERVICE_STATUS structure of the service.
- //
-
- m_status.dwCurrentState = CurrentState;
- m_status.dwWin32ExitCode = Win32ExitCode;
- m_status.dwWaitHint = WaitHint;
-
- m_status.dwCheckPoint = ((CurrentState == SERVICE_RUNNING) ||
- (CurrentState == SERVICE_STOPPED)) ? 0 :
- CheckPoint++;
-
- //
- // Report the status of the service to the SCM.
- //
- ::SetServiceStatus(m_statusHandle, &m_status);
-}
-
-#pragma endregion \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h
deleted file mode 100644
index 106597e1..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*++
-
-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:
-
- ServiceBase.cpp
-
-Abstract:
-
- Provides a base class for a service that will exist as part of a service
- application. CServiceBase must be derived from when creating a new service
- class.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include <windows.h>
-#include "Utils.h"
-
-class CServiceBase
-{
-public:
-
- /*++
-
- Routine Description:
-
- Register the executable for a service with the Service Control
- Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start
- command, which results in a call to the OnStart method in the service.
- This method blocks until the service has stopped.
-
- Arguments:
-
- Service - The reference to a CServiceBase object. It will become the
- singleton service instance of this service application.
-
- Return Value:
-
- If the function succeeds, the return value is TRUE. If the function
- fails, the return value is FALSE. To get extended error information,
- call GetLastError.
-
- --*/
- static BOOL Run(CServiceBase &service);
-
-
- /*++
-
- Routine Description:
-
- The constructor of CServiceBase. It initializes a new instance
- of the CServiceBase class. The optional parameters (CanStop,
- CanShutdown and CanPauseContinue) allow you to specify whether the
- service can be stopped, paused and continued, or be notified when system
- shutdown occurs.
-
- Arguments:
-
- ServiceName - The name of the service
-
- CanStop - The service can be stopped
-
- CanShutdown - The service is notified when system shutdown occurs
-
- CanPauseContinue - The service can be paused and continued
-
- Return Value:
-
- VOID
-
- --*/
- CServiceBase(PWSTR ServiceName,
- BOOL CanStop = TRUE,
- BOOL CanShutdown = TRUE,
- BOOL CanPauseContinue = FALSE);
-
-
- /*++
-
- Routine Description:
-
- The virtual destructor of CServiceBase.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual ~CServiceBase();
-
-
- /*++
-
- Routine Description:
-
- This function stops the service. It calls the OnStop virtual
- function in which you can specify the actions to take when the service
- stops. If an error occurs, the error will be logged in the Application
- event log, and the service will be restored to the original state.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Stop();
-
-protected:
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when a Start
- command is sent to the service by the SCM or when the operating system
- starts (for a service that starts automatically). Specifies actions to
- take when the service starts. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the
- procedure is going to take long time. You may also consider spawning a
- new thread in OnStart to perform time-consuming initialization tasks.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStart(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when a Stop
- command is sent to the service by the SCM. Specifies actions to take
- when a service stops running. Be sure to periodically call
- CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the
- procedure is going to take long time.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnStop();
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when a Pause
- command is sent to the service by the SCM. Specifies actions to take
- when a service pauses.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnPause();
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, OnContinue runs when a
- Continue command is sent to the service by the SCM. Specifies actions to
- take when a service resumes normal functioning after being paused.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnContinue();
-
-
- /*++
-
- Routine Description:
-
- When implemented in a derived class, executes when the system
- is shutting down. Specifies what should occur immediately prior to the
- system shutting down.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- virtual VOID OnShutdown();
-
-
- /*++
-
- Routine Description:
-
- The function sets the service status and reports the status to the SCM.
-
- Arguments:
-
- CurrentState - The current state of the service
-
- Win32ExitCode - The error code to report
-
- WaitHint - The estimated time for pending operation, in milliseconds
-
- Return Value:
-
- VOID
-
- --*/
- VOID SetServiceStatus(DWORD CurrentState,
- DWORD Win32ExitCode = NO_ERROR,
- DWORD WaitHint = 0);
-
-private:
-
- /*++
-
- Routine Description:
-
- The entry point for the service. It registers the handler function
- for the service and starts the service.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- static VOID WINAPI ServiceMain(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- Called by the SCM whenever a control code is sent to the service.
-
- Arguments:
-
- CtrlCode - The control code. This parameter can be one of
- the following values:
-
- SERVICE_CONTROL_CONTINUE
- SERVICE_CONTROL_INTERROGATE
- SERVICE_CONTROL_NETBINDADD
- SERVICE_CONTROL_NETBINDDISABLE
- SERVICE_CONTROL_NETBINDREMOVE
- SERVICE_CONTROL_PARAMCHANGE
- SERVICE_CONTROL_PAUSE
- SERVICE_CONTROL_SHUTDOWN
- SERVICE_CONTROL_STOP
-
- This parameter can also be a user-defined control
- code ranging from 128 to 255.
-
- Return Value:
-
- VOID
-
- --*/
- static VOID WINAPI ServiceCtrlHandler(DWORD Ctrl);
-
-
- /*++
-
- Routine Description:
-
- This function starts the service. It calls the OnStart virtual function
- in which you can specify the actions to take when the service starts. If
- an error occurs during the startup, the error will be logged in the
- Application event log, and the service will be stopped.
-
- Arguments:
-
- Argc - The number of command line arguments
-
- Argv - The array of command line arguments
-
- Return Value:
-
- VOID
-
- --*/
- VOID Start(DWORD Argc, PWSTR *Argv);
-
-
- /*++
-
- Routine Description:
-
- The function pauses the service if the service supports pause
- and continue. It calls the OnPause virtual function in which you can
- specify the actions to take when the service pauses. If an error occurs,
- the error will be logged in the Application event log, and the service
- will become running.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Pause();
-
-
- /*++
-
- Routine Description:
-
- The function resumes normal functioning after being paused if
- the service supports pause and continue. It calls the OnContinue virtual
- function in which you can specify the actions to take when the service
- continues. If an error occurs, the error will be logged in the
- Application event log, and the service will still be paused.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Continue();
-
-
- /*++
-
- Routine Description:
-
- The function executes when the system is shutting down. It
- calls the OnShutdown virtual function in which you can specify what
- should occur immediately prior to the system shutting down. If an error
- occurs, the error will be logged in the Application event log.
-
- Arguments:
-
- VOID
-
- Return Value:
-
- VOID
-
- --*/
- VOID Shutdown();
-
-
- //
- // The singleton service instance.
- //
- static CServiceBase *s_service;
-
- //
- // The name of the service.
- //
- PWSTR m_name;
-
- //
- // The status of the service.
- //
- SERVICE_STATUS m_status;
-
- //
- // The service status handle.
- //
- SERVICE_STATUS_HANDLE m_statusHandle;
-}; \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp
new file mode 100644
index 00000000..f6616850
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp
@@ -0,0 +1,375 @@
+/*++
+
+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:
+
+ ServiceWin32API.cpp
+
+Abstract:
+
+ Implements functions to start/run/stop the service.
+
+Environment:
+
+ User mode
+
+--*/
+
+#include "stdafx.h"
+
+//
+// Settings of the service
+//
+#define SERVICE_NAME L"OsrUsbFx2UmUserSvc"
+#define SERVICE_FLAGS_RUNNING 0x1
+
+//
+// Service context
+//
+SERVICE_STATUS_HANDLE SvcStatusHandle = NULL;
+volatile LONG SvcControlFlags = 0;
+HANDLE SvcStoppedEvent = NULL;
+HANDLE SvcStopRequestEvent = NULL;
+HANDLE SvcStopWaitObject = NULL;
+
+//
+// Device interface context
+//
+HCMNOTIFICATION InterfaceNotificationHandle = NULL;
+SRWLOCK DeviceListLock = SRWLOCK_INIT;
+DEVICE_LIST_ENTRY DeviceList;
+
+//
+// Debugging support during development time
+//
+//#define DEBUG_SUPPORT
+
+/*++
+
+Routine Description:
+
+ Entry point for the service.
+
+Arguments:
+
+ Argc - The number of command line arguments
+
+ Argv - The array of command line arguments
+
+Return Value:
+
+ VOID
+
+--*/
+INT
+wmain(
+ INT Argc,
+ WCHAR *Argv[]
+ )
+{
+ UNREFERENCED_PARAMETER(Argc);
+ UNREFERENCED_PARAMETER(Argv);
+
+ SERVICE_TABLE_ENTRY serviceTable[] =
+ {
+ { SERVICE_NAME, ServiceMain },
+ { NULL, NULL }
+ };
+
+ return StartServiceCtrlDispatcher(serviceTable);
+}
+
+VOID WINAPI ServiceMain(
+ DWORD Argc,
+ PWSTR *Argv
+ )
+{
+ DWORD Err = ERROR_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Argc);
+ UNREFERENCED_PARAMETER(Argv);
+
+ //
+ // Initialize global variables
+ //
+ InitializeDeviceListHead(&DeviceList);
+
+#ifdef DEBUG_SUPPORT
+
+ while (!IsDebuggerPresent()) {
+ Sleep(1000);
+ }
+
+ __debugbreak();
+
+#endif
+
+ SvcStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME,
+ ServiceCtrlHandler);
+
+ if (SvcStatusHandle == NULL)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_START_PENDING,
+ ERROR_SUCCESS);
+
+ //
+ // Setup device interface context
+ //
+ Err = SetupDeviceInterfaceContext();
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_START_PENDING,
+ ERROR_SUCCESS);
+
+ //
+ // Initialize device control
+ //
+ OsrFx2InitializeDevice();
+
+ //
+ // Register callback function for stop event
+ //
+ SvcStopRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (SvcStopRequestEvent == NULL)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ if (!RegisterWaitForSingleObject(&SvcStopWaitObject,
+ SvcStopRequestEvent,
+ ServiceStopCallback,
+ NULL,
+ INFINITE,
+ WT_EXECUTEONLYONCE | WT_EXECUTEINPERSISTENTTHREAD))
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ //
+ // Create stopped event for the running worker thread
+ //
+ SvcStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (SvcStoppedEvent == NULL)
+ {
+ Err = GetLastError();
+ goto cleanup;
+ }
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_START_PENDING,
+ ERROR_SUCCESS);
+
+ //
+ // Queue the main service function for execution in a worker thread.
+ //
+ QueueUserWorkItem(&ServiceRunningWorkerThread,
+ NULL,
+ WT_EXECUTELONGFUNCTION);
+
+ UpdateServiceStatus(SvcStatusHandle,
+ SERVICE_RUNNING,
+ ERROR_SUCCESS);
+
+cleanup:
+
+ if (Err != ERROR_SUCCESS)
+ {
+ ServiceStop(Err);
+ }
+}
+
+VOID
+WINAPI
+ServiceCtrlHandler(
+ DWORD Ctrl
+ )
+{
+ switch (Ctrl)
+ {
+ case SERVICE_CONTROL_STOP:
+ //
+ // Set service stop event
+ //
+ UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ERROR_SUCCESS);
+ SetEvent(SvcStopRequestEvent);
+ break;
+
+ default:
+ break;
+ }
+}
+
+#define SERVICE_WAIT_HINT_TIME 30000 // 30 seconds
+
+BOOL
+UpdateServiceStatus(
+ __in_opt SERVICE_STATUS_HANDLE hSvcHandle,
+ __in DWORD dwCurrentState,
+ __in DWORD dwWin32ExitCode
+ )
+{
+ SERVICE_STATUS SvcStatus;
+
+ static DWORD dwCheckPoint = 1;
+
+ SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ SvcStatus.dwCurrentState = dwCurrentState;
+ SvcStatus.dwWin32ExitCode = dwWin32ExitCode;
+ SvcStatus.dwServiceSpecificExitCode = ERROR_SUCCESS;
+
+ if (dwCurrentState == SERVICE_START_PENDING)
+ {
+ SvcStatus.dwControlsAccepted = 0;
+ }
+ else
+ {
+ SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+ }
+
+ if ((dwCurrentState == SERVICE_RUNNING) ||
+ (dwCurrentState == SERVICE_STOPPED))
+ {
+ SvcStatus.dwCheckPoint = 0;
+ SvcStatus.dwWaitHint = 0;
+ }
+ else
+ {
+ SvcStatus.dwCheckPoint = dwCheckPoint++;
+ SvcStatus.dwWaitHint = SERVICE_WAIT_HINT_TIME;
+ }
+
+ return SetServiceStatus(hSvcHandle, &SvcStatus);
+}
+
+DWORD
+WINAPI
+ServiceRunningWorkerThread(
+ _In_ PVOID lpThreadParameter
+ )
+{
+ PDEVICE_CONTEXT DeviceContext = NULL;
+ PDEVICE_LIST_ENTRY Link = NULL;
+
+ UNREFERENCED_PARAMETER(lpThreadParameter);
+
+ InterlockedOr(&SvcControlFlags, SERVICE_FLAGS_RUNNING);
+
+ //
+ // Periodically check if the service is stopping.
+ //
+ while ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0)
+ {
+ AcquireSRWLockShared(&DeviceListLock);
+
+ for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink)
+ {
+ DeviceContext = CONTAINING_DEVICE_RECORD(Link);
+
+ OsrFx2ControlDevice(DeviceContext);
+ }
+
+ ReleaseSRWLockShared(&DeviceListLock);
+
+ Sleep(2000); // Simulate some lengthy operations.
+ }
+
+ //
+ // Signal the stopped event.
+ //
+ SetEvent(SvcStoppedEvent);
+
+ return 0;
+}
+
+VOID
+CALLBACK
+ServiceStopCallback(
+ _In_ PVOID lpParameter,
+ _In_ BOOLEAN TimerOrWaitFired
+ )
+{
+ UNREFERENCED_PARAMETER(TimerOrWaitFired);
+
+ //
+ // Since wait object can not be unregistered in callback function, queue
+ // another thread
+ //
+ QueueUserWorkItem(ServiceStopWorkerThread,
+ lpParameter,
+ WT_EXECUTEDEFAULT);
+}
+
+DWORD
+WINAPI
+ServiceStopWorkerThread(
+ _In_ PVOID lpThreadParameter
+ )
+{
+ UNREFERENCED_PARAMETER(lpThreadParameter);
+
+ ServiceStop(ERROR_SUCCESS);
+
+ return 0;
+}
+
+VOID
+ServiceStop(
+ _In_ DWORD ExitCode
+ )
+{
+ if (SvcStatusHandle == NULL)
+ {
+ return;
+ }
+
+ UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ExitCode);
+
+ //
+ // Notify the working thread to stop
+ //
+ if ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0)
+ {
+ InterlockedAnd(&SvcControlFlags, ~SERVICE_FLAGS_RUNNING);
+ WaitForSingleObject(SvcStoppedEvent, INFINITE);
+ }
+
+ //
+ // Clean up device context after the worker thread has finished.
+ //
+ CleanupDeviceInterfaceContext();
+
+ //
+ // cleanup work
+ //
+ if (SvcStopWaitObject != NULL)
+ {
+ UnregisterWait(SvcStopWaitObject);
+ }
+
+ if (SvcStopRequestEvent != NULL)
+ {
+ CloseHandle(SvcStopRequestEvent);
+ }
+
+ if (SvcStoppedEvent != NULL)
+ {
+ CloseHandle(SvcStoppedEvent);
+ }
+
+ UpdateServiceStatus(SvcStatusHandle, SERVICE_STOPPED, ExitCode);
+}
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h
new file mode 100644
index 00000000..e469ca9d
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h
@@ -0,0 +1,56 @@
+/*++
+
+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.
+
+--*/
+
+#pragma once
+
+VOID
+WINAPI
+ServiceMain(
+ DWORD Argc,
+ PWSTR *Argv
+ );
+
+VOID
+WINAPI
+ServiceCtrlHandler(
+ DWORD Ctrl
+ );
+
+BOOL
+UpdateServiceStatus(
+ __in_opt SERVICE_STATUS_HANDLE hSvcHandle,
+ __in DWORD dwCurrentState,
+ __in DWORD dwWin32ExitCode
+ );
+
+VOID
+CALLBACK
+ServiceStopCallback(
+ _In_ PVOID lpParameter,
+ _In_ BOOLEAN TimerOrWaitFired
+ );
+
+VOID
+ServiceStop(
+ _In_ DWORD ExitCode
+ );
+
+DWORD
+WINAPI
+ServiceRunningWorkerThread(
+ _In_ PVOID lpThreadParameter
+ );
+
+DWORD
+WINAPI
+ServiceStopWorkerThread(
+ _In_ PVOID lpThreadParameter
+ );
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h
deleted file mode 100644
index 3d851537..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************** Module Header ******************************\
-* Module Name: ThreadPool.h
-* Project: CppWindowsService
-* Copyright (c) Microsoft Corporation.
-*
-* The class was designed by Kenny Kerr. It provides the ability to queue
-* simple member functions of a class to the Windows thread pool.
-*
-* Using the thread pool is simple and feels natural in C++.
-*
-* class CSampleService
-* {
-* public:
-*
-* void AsyncRun()
-* {
-* CThreadPool::QueueUserWorkItem(&Service::Run, this);
-* }
-*
-* void Run()
-* {
-* // Some lengthy operation
-* }
-* };
-*
-* Kenny Kerr spends most of his time designing and building distributed
-* applications for the Microsoft Windows platform. He also has a particular
-* passion for C++ and security programming. Reach Kenny at
-* http://weblogs.asp.net/kennykerr/ or visit his Web site:
-* http://www.kennyandkarin.com/Kenny/.
-*
-* This source is subject to the Microsoft Public License.
-* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
-* All other 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.
-\***************************************************************************/
-
-#pragma once
-
-#include <memory>
-
-
-class CThreadPool
-{
-public:
-
- template <typename T>
- static void QueueUserWorkItem(void (T::*function)(void),
- T *object, ULONG flags = WT_EXECUTELONGFUNCTION)
- {
- typedef std::pair<void (T::*)(), T *> CallbackType;
- std::auto_ptr<CallbackType> p(new CallbackType(function, object));
-
- if (::QueueUserWorkItem(ThreadProc<T>, p.get(), flags))
- {
- // The ThreadProc now has the responsibility of deleting the pair.
- p.release();
- }
- else
- {
- throw GetLastError();
- }
- }
-
-private:
-
- template <typename T>
- static DWORD WINAPI ThreadProc(PVOID context)
- {
- typedef std::pair<void (T::*)(), T *> CallbackType;
-
- std::auto_ptr<CallbackType> p(static_cast<CallbackType *>(context));
-
- (p->second->*p->first)();
- return 0;
- }
-}; \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp
deleted file mode 100644
index e8fc87ee..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*++
-
-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:
-
- Utils.cpp
-
-Abstract:
-
- Provides utility function to SampleApp.cpp.
-
-Environment:
-
- User mode
-
---*/
-
-#include "Utils.h"
-
-//
-// Service trace event provider
-// {54a25c42-cd91-4210-98cc-c3447b56e447}
-//
-EXTERN_C __declspec(selectany) const GUID SERVICE_PROVIDER_GUID = { 0x54a25c42, 0xcd91, 0x4210,{ 0x98, 0xcc, 0xc3, 0x44, 0x7b, 0x56, 0xe4, 0x47 } };
-
-REGHANDLE m_etwRegHandle;
-
-
-/*++
-
-Routine Description:
-
- Sets up logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-SetupEvents()
-{
- NTSTATUS status = EventRegister(&SERVICE_PROVIDER_GUID,
- nullptr,
- nullptr,
- &m_etwRegHandle);
-
- if (status != ERROR_SUCCESS)
- {
- wprintf(L"Provider not registered. EventRegister failed with error: 0x%08X\n", status);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- Destroys logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID
-DestroyEvents()
-{
- if (m_etwRegHandle != NULL)
- {
- EventUnregister(m_etwRegHandle);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- Log a message.
-
-Arguments:
-
- Message - The string message to be logged
-
- Level - The type of event to be logged. This parameter can
- be one of the following values:
-
- TRACE_LEVEL_CRITICAL
- TRACE_LEVEL_ERROR
- TRACE_LEVEL_WARNING
- TRACE_LEVEL_INFORMATION
- TRACE_LEVEL_VERBOSE
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WriteToEventLog(
- PWSTR Message,
- BYTE Level
- )
-{
- if (m_etwRegHandle != NULL)
- {
- EventWriteString(m_etwRegHandle, Level, 0, Message);
- }
-}
-
-
-/*++
-
-Routine Description:
-
- Log an error message.
-
-Arguments:
-
- Function - The function that gives the error
-
- Error - The error code
-
-Return Value:
-
- VOID
-
---*/
-VOID
-WriteToErrorLog(
- PWSTR Function,
- DWORD Error
- )
-{
- WCHAR Message[260];
-
- StringCchPrintf(Message, ARRAYSIZE(Message),
- L"%ws failed with error: 0x%08x", Function, Error);
-
- WriteToEventLog(Message, TRACE_LEVEL_ERROR);
-} \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h
deleted file mode 100644
index b619f461..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*++
-
-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:
-
- Utils.cpp
-
-Abstract:
-
- Provides utility function to SampleApp.cpp.
-
-Environment:
-
- User mode
-
---*/
-
-#pragma once
-
-#include <Windows.h>
-#include <strsafe.h>
-#include <evntprov.h>
-#include <evntrace.h>
-
-/*++
-
-Routine Description:
-
- Sets up logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID SetupEvents();
-
-
-/*++
-
-Routine Description:
-
- Destroys logging.
-
-Arguments:
-
- VOID
-
-Return Value:
-
- VOID
-
---*/
-VOID DestroyEvents();
-
-
-/*++
-
-Routine Description:
-
- Log a message.
-
-Arguments:
-
- Message - The string message to be logged
-
- Level - The type of event to be logged. This parameter can
- be one of the following values:
-
- TRACE_LEVEL_CRITICAL
- TRACE_LEVEL_ERROR
- TRACE_LEVEL_WARNING
- TRACE_LEVEL_INFORMATION
- TRACE_LEVEL_VERBOSE
-
-Return Value:
-
- VOID
-
---*/
-VOID WriteToEventLog(PWSTR Message, BYTE Level);
-
-
-/*++
-
-Routine Description:
-
- Log an error message.
-
-Arguments:
-
- Function - The function that gives the error
-
- Error - The error code
-
-Return Value:
-
- VOID
-
---*/
-VOID WriteToErrorLog(PWSTR Function, DWORD Error); \ No newline at end of file
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx
deleted file mode 100644
index 61e1e958..00000000
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx
+++ /dev/null
Binary files differ
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj
index 6965d745..60174c56 100644
--- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj
@@ -23,7 +23,7 @@
<RootNamespace>osrfx2_DCHU_usersvc</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>osrfx2_DCHU_usersvc</ProjectName>
- <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
@@ -93,14 +93,13 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
- <Optimization>Full</Optimization>
+ <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
+ <WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
@@ -108,11 +107,11 @@
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>onecoreuap.lib;%(AdditionalDependencies);</AdditionalDependencies>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
- <Optimization>Full</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -121,6 +120,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <Optimization>Full</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -138,8 +138,7 @@
<ClCompile>
<Optimization>Full</Optimization>
<PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
@@ -182,18 +181,15 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="CppWindowsService.cpp" />
- <ClCompile Include="SampleService.cpp" />
- <ClCompile Include="ServiceBase.cpp" />
- <ClCompile Include="Main.cpp" />
- <ClCompile Include="Utils.cpp" />
+ <ClCompile Include="DeviceControl.cpp" />
+ <ClCompile Include="DeviceContext.cpp" />
+ <ClCompile Include="ServiceWin32API.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="SampleService.h" />
- <ClInclude Include="ServiceBase.h" />
- <ClInclude Include="Main.h" />
- <ClInclude Include="ThreadPool.h" />
- <ClInclude Include="Utils.h" />
+ <ClInclude Include="DeviceControl.h" />
+ <ClInclude Include="DeviceContext.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="ServiceWin32API.h" />
</ItemGroup>
<ItemGroup>
<None Include="Documentation\ReadMe.htm">
diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h
new file mode 100644
index 00000000..7bd67951
--- /dev/null
+++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h
@@ -0,0 +1,26 @@
+/*++
+
+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.
+
+--*/
+
+#pragma once
+
+#include <Windows.h>
+#include <strsafe.h>
+
+//
+// Device context
+//
+#include <cfgmgr32.h>
+
+#include <initguid.h>
+
+#include "ServiceWin32API.h"
+#include "DeviceContext.h"
+#include "DeviceControl.h"
diff --git a/gpio/samples/simdevice/umdf/simdeviceumdf.inx b/gpio/samples/simdevice/umdf/simdeviceumdf.inx
index e19f9f2c..5493ece4 100644
--- a/gpio/samples/simdevice/umdf/simdeviceumdf.inx
+++ b/gpio/samples/simdevice/umdf/simdeviceumdf.inx
Binary files differ
diff --git a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c
index 0aed2564..03087d9f 100644
--- a/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c
+++ b/tools/sdv/samples/SDV-FailDriver-WDM/driver/fail_driver1.c
@@ -68,6 +68,9 @@ DriverAddDevice(
UNREFERENCED_PARAMETER(PhysicalDeviceObject);
PAGED_CODE();
+
+ // Injected CA defect for C28171
+ PAGED_CODE();
status = IoCreateDevice(DriverObject,
sizeof(DRIVER_DEVICE_EXTENSION),
diff --git a/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj
new file mode 100644
index 00000000..0e8fbdba
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" 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">
+ <VCProjectVersion>16.0</VCProjectVersion>
+ <ProjectGuid>{ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}</ProjectGuid>
+ <RootNamespace>IddSampleApp</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v142</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </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')" Label="LocalAppDataPlatform" />
+ </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')" Label="LocalAppDataPlatform" />
+ </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')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;swdevice.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters
new file mode 100644
index 00000000..a91ad0ed
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleApp/IddSampleApp.vcxproj.filters
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleApp/main.cpp b/video/IndirectDisplay/IddSampleApp/main.cpp
new file mode 100644
index 00000000..e1d55ee8
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleApp/main.cpp
@@ -0,0 +1,93 @@
+#include <iostream>
+#include <vector>
+
+#include <windows.h>
+#include <swdevice.h>
+#include <conio.h>
+#include <wrl.h>
+
+VOID WINAPI
+CreationCallback(
+ _In_ HSWDEVICE hSwDevice,
+ _In_ HRESULT hrCreateResult,
+ _In_opt_ PVOID pContext,
+ _In_opt_ PCWSTR pszDeviceInstanceId
+ )
+{
+ HANDLE hEvent = *(HANDLE*) pContext;
+
+ SetEvent(hEvent);
+ UNREFERENCED_PARAMETER(hSwDevice);
+ UNREFERENCED_PARAMETER(hrCreateResult);
+ UNREFERENCED_PARAMETER(pszDeviceInstanceId);
+}
+
+int __cdecl main(int argc, wchar_t *argv[])
+{
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+
+ HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ HSWDEVICE hSwDevice;
+ SW_DEVICE_CREATE_INFO createInfo = { 0 };
+ PCWSTR description = L"Idd Sample Driver";
+
+ // These match the Pnp id's in the inf file so OS will load the driver when the device is created
+ PCWSTR instanceId = L"IddSampleDriver";
+ PCWSTR hardwareIds = L"IddSampleDriver\0\0";
+ PCWSTR compatibleIds = L"IddSampleDriver\0\0";
+
+ createInfo.cbSize = sizeof(createInfo);
+ createInfo.pszzCompatibleIds = compatibleIds;
+ createInfo.pszInstanceId = instanceId;
+ createInfo.pszzHardwareIds = hardwareIds;
+ createInfo.pszDeviceDescription = description;
+
+ createInfo.CapabilityFlags = SWDeviceCapabilitiesRemovable |
+ SWDeviceCapabilitiesSilentInstall |
+ SWDeviceCapabilitiesDriverRequired;
+
+ // Create the device
+ HRESULT hr = SwDeviceCreate(L"IddSampleDriver",
+ L"HTREE\\ROOT\\0",
+ &createInfo,
+ 0,
+ nullptr,
+ CreationCallback,
+ &hEvent,
+ &hSwDevice);
+ if (FAILED(hr))
+ {
+ printf("SwDeviceCreate failed with 0x%lx\n", hr);
+ return 1;
+ }
+
+ // Wait for callback to signal that the device has been created
+ printf("Waiting for device to be created....\n");
+ DWORD waitResult = WaitForSingleObject(hEvent, 10*1000);
+ if (waitResult != WAIT_OBJECT_0)
+ {
+ printf("Wait for device creation failed\n");
+ return 1;
+ }
+ printf("Device created\n\n");
+
+ // Now wait for user to indicate the device should be stopped
+ printf("Press 'x' to exit and destory the software device\n");
+ bool bExit = false;
+ do
+ {
+ // Wait for key press
+ int key = _getch();
+
+ if (key == 'x' || key == 'X')
+ {
+ bExit = true;
+ }
+ }while (!bExit);
+
+ // Stop the device, this will cause the sample to be unloaded
+ SwDeviceClose(hSwDevice);
+
+ return 0;
+} \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleDriver.sln b/video/IndirectDisplay/IddSampleDriver.sln
new file mode 100644
index 00000000..ec38923b
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver.sln
@@ -0,0 +1,53 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29728.190
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IddSampleDriver", "IddSampleDriver\IddSampleDriver.vcxproj", "{2D54CB75-8B17-4F11-97DC-847B0244CD46}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IddSampleApp", "IddSampleApp\IddSampleApp.vcxproj", "{ED59DFCA-E75B-4DD8-B5C2-6BFF77A225A6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.ActiveCfg = Debug|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Build.0 = Debug|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM.Deploy.0 = Debug|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.ActiveCfg = Debug|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Build.0 = Debug|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x64.Deploy.0 = Debug|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.ActiveCfg = Debug|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Build.0 = Debug|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Debug|x86.Deploy.0 = Debug|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.ActiveCfg = Release|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Build.0 = Release|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM.Deploy.0 = Release|ARM
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Build.0 = Release|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|ARM64.Deploy.0 = Release|ARM64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.ActiveCfg = Release|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.Build.0 = Release|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x64.Deploy.0 = Release|x64
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.ActiveCfg = Release|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Build.0 = Release|Win32
+ {2D54CB75-8B17-4F11-97DC-847B0244CD46}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1C92CFF5-AC99-48BC-949B-7E7DD3AA4AD7}
+ EndGlobalSection
+EndGlobal
diff --git a/video/IndirectDisplay/IddSampleDriver/Driver.cpp b/video/IndirectDisplay/IddSampleDriver/Driver.cpp
new file mode 100644
index 00000000..a9bd6108
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/Driver.cpp
@@ -0,0 +1,686 @@
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Abstract:
+
+ This module contains a sample implementation of an indirect display driver. See the included README.md file and the
+ various TODO blocks throughout this file and all accompanying files for information on building a production driver.
+
+ MSDN documentation on indirect displays can be found at https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx.
+
+Environment:
+
+ User Mode, UMDF
+
+--*/
+
+#include "Driver.h"
+#include "Driver.tmh"
+
+using namespace std;
+using namespace Microsoft::IndirectDisp;
+using namespace Microsoft::WRL;
+
+extern "C" DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_DRIVER_DEVICE_ADD IddSampleDeviceAdd;
+EVT_WDF_DEVICE_D0_ENTRY IddSampleDeviceD0Entry;
+
+EVT_IDD_CX_ADAPTER_INIT_FINISHED IddSampleAdapterInitFinished;
+EVT_IDD_CX_ADAPTER_COMMIT_MODES IddSampleAdapterCommitModes;
+
+EVT_IDD_CX_PARSE_MONITOR_DESCRIPTION IddSampleParseMonitorDescription;
+EVT_IDD_CX_MONITOR_GET_DEFAULT_DESCRIPTION_MODES IddSampleMonitorGetDefaultModes;
+EVT_IDD_CX_MONITOR_QUERY_TARGET_MODES IddSampleMonitorQueryModes;
+
+EVT_IDD_CX_MONITOR_ASSIGN_SWAPCHAIN IddSampleMonitorAssignSwapChain;
+EVT_IDD_CX_MONITOR_UNASSIGN_SWAPCHAIN IddSampleMonitorUnassignSwapChain;
+
+struct IndirectDeviceContextWrapper
+{
+ IndirectDeviceContext* pContext;
+
+ void Cleanup()
+ {
+ delete pContext;
+ pContext = nullptr;
+ }
+};
+
+// This macro creates the methods for accessing an IndirectDeviceContextWrapper as a context for a WDF object
+WDF_DECLARE_CONTEXT_TYPE(IndirectDeviceContextWrapper);
+
+extern "C" BOOL WINAPI DllMain(
+ _In_ HINSTANCE hInstance,
+ _In_ UINT dwReason,
+ _In_opt_ LPVOID lpReserved)
+{
+ UNREFERENCED_PARAMETER(hInstance);
+ UNREFERENCED_PARAMETER(lpReserved);
+ UNREFERENCED_PARAMETER(dwReason);
+
+ return TRUE;
+}
+
+_Use_decl_annotations_
+extern "C" NTSTATUS DriverEntry(
+ PDRIVER_OBJECT pDriverObject,
+ PUNICODE_STRING pRegistryPath
+)
+{
+ WDF_DRIVER_CONFIG Config;
+ NTSTATUS Status;
+
+ WDF_OBJECT_ATTRIBUTES Attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
+
+ WDF_DRIVER_CONFIG_INIT(&Config,
+ IddSampleDeviceAdd
+ );
+
+ Status = WdfDriverCreate(pDriverObject, pRegistryPath, &Attributes, &Config, WDF_NO_HANDLE);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ return Status;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT pDeviceInit)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ // Register for power callbacks - in this sample only power-on is needed
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
+ PnpPowerCallbacks.EvtDeviceD0Entry = IddSampleDeviceD0Entry;
+ WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &PnpPowerCallbacks);
+
+ IDD_CX_CLIENT_CONFIG IddConfig;
+ IDD_CX_CLIENT_CONFIG_INIT(&IddConfig);
+
+ // If the driver wishes to handle custom IoDeviceControl requests, it's necessary to use this callback since IddCx
+ // redirects IoDeviceControl requests to an internal queue. This sample does not need this.
+ // IddConfig.EvtIddCxDeviceIoControl = IddSampleIoDeviceControl;
+
+ IddConfig.EvtIddCxAdapterInitFinished = IddSampleAdapterInitFinished;
+
+ IddConfig.EvtIddCxParseMonitorDescription = IddSampleParseMonitorDescription;
+ IddConfig.EvtIddCxMonitorGetDefaultDescriptionModes = IddSampleMonitorGetDefaultModes;
+ IddConfig.EvtIddCxMonitorQueryTargetModes = IddSampleMonitorQueryModes;
+ IddConfig.EvtIddCxAdapterCommitModes = IddSampleAdapterCommitModes;
+ IddConfig.EvtIddCxMonitorAssignSwapChain = IddSampleMonitorAssignSwapChain;
+ IddConfig.EvtIddCxMonitorUnassignSwapChain = IddSampleMonitorUnassignSwapChain;
+
+ Status = IddCxDeviceInitConfig(pDeviceInit, &IddConfig);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ WDF_OBJECT_ATTRIBUTES Attr;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
+ Attr.EvtCleanupCallback = [](WDFOBJECT Object)
+ {
+ // Automatically cleanup the context when the WDF object is about to be deleted
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Object);
+ if (pContext)
+ {
+ pContext->Cleanup();
+ }
+ };
+
+ WDFDEVICE Device = nullptr;
+ Status = WdfDeviceCreate(&pDeviceInit, &Attr, &Device);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ Status = IddCxDeviceInitialize(Device);
+
+ // Create a new device context object and attach it to the WDF device object
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device);
+ pContext->pContext = new IndirectDeviceContext(Device);
+
+ return Status;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleDeviceD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
+{
+ UNREFERENCED_PARAMETER(PreviousState);
+
+ // This function is called by WDF to start the device in the fully-on power state.
+
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(Device);
+ pContext->pContext->InitAdapter();
+
+ return STATUS_SUCCESS;
+}
+
+#pragma region Direct3DDevice
+
+Direct3DDevice::Direct3DDevice(LUID AdapterLuid) : AdapterLuid(AdapterLuid)
+{
+
+}
+
+Direct3DDevice::Direct3DDevice()
+{
+ AdapterLuid = LUID{};
+}
+
+HRESULT Direct3DDevice::Init()
+{
+ // The DXGI factory could be cached, but if a new render adapter appears on the system, a new factory needs to be
+ // created. If caching is desired, check DxgiFactory->IsCurrent() each time and recreate the factory if !IsCurrent.
+ HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&DxgiFactory));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Find the specified render adapter
+ hr = DxgiFactory->EnumAdapterByLuid(AdapterLuid, IID_PPV_ARGS(&Adapter));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Create a D3D device using the render adapter. BGRA support is required by the WHQL test suite.
+ hr = D3D11CreateDevice(Adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, &Device, nullptr, &DeviceContext);
+ if (FAILED(hr))
+ {
+ // If creating the D3D device failed, it's possible the render GPU was lost (e.g. detachable GPU) or else the
+ // system is in a transient state.
+ return hr;
+ }
+
+ return S_OK;
+}
+
+#pragma endregion
+
+#pragma region SwapChainProcessor
+
+SwapChainProcessor::SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, shared_ptr<Direct3DDevice> Device, HANDLE NewFrameEvent)
+ : m_hSwapChain(hSwapChain), m_Device(Device), m_hAvailableBufferEvent(NewFrameEvent)
+{
+ m_hTerminateEvent.Attach(CreateEvent(nullptr, FALSE, FALSE, nullptr));
+
+ // Immediately create and run the swap-chain processing thread, passing 'this' as the thread parameter
+ m_hThread.Attach(CreateThread(nullptr, 0, RunThread, this, 0, nullptr));
+}
+
+SwapChainProcessor::~SwapChainProcessor()
+{
+ // Alert the swap-chain processing thread to terminate
+ SetEvent(m_hTerminateEvent.Get());
+
+ if (m_hThread.Get())
+ {
+ // Wait for the thread to terminate
+ WaitForSingleObject(m_hThread.Get(), INFINITE);
+ }
+}
+
+DWORD CALLBACK SwapChainProcessor::RunThread(LPVOID Argument)
+{
+ reinterpret_cast<SwapChainProcessor*>(Argument)->Run();
+ return 0;
+}
+
+void SwapChainProcessor::Run()
+{
+ // For improved performance, make use of the Multimedia Class Scheduler Service, which will intelligently
+ // prioritize this thread for improved throughput in high CPU-load scenarios.
+ DWORD AvTask = 0;
+ HANDLE AvTaskHandle = AvSetMmThreadCharacteristics(L"Distribution", &AvTask);
+
+ RunCore();
+
+ // Always delete the swap-chain object when swap-chain processing loop terminates in order to kick the system to
+ // provide a new swap-chain if necessary.
+ WdfObjectDelete((WDFOBJECT)m_hSwapChain);
+ m_hSwapChain = nullptr;
+
+ AvRevertMmThreadCharacteristics(AvTaskHandle);
+}
+
+void SwapChainProcessor::RunCore()
+{
+ // Get the DXGI device interface
+ ComPtr<IDXGIDevice> DxgiDevice;
+ HRESULT hr = m_Device->Device.As(&DxgiDevice);
+ if (FAILED(hr))
+ {
+ return;
+ }
+
+ IDARG_IN_SWAPCHAINSETDEVICE SetDevice = {};
+ SetDevice.pDevice = DxgiDevice.Get();
+
+ hr = IddCxSwapChainSetDevice(m_hSwapChain, &SetDevice);
+ if (FAILED(hr))
+ {
+ return;
+ }
+
+ // Acquire and release buffers in a loop
+ for (;;)
+ {
+ ComPtr<IDXGIResource> AcquiredBuffer;
+
+ // Ask for the next buffer from the producer
+ IDARG_OUT_RELEASEANDACQUIREBUFFER Buffer = {};
+ hr = IddCxSwapChainReleaseAndAcquireBuffer(m_hSwapChain, &Buffer);
+
+ // AcquireBuffer immediately returns STATUS_PENDING if no buffer is yet available
+ if (hr == E_PENDING)
+ {
+ // We must wait for a new buffer
+ HANDLE WaitHandles [] =
+ {
+ m_hAvailableBufferEvent,
+ m_hTerminateEvent.Get()
+ };
+ DWORD WaitResult = WaitForMultipleObjects(ARRAYSIZE(WaitHandles), WaitHandles, FALSE, 16);
+ if (WaitResult == WAIT_OBJECT_0 || WaitResult == WAIT_TIMEOUT)
+ {
+ // We have a new buffer, so try the AcquireBuffer again
+ continue;
+ }
+ else if (WaitResult == WAIT_OBJECT_0 + 1)
+ {
+ // We need to terminate
+ break;
+ }
+ else
+ {
+ // The wait was cancelled or something unexpected happened
+ hr = HRESULT_FROM_WIN32(WaitResult);
+ break;
+ }
+ }
+ else if (SUCCEEDED(hr))
+ {
+ AcquiredBuffer.Attach(Buffer.MetaData.pSurface);
+
+ // ==============================
+ // TODO: Process the frame here
+ //
+ // This is the most performance-critical section of code in an IddCx driver. It's important that whatever
+ // is done with the acquired surface be finished as quickly as possible. This operation could be:
+ // * a GPU copy to another buffer surface for later processing (such as a staging surface for mapping to CPU memory)
+ // * a GPU encode operation
+ // * a GPU VPBlt to another surface
+ // * a GPU custom compute shader encode operation
+ // ==============================
+
+ AcquiredBuffer.Reset();
+ hr = IddCxSwapChainFinishedProcessingFrame(m_hSwapChain);
+ if (FAILED(hr))
+ {
+ break;
+ }
+
+ // ==============================
+ // TODO: Report frame statistics once the asynchronous encode/send work is completed
+ //
+ // Drivers should report information about sub-frame timings, like encode time, send time, etc.
+ // ==============================
+ // IddCxSwapChainReportFrameStatistics(m_hSwapChain, ...);
+ }
+ else
+ {
+ // The swap-chain was likely abandoned (e.g. DXGI_ERROR_ACCESS_LOST), so exit the processing loop
+ break;
+ }
+ }
+}
+
+#pragma endregion
+
+#pragma region IndirectDeviceContext
+
+const UINT64 MHZ = 1000000;
+const UINT64 KHZ = 1000;
+
+// A list of modes exposed by the sample monitor EDID - FOR SAMPLE PURPOSES ONLY
+const DISPLAYCONFIG_VIDEO_SIGNAL_INFO IndirectDeviceContext::s_KnownMonitorModes[] =
+{
+ // 800 x 600 @ 60Hz
+ {
+ 40 * MHZ, // pixel clock rate [Hz]
+ { 40 * MHZ, 800 + 256 }, // fractional horizontal refresh rate [Hz]
+ { 40 * MHZ, (800 + 256) * (600 + 28) }, // fractional vertical refresh rate [Hz]
+ { 800, 600 }, // (horizontal, vertical) active pixel resolution
+ { 800 + 256, 600 + 28 }, // (horizontal, vertical) total pixel resolution
+ { { 255, 0 }}, // video standard and vsync divider
+ DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE
+ },
+ // 640 x 480 @ 60Hz
+ {
+ 25175 * KHZ, // pixel clock rate [Hz]
+ { 25175 * KHZ, 640 + 160 }, // fractional horizontal refresh rate [Hz]
+ { 25175 * KHZ, (640 + 160) * (480 + 46) }, // fractional vertical refresh rate [Hz]
+ { 640, 480 }, // (horizontal, vertical) active pixel resolution
+ { 640 + 160, 480 + 46 }, // (horizontal, vertical) blanking pixel resolution
+ { { 255, 0 } }, // video standard and vsync divider
+ DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE
+ },
+};
+
+// This is a sample monitor EDID - FOR SAMPLE PURPOSES ONLY
+const BYTE IndirectDeviceContext::s_KnownMonitorEdid[] =
+{
+ 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x79,0x5E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA6,0x01,0x03,0x80,0x28,
+ 0x1E,0x78,0x0A,0xEE,0x91,0xA3,0x54,0x4C,0x99,0x26,0x0F,0x50,0x54,0x20,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xA0,0x0F,0x20,0x00,0x31,0x58,0x1C,0x20,0x28,0x80,0x14,0x00,
+ 0x90,0x2C,0x11,0x00,0x00,0x1E,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E
+};
+
+IndirectDeviceContext::IndirectDeviceContext(_In_ WDFDEVICE WdfDevice) :
+ m_WdfDevice(WdfDevice)
+{
+ m_Adapter = {};
+ m_Monitor = {};
+}
+
+IndirectDeviceContext::~IndirectDeviceContext()
+{
+ m_ProcessingThread.reset();
+}
+
+void IndirectDeviceContext::InitAdapter()
+{
+ // ==============================
+ // TODO: Update the below diagnostic information in accordance with the target hardware. The strings and version
+ // numbers are used for telemetry and may be displayed to the user in some situations.
+ //
+ // This is also where static per-adapter capabilities are determined.
+ // ==============================
+
+ IDDCX_ADAPTER_CAPS AdapterCaps = {};
+ AdapterCaps.Size = sizeof(AdapterCaps);
+
+ // Declare basic feature support for the adapter (required)
+ AdapterCaps.MaxMonitorsSupported = 1;
+ AdapterCaps.EndPointDiagnostics.Size = sizeof(AdapterCaps.EndPointDiagnostics);
+ AdapterCaps.EndPointDiagnostics.GammaSupport = IDDCX_FEATURE_IMPLEMENTATION_NONE;
+ AdapterCaps.EndPointDiagnostics.TransmissionType = IDDCX_TRANSMISSION_TYPE_WIRED_OTHER;
+
+ // Declare your device strings for telemetry (required)
+ AdapterCaps.EndPointDiagnostics.pEndPointFriendlyName = L"IddSample Device";
+ AdapterCaps.EndPointDiagnostics.pEndPointManufacturerName = L"Microsoft";
+ AdapterCaps.EndPointDiagnostics.pEndPointModelName = L"IddSample Model";
+
+ // Declare your hardware and firmware versions (required)
+ IDDCX_ENDPOINT_VERSION Version = {};
+ Version.Size = sizeof(Version);
+ Version.MajorVer = 1;
+ AdapterCaps.EndPointDiagnostics.pFirmwareVersion = &Version;
+ AdapterCaps.EndPointDiagnostics.pHardwareVersion = &Version;
+
+ // Initialize a WDF context that can store a pointer to the device context object
+ WDF_OBJECT_ATTRIBUTES Attr;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
+
+ IDARG_IN_ADAPTER_INIT AdapterInit = {};
+ AdapterInit.WdfDevice = m_WdfDevice;
+ AdapterInit.pCaps = &AdapterCaps;
+ AdapterInit.ObjectAttributes = &Attr;
+
+ // Start the initialization of the adapter, which will trigger the AdapterFinishInit callback later
+ IDARG_OUT_ADAPTER_INIT AdapterInitOut;
+ NTSTATUS Status = IddCxAdapterInitAsync(&AdapterInit, &AdapterInitOut);
+
+ if (NT_SUCCESS(Status))
+ {
+ // Store a reference to the WDF adapter handle
+ m_Adapter = AdapterInitOut.AdapterObject;
+
+ // Store the device context object into the WDF object context
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(AdapterInitOut.AdapterObject);
+ pContext->pContext = this;
+ }
+}
+
+void IndirectDeviceContext::FinishInit()
+{
+ // ==============================
+ // TODO: In a real driver, the EDID should be retrieved dynamically from a connected physical monitor. The EDID
+ // provided here is purely for demonstration, as it describes only 640x480 @ 60 Hz and 800x600 @ 60 Hz. Monitor
+ // manufacturers are required to correctly fill in physical monitor attributes in order to allow the OS to optimize
+ // settings like viewing distance and scale factor. Manufacturers should also use a unique serial number every
+ // single device to ensure the OS can tell the monitors apart.
+ // ==============================
+
+ WDF_OBJECT_ATTRIBUTES Attr;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attr, IndirectDeviceContextWrapper);
+
+ IDDCX_MONITOR_INFO MonitorInfo = {};
+ MonitorInfo.Size = sizeof(MonitorInfo);
+ MonitorInfo.MonitorType = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI;
+ MonitorInfo.ConnectorIndex = 0;
+ MonitorInfo.MonitorDescription.Size = sizeof(MonitorInfo.MonitorDescription);
+ MonitorInfo.MonitorDescription.Type = IDDCX_MONITOR_DESCRIPTION_TYPE_EDID;
+ MonitorInfo.MonitorDescription.DataSize = sizeof(s_KnownMonitorEdid);
+ MonitorInfo.MonitorDescription.pData = const_cast<BYTE*>(s_KnownMonitorEdid);
+
+ // ==============================
+ // TODO: The monitor's container ID should be distinct from "this" device's container ID if the monitor is not
+ // permanently attached to the display adapter device object. The container ID is typically made unique for each
+ // monitor and can be used to associate the monitor with other devices, like audio or input devices. In this
+ // sample we generate a random container ID GUID, but it's best practice to choose a stable container ID for a
+ // unique monitor or to use "this" device's container ID for a permanent/integrated monitor.
+ // ==============================
+
+ // Create a container ID
+ CoCreateGuid(&MonitorInfo.MonitorContainerId);
+
+ IDARG_IN_MONITORCREATE MonitorCreate = {};
+ MonitorCreate.ObjectAttributes = &Attr;
+ MonitorCreate.pMonitorInfo = &MonitorInfo;
+
+ // Create a monitor object with the specified monitor descriptor
+ IDARG_OUT_MONITORCREATE MonitorCreateOut;
+ NTSTATUS Status = IddCxMonitorCreate(m_Adapter, &MonitorCreate, &MonitorCreateOut);
+ if (NT_SUCCESS(Status))
+ {
+ m_Monitor = MonitorCreateOut.MonitorObject;
+
+ // Associate the monitor with this device context
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorCreateOut.MonitorObject);
+ pContext->pContext = this;
+
+ // Tell the OS that the monitor has been plugged in
+ IDARG_OUT_MONITORARRIVAL ArrivalOut;
+ Status = IddCxMonitorArrival(m_Monitor, &ArrivalOut);
+ }
+}
+
+void IndirectDeviceContext::AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent)
+{
+ m_ProcessingThread.reset();
+
+ auto Device = make_shared<Direct3DDevice>(RenderAdapter);
+ if (FAILED(Device->Init()))
+ {
+ // It's important to delete the swap-chain if D3D initialization fails, so that the OS knows to generate a new
+ // swap-chain and try again.
+ WdfObjectDelete(SwapChain);
+ }
+ else
+ {
+ // Create a new swap-chain processing thread
+ m_ProcessingThread.reset(new SwapChainProcessor(SwapChain, Device, NewFrameEvent));
+ }
+}
+
+void IndirectDeviceContext::UnassignSwapChain()
+{
+ // Stop processing the last swap-chain
+ m_ProcessingThread.reset();
+}
+
+#pragma endregion
+
+#pragma region DDI Callbacks
+
+_Use_decl_annotations_
+NTSTATUS IddSampleAdapterInitFinished(IDDCX_ADAPTER AdapterObject, const IDARG_IN_ADAPTER_INIT_FINISHED* pInArgs)
+{
+ // This is called when the OS has finished setting up the adapter for use by the IddCx driver. It's now possible
+ // to report attached monitors.
+
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(AdapterObject);
+ if (NT_SUCCESS(pInArgs->AdapterInitStatus))
+ {
+ pContext->pContext->FinishInit();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleAdapterCommitModes(IDDCX_ADAPTER AdapterObject, const IDARG_IN_COMMITMODES* pInArgs)
+{
+ UNREFERENCED_PARAMETER(AdapterObject);
+ UNREFERENCED_PARAMETER(pInArgs);
+
+ // For the sample, do nothing when modes are picked - the swap-chain is taken care of by IddCx
+
+ // ==============================
+ // TODO: In a real driver, this function would be used to reconfigure the device to commit the new modes. Loop
+ // through pInArgs->pPaths and look for IDDCX_PATH_FLAGS_ACTIVE. Any path not active is inactive (e.g. the monitor
+ // should be turned off).
+ // ==============================
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleParseMonitorDescription(const IDARG_IN_PARSEMONITORDESCRIPTION* pInArgs, IDARG_OUT_PARSEMONITORDESCRIPTION* pOutArgs)
+{
+ // ==============================
+ // TODO: In a real driver, this function would be called to generate monitor modes for an EDID by parsing it. In
+ // this sample driver, we hard-code the EDID, so this function can generate known modes.
+ // ==============================
+
+ pOutArgs->MonitorModeBufferOutputCount = ARRAYSIZE(IndirectDeviceContext::s_KnownMonitorModes);
+
+ if (pInArgs->MonitorModeBufferInputCount < ARRAYSIZE(IndirectDeviceContext::s_KnownMonitorModes))
+ {
+ // Return success if there was no buffer, since the caller was only asking for a count of modes
+ return (pInArgs->MonitorModeBufferInputCount > 0) ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS;
+ }
+ else
+ {
+ // Copy the known modes to the output buffer
+ for (DWORD ModeIndex = 0; ModeIndex < ARRAYSIZE(IndirectDeviceContext::s_KnownMonitorModes); ModeIndex++)
+ {
+ pInArgs->pMonitorModes[ModeIndex].Size = sizeof(IDDCX_MONITOR_MODE);
+ pInArgs->pMonitorModes[ModeIndex].Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR;
+ pInArgs->pMonitorModes[ModeIndex].MonitorVideoSignalInfo = IndirectDeviceContext::s_KnownMonitorModes[ModeIndex];
+ }
+
+ // Set the preferred mode as represented in the EDID
+ pOutArgs->PreferredMonitorModeIdx = 0;
+
+ return STATUS_SUCCESS;
+ }
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorGetDefaultModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_GETDEFAULTDESCRIPTIONMODES* pInArgs, IDARG_OUT_GETDEFAULTDESCRIPTIONMODES* pOutArgs)
+{
+ UNREFERENCED_PARAMETER(MonitorObject);
+ UNREFERENCED_PARAMETER(pInArgs);
+ UNREFERENCED_PARAMETER(pOutArgs);
+
+ // Should never be called since we create a single monitor with a known EDID in this sample driver.
+
+ // ==============================
+ // TODO: In a real driver, this function would be called to generate monitor modes for a monitor with no EDID.
+ // Drivers should report modes that are guaranteed to be supported by the transport protocol and by nearly all
+ // monitors (such 640x480, 800x600, or 1024x768). If the driver has access to monitor modes from a descriptor other
+ // than an EDID, those modes would also be reported here.
+ // ==============================
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+/// <summary>
+/// Creates a target mode from the fundamental mode attributes.
+/// </summary>
+void CreateTargetMode(DISPLAYCONFIG_VIDEO_SIGNAL_INFO& Mode, UINT Width, UINT Height, UINT VSync)
+{
+ Mode.totalSize.cx = Mode.activeSize.cx = Width;
+ Mode.totalSize.cy = Mode.activeSize.cy = Height;
+ Mode.AdditionalSignalInfo.vSyncFreqDivider = 1;
+ Mode.AdditionalSignalInfo.videoStandard = 255;
+ Mode.vSyncFreq.Numerator = VSync;
+ Mode.vSyncFreq.Denominator = Mode.hSyncFreq.Denominator = 1;
+ Mode.hSyncFreq.Numerator = VSync * Height;
+ Mode.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE;
+ Mode.pixelRate = ((UINT64) VSync) * ((UINT64) Width) * ((UINT64) Height);
+}
+
+void CreateTargetMode(IDDCX_TARGET_MODE& Mode, UINT Width, UINT Height, UINT VSync)
+{
+ Mode.Size = sizeof(Mode);
+ CreateTargetMode(Mode.TargetVideoSignalInfo.targetVideoSignalInfo, Width, Height, VSync);
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorQueryModes(IDDCX_MONITOR MonitorObject, const IDARG_IN_QUERYTARGETMODES* pInArgs, IDARG_OUT_QUERYTARGETMODES* pOutArgs)
+{
+ UNREFERENCED_PARAMETER(MonitorObject);
+
+ vector<IDDCX_TARGET_MODE> TargetModes(4);
+
+ // Create a set of modes supported for frame processing and scan-out. These are typically not based on the
+ // monitor's descriptor and instead are based on the static processing capability of the device. The OS will
+ // report the available set of modes for a given output as the intersection of monitor modes with target modes.
+
+ CreateTargetMode(TargetModes[0], 1920, 1080, 60);
+ CreateTargetMode(TargetModes[1], 1024, 768, 60);
+ CreateTargetMode(TargetModes[2], 800, 600, 60);
+ CreateTargetMode(TargetModes[3], 640, 480, 60);
+
+ pOutArgs->TargetModeBufferOutputCount = (UINT)TargetModes.size();
+
+ if (pInArgs->TargetModeBufferInputCount >= TargetModes.size())
+ {
+ copy(TargetModes.begin(), TargetModes.end(), pInArgs->pTargetModes);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorAssignSwapChain(IDDCX_MONITOR MonitorObject, const IDARG_IN_SETSWAPCHAIN* pInArgs)
+{
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorObject);
+ pContext->pContext->AssignSwapChain(pInArgs->hSwapChain, pInArgs->RenderAdapterLuid, pInArgs->hNextSurfaceAvailable);
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+NTSTATUS IddSampleMonitorUnassignSwapChain(IDDCX_MONITOR MonitorObject)
+{
+ auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(MonitorObject);
+ pContext->pContext->UnassignSwapChain();
+ return STATUS_SUCCESS;
+}
+
+#pragma endregion
diff --git a/video/IndirectDisplay/IddSampleDriver/Driver.h b/video/IndirectDisplay/IddSampleDriver/Driver.h
new file mode 100644
index 00000000..df69b0e4
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/Driver.h
@@ -0,0 +1,103 @@
+#pragma once
+
+#define NOMINMAX
+#include <windows.h>
+#include <bugcodes.h>
+#include <wudfwdm.h>
+#include <wdf.h>
+#include <iddcx.h>
+
+#include <dxgi1_5.h>
+#include <d3d11_2.h>
+#include <avrt.h>
+#include <wrl.h>
+
+#include <memory>
+#include <vector>
+
+#include "Trace.h"
+
+namespace Microsoft
+{
+ namespace WRL
+ {
+ namespace Wrappers
+ {
+ // Adds a wrapper for thread handles to the existing set of WRL handle wrapper classes
+ typedef HandleT<HandleTraits::HANDLENullTraits> Thread;
+ }
+ }
+}
+
+namespace Microsoft
+{
+ namespace IndirectDisp
+ {
+ /// <summary>
+ /// Manages the creation and lifetime of a Direct3D render device.
+ /// </summary>
+ struct Direct3DDevice
+ {
+ Direct3DDevice(LUID AdapterLuid);
+ Direct3DDevice();
+ HRESULT Init();
+
+ LUID AdapterLuid;
+ Microsoft::WRL::ComPtr<IDXGIFactory5> DxgiFactory;
+ Microsoft::WRL::ComPtr<IDXGIAdapter1> Adapter;
+ Microsoft::WRL::ComPtr<ID3D11Device> Device;
+ Microsoft::WRL::ComPtr<ID3D11DeviceContext> DeviceContext;
+ };
+
+ /// <summary>
+ /// Manages a thread that consumes buffers from an indirect display swap-chain object.
+ /// </summary>
+ class SwapChainProcessor
+ {
+ public:
+ SwapChainProcessor(IDDCX_SWAPCHAIN hSwapChain, std::shared_ptr<Direct3DDevice> Device, HANDLE NewFrameEvent);
+ ~SwapChainProcessor();
+
+ private:
+ static DWORD CALLBACK RunThread(LPVOID Argument);
+
+ void Run();
+ void RunCore();
+
+ public:
+ IDDCX_SWAPCHAIN m_hSwapChain;
+ std::shared_ptr<Direct3DDevice> m_Device;
+ HANDLE m_hAvailableBufferEvent;
+ Microsoft::WRL::Wrappers::Thread m_hThread;
+ Microsoft::WRL::Wrappers::Event m_hTerminateEvent;
+ };
+
+ /// <summary>
+ /// Provides a sample implementation of an indirect display driver.
+ /// </summary>
+ class IndirectDeviceContext
+ {
+ public:
+ IndirectDeviceContext(_In_ WDFDEVICE WdfDevice);
+ virtual ~IndirectDeviceContext();
+
+ void InitAdapter();
+ void FinishInit();
+
+ void AssignSwapChain(IDDCX_SWAPCHAIN SwapChain, LUID RenderAdapter, HANDLE NewFrameEvent);
+ void UnassignSwapChain();
+
+ protected:
+
+ WDFDEVICE m_WdfDevice;
+ IDDCX_ADAPTER m_Adapter;
+ IDDCX_MONITOR m_Monitor;
+
+ std::unique_ptr<SwapChainProcessor> m_ProcessingThread;
+
+ public:
+ static const DISPLAYCONFIG_VIDEO_SIGNAL_INFO s_KnownMonitorModes[];
+ static const BYTE s_KnownMonitorEdid[];
+ };
+ }
+}
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf
new file mode 100644
index 00000000..d70c8a87
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.inf
Binary files differ
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc
new file mode 100644
index 00000000..ca2d8226
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "UMDF Indirect Display Driver Sample"
+#define VER_INTERNALNAME_STR "IddSampleDriver"
+#define VER_ORIGINALFILENAME_STR "IddSampleDriver.dll"
+
+#include "common.ver"
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj
new file mode 100644
index 00000000..8a484288
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj
@@ -0,0 +1,319 @@
+<?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>
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Driver.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Driver.h" />
+ <ClInclude Include="Trace.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="IddSampleDriver.inf" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2D54CB75-8B17-4F11-97DC-847B0244CD46}</ProjectGuid>
+ <TemplateGuid>{32909489-7be5-497b-aafa-db6669d9b44b}</TemplateGuid>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <Configuration>Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <RootNamespace>IddSampleDriver</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <UMDF_VERSION_MINOR>25</UMDF_VERSION_MINOR>
+ <IndirectDisplayDriver>true</IndirectDisplayDriver>
+ <IDDCX_VERSION_MAJOR>1</IDDCX_VERSION_MAJOR>
+ <IDDCX_VERSION_MINOR>4</IDDCX_VERSION_MINOR>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalOptions>/D_ATL_NO_WIN_SUPPORT /DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions)</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ <AdditionalOptions>/DUMDF_DRIVER /DIDDCX_VERSION_MAJOR=1 /DIDDCX_VERSION_MINOR=6 /DIDDCX_MINIMUM_VERSION_REQUIRED=4 %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <ExceptionHandling>Async</ExceptionHandling>
+ <EnablePREfast>true</EnablePREfast>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib;avrt.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters
new file mode 100644
index 00000000..f47c3804
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/IddSampleDriver.vcxproj.filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Driver Files">
+ <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="IddSampleDriver.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Driver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Trace.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/video/IndirectDisplay/IddSampleDriver/Trace.h b/video/IndirectDisplay/IddSampleDriver/Trace.h
new file mode 100644
index 00000000..9852bab4
--- /dev/null
+++ b/video/IndirectDisplay/IddSampleDriver/Trace.h
@@ -0,0 +1,63 @@
+/*++
+
+Module Name:
+
+ Internal.h
+
+Abstract:
+
+ This module contains the local type definitions for the
+ driver.
+
+Environment:
+
+ Windows User-Mode Driver Framework 2
+
+--*/
+
+//
+// Define the tracing flags.
+//
+// Tracing GUID - b254994f-46e6-4718-80a0-0a3aa50d6ce4
+//
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ MyDriver1TraceGuid, (b254994f,46e6,4718,80a0,0a3aa50d6ce4), \
+ \
+ WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
+ WPP_DEFINE_BIT(TRACE_DRIVER) \
+ WPP_DEFINE_BIT(TRACE_DEVICE) \
+ WPP_DEFINE_BIT(TRACE_QUEUE) \
+ )
+
+#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)
+
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
+ WPP_LEVEL_LOGGER(flags)
+
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
+ (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
+
+//
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
+// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
+// end_wpp
+
+//
+//
+// Driver specific #defines
+//
+
+// TODO: Use a unique driver tracing ID here,
+// see https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/adding-wpp-software-tracing-to-a-windows-driver
+#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF2.25\\IddSampleDriver v1.0"
diff --git a/video/IndirectDisplay/README.md b/video/IndirectDisplay/README.md
new file mode 100644
index 00000000..ac399233
--- /dev/null
+++ b/video/IndirectDisplay/README.md
@@ -0,0 +1,48 @@
+---
+topic: sample
+page_type: sample
+languages:
+- cpp
+products:
+- windows
+- windows-wdk
+name: 'IddSample'
+description: "Implements a sample IddCx 1.4 driver and a sample application that instantiates a software device using it."
+statusNotificationTargets:
+---
+
+# Indirect Display Driver Sample #
+
+This is a sample driver that shows how to create a Windows Indirect Display Driver using IddCx (Indirect Display Driver Class eXtension).
+
+## Background reading ##
+
+Start at the [Indirect Display Driver Model Overview](https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx) on MSDN.
+
+## Customizing the sample ##
+
+The sample driver code is very simplistic and does nothing more than enumerate a single monitor when its device enters the D0/started power state. Throughout the code, there are `TODO` blocks with important information on implementing functionality in a production driver.
+
+### Code structure ###
+
+* `Direct3DDevice` class
+ * Contains logic for enumerating the correct render GPU from DXGI and creating a D3D device.
+ * Manages the lifetime of a DXGI factory and a D3D device created for the render GPU the system is using to render frames for your indirect display device's swap-chain.
+* `SwapChainProcessor` class
+ * Processes frames for a swap-chain assigned to the monitor object on a dedicated thread.
+ * The sample code does nothing with the frames, but demonstrates a correct processing loop with error handling and notifying the OS of frame completion.
+* `IndirectDeviceContext` class
+ * Processes device callbacks from IddCx.
+ * Manages the creation and arrival of the sample monitor.
+ * Handles swap-chain arrival and departure by creating a `Direct3DDevice` and handing it off to a `SwapChainProcessor`.
+
+### First steps ###
+
+Consider the capabilities of your device. If the device supports multiple monitors being hotplugged and removed at runtime, you may want to abstract the monitors further from the `IndirectDeviceContext` class.
+
+The INF file included in the sample needs updating for production use. One field, `DeviceGroupId`, controls how the UMDF driver gets pooled with other UMDF drivers in the same process. Since indirect display drivers tend to be more complicated than other driver classes, it's highly recommended that you pick a unique string for this field which will cause instances of your device driver to pool in a dedicated process. This will improve system reliability in case your driver encounters a problem since other drivers will not be affected.
+
+Ensure the device information reported to `IddCxAdapterInitAsync` is accurate. This information determines how the device is reported to the OS and what static features (like support for gamma tables) the device will have available. If some information cannot be known immediately in the `EvtDeviceD0Entry` callback, IddCx allows the driver to call `IddCxAdapterInitAsync` at any point after D0 entry, before D0 exit.
+
+Careful attention should be paid to the frame processing loop. This will directly impact the performance of the user's system, so making use of the [Multimedia Class Scheduler Service](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684247(v=vs.85).aspx) and DXGI's support for [GPU prioritization](https://msdn.microsoft.com/en-us/library/windows/desktop/bb174534(v=vs.85).aspx) should be considered. Any significant work should be performed outside the main processing loop, such as by queuing work in a thread pool. See `SwapChainProcessor::RunCore` for more information. \ No newline at end of file