summaryrefslogtreecommitdiff
path: root/network/radio/RadioManagerSample/cpp
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-04-29 09:48:49 -0700
committerDave Wilson <[email protected]>2015-04-29 10:47:29 -0700
commitd40232638faaab19de557e70a3ee938da7a35295 (patch)
tree14e61c973745949af186b7940e3a53d25322f5de /network/radio/RadioManagerSample/cpp
parent02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff)
samples update for //build
Diffstat (limited to 'network/radio/RadioManagerSample/cpp')
-rw-r--r--network/radio/RadioManagerSample/cpp/InternalInterfaces.h23
-rw-r--r--network/radio/RadioManagerSample/cpp/RadioMgr.idl155
-rw-r--r--network/radio/RadioManagerSample/cpp/RadioMgr_interface.cpp3
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleInstanceCollection.cpp102
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleInstanceCollection.h32
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRM.def8
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRM.rc10
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRM.vcxproj326
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRM.vcxproj.Filters45
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRadioInstance.cpp523
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRadioInstance.h71
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRadioManager.cpp570
-rw-r--r--network/radio/RadioManagerSample/cpp/SampleRadioManager.h79
-rw-r--r--network/radio/RadioManagerSample/cpp/dllmain.cpp57
-rw-r--r--network/radio/RadioManagerSample/cpp/precomp.h17
-rw-r--r--network/radio/RadioManagerSample/cpp/precompsrc.cpp1
-rw-r--r--network/radio/RadioManagerSample/cpp/sampleRM.idl21
17 files changed, 2043 insertions, 0 deletions
diff --git a/network/radio/RadioManagerSample/cpp/InternalInterfaces.h b/network/radio/RadioManagerSample/cpp/InternalInterfaces.h
new file mode 100644
index 00000000..6e7f7b02
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/InternalInterfaces.h
@@ -0,0 +1,23 @@
+#pragma once
+
+interface __declspec(uuid("{931D7B9C-11FB-45B6-97DA-47894D597F39}")) ISampleRadioInstanceInternal : public IUnknown
+{
+ IFACEMETHOD(OnSysRadioChange)(_In_ SYSTEM_RADIO_STATE sysRadioState) = 0;
+};
+
+interface __declspec(uuid("{98595167-4F34-4247-A669-CA41ABBC479A}")) ISampleRadioManagerInternal : public IUnknown
+{
+ IFACEMETHOD(OnInstanceRadioChange)(_In_ BSTR bstrRadioInstanceID, _In_ DEVICE_RADIO_STATE radioState) = 0;
+};
+
+
+HRESULT CSampleRadioInstance_CreateInstance(
+ _In_ PCWSTR pszKeyName,
+ _In_ ISampleRadioManagerInternal *pParentManager,
+ _COM_Outptr_ ISampleRadioInstanceInternal **ppRadioInstance);
+
+HRESULT CRadioInstanceCollection_CreateInstance(
+ _In_ DWORD cInstances,
+ _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance,
+ _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection);
+
diff --git a/network/radio/RadioManagerSample/cpp/RadioMgr.idl b/network/radio/RadioManagerSample/cpp/RadioMgr.idl
new file mode 100644
index 00000000..5c7b5866
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/RadioMgr.idl
@@ -0,0 +1,155 @@
+//
+// Microsoft Windows
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// File: RadioMgr.idl
+//
+//----------------------------------------------------------------------------
+
+
+cpp_quote("//+-------------------------------------------------------------------------")
+cpp_quote("//")
+cpp_quote("// Microsoft Windows")
+cpp_quote("// Copyright (c) Microsoft Corporation. All rights reserved.")
+cpp_quote("//")
+cpp_quote("//--------------------------------------------------------------------------")
+
+cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN8)")
+
+import "oaidl.idl";
+import "wtypes.idl";
+
+
+interface IMediaRadioManager;
+interface IRadioInstanceCollection;
+interface IRadioInstance;
+interface IMediaRadioManagerNotifySink;
+
+typedef enum _DEVICE_RADIO_STATE
+{
+ DRS_RADIO_ON = 0,
+ DRS_SW_RADIO_OFF = 1,
+ DRS_HW_RADIO_OFF = 2,
+ DRS_SW_HW_RADIO_OFF = 3,
+ DRS_HW_RADIO_ON_UNCONTROLLABLE = 4,
+ DRS_RADIO_INVALID = 5,
+ DRS_HW_RADIO_OFF_UNCONTROLLABLE = 6,
+ DRS_RADIO_MAX = DRS_HW_RADIO_OFF_UNCONTROLLABLE
+} DEVICE_RADIO_STATE;
+
+typedef enum _SYSTEM_RADIO_STATE
+{
+ SRS_RADIO_ENABLED = 0,
+ SRS_RADIO_DISABLED = 1,
+} SYSTEM_RADIO_STATE;
+
+//+--------------------------------------------------------------------------------
+// IMediaRadioManager -- Represents high level radio operations on each radio type.
+// The object implementing this interface will implement a Connection point (IConnectionPoint)
+// for IMediaRadioManagerNotifySink.
+// Each IMediaRadioManager object controls several or no IRadioInstance objects.
+[
+ local,
+ object,
+ uuid(6CFDCAB5-FC47-42A5-9241-074B58830E73),
+ pointer_default(unique)
+]
+interface IMediaRadioManager : IUnknown
+{
+ HRESULT GetRadioInstances(
+ [out] IRadioInstanceCollection **ppCollection
+ );
+
+ HRESULT OnSystemRadioStateChange(
+ [in] SYSTEM_RADIO_STATE sysRadioState,
+ [in] UINT32 uTimeoutSec
+ );
+
+};
+
+
+//+---------------------------------------------------------------------------
+// IRadioInstanceCollection -- a flat list of radio instances
+//
+[
+ local,
+ object,
+ uuid(E5791FAE-5665-4E0C-95BE-5FDE31644185),
+ pointer_default(unique)
+]
+interface IRadioInstanceCollection : IUnknown
+{
+ HRESULT GetCount(
+ [out] UINT32 *pcInstance
+ );
+
+ HRESULT GetAt(
+ [in] UINT32 uIndex,
+ [out] IRadioInstance **ppRadioInstance
+ );
+};
+
+//+---------------------------------------------------------------------------
+// IRadioInstance -- Interface to control specific radio instance
+//
+[
+ local,
+ object,
+ uuid(70AA1C9E-F2B4-4C61-86D3-6B9FB75FD1A2),
+ pointer_default(unique)
+]
+interface IRadioInstance : IUnknown
+{
+ HRESULT GetRadioManagerSignature(
+ [out] GUID *pguidSignature
+ );
+
+ HRESULT GetInstanceSignature(
+ [out, string] BSTR *pbstrId
+ );
+
+ HRESULT GetFriendlyName(
+ [in] LCID lcid,
+ [out, string] BSTR *pbstrName
+ );
+
+ HRESULT GetRadioState(
+ [out] DEVICE_RADIO_STATE *pRadioState
+ );
+
+ HRESULT SetRadioState(
+ [in] DEVICE_RADIO_STATE radioState,
+ [in] UINT32 uTimeoutSec
+ );
+
+ BOOL IsMultiComm();
+
+ BOOL IsAssociatingDevice();
+}
+
+//+---------------------------------------------------------------------------
+// IMediaRadioManagerNotifySink -- notify instance add/remove and radio state change event
+//
+[
+ local,
+ object,
+ uuid(89D81F5F-C147-49ED-A11C-77B20C31E7C9),
+ pointer_default(unique)
+]
+interface IMediaRadioManagerNotifySink : IUnknown
+{
+ HRESULT OnInstanceAdd(
+ [in] IRadioInstance *pRadioInstance
+ );
+
+ HRESULT OnInstanceRemove(
+ [in, string] BSTR bstrRadioInstanceId
+ );
+
+ HRESULT OnInstanceRadioChange(
+ [in, string] BSTR bstrRadioInstanceId,
+ [in] DEVICE_RADIO_STATE radioState
+ );
+};
+
+cpp_quote("#endif // (NTDDI >= NTDDI_WIN8)")
diff --git a/network/radio/RadioManagerSample/cpp/RadioMgr_interface.cpp b/network/radio/RadioManagerSample/cpp/RadioMgr_interface.cpp
new file mode 100644
index 00000000..427e27fe
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/RadioMgr_interface.cpp
@@ -0,0 +1,3 @@
+#include "precomp.h"
+#pragma hdrstop
+#include "RadioMgr_i.c" \ No newline at end of file
diff --git a/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.cpp b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.cpp
new file mode 100644
index 00000000..5a4371de
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.cpp
@@ -0,0 +1,102 @@
+#include "precomp.h"
+#pragma hdrstop
+
+HRESULT CRadioInstanceCollection_CreateInstance(
+ _In_ DWORD cInstances,
+ _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance,
+ _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection)
+{
+ return CRadioInstanceCollection::CreateInstance(cInstances, rgpIRadioInstance, ppInstanceCollection);
+}
+
+void CRadioInstanceCollection::FinalRelease()
+{
+ POSITION p;
+ while (nullptr != (p = _listRadioInstances.GetHeadPosition()))
+ {
+ IRadioInstance *pRadioInstance = _listRadioInstances.GetAt(p);
+ pRadioInstance->Release();
+ _listRadioInstances.SetAt(p, nullptr);
+ _listRadioInstances.RemoveHeadNoReturn();
+ }
+}
+
+// static
+HRESULT CRadioInstanceCollection::CreateInstance(
+ _In_ DWORD cInstances,
+ _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance,
+ _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection)
+{
+ HRESULT hr;
+ CComObject<CRadioInstanceCollection> *pInstanceCollection;
+ CComPtr<IRadioInstanceCollection> spInstanceCollection;
+
+ *ppInstanceCollection = nullptr;
+
+ hr = CComObject<CRadioInstanceCollection>::CreateInstance(&pInstanceCollection);
+
+ if (SUCCEEDED(hr) && (pInstanceCollection != nullptr))
+ {
+ hr = pInstanceCollection->QueryInterface(IID_PPV_ARGS(&spInstanceCollection));
+ }
+
+ if (SUCCEEDED(hr) && (pInstanceCollection != nullptr))
+ {
+ for (DWORD dwIndex = 0; dwIndex < cInstances; dwIndex++)
+ {
+ _ATLTRY
+ {
+ pInstanceCollection->_listRadioInstances.AddTail(rgpIRadioInstance[dwIndex]);
+ rgpIRadioInstance[dwIndex]->AddRef();
+ }
+ _ATLCATCH(e)
+ {
+ hr = e;
+ break;
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *ppInstanceCollection = spInstanceCollection.Detach();
+ }
+
+ return hr;
+}
+
+IFACEMETHODIMP CRadioInstanceCollection::GetCount(_Out_ UINT32 *pcInstance)
+{
+ if (nullptr == pcInstance)
+ {
+ return E_INVALIDARG;
+ }
+
+ *pcInstance = static_cast<UINT32>(_listRadioInstances.GetCount());
+ return S_OK;
+}
+
+IFACEMETHODIMP CRadioInstanceCollection::GetAt(_In_ UINT32 uIndex, _COM_Outptr_ IRadioInstance **ppRadioInstance)
+{
+ if (nullptr == ppRadioInstance)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+ *ppRadioInstance = nullptr;
+
+ POSITION p = _listRadioInstances.FindIndex(uIndex);
+ *ppRadioInstance = _listRadioInstances.GetAt(p);
+ if (nullptr != *ppRadioInstance)
+ {
+ (*ppRadioInstance)->AddRef();
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+
+ return hr;
+}
diff --git a/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.h b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.h
new file mode 100644
index 00000000..b210adcb
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.h
@@ -0,0 +1,32 @@
+#pragma once
+
+class ATL_NO_VTABLE CRadioInstanceCollection :
+ public CComObjectRootEx<CComMultiThreadModel>,
+ public CComCoClass<CRadioInstanceCollection>,
+ public IRadioInstanceCollection
+{
+public:
+ DECLARE_CLASSFACTORY()
+ DECLARE_NOT_AGGREGATABLE(CRadioInstanceCollection)
+
+ DECLARE_NO_REGISTRY()
+
+ BEGIN_COM_MAP(CRadioInstanceCollection)
+ COM_INTERFACE_ENTRY(IRadioInstanceCollection)
+ END_COM_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ void FinalRelease();
+
+ static HRESULT CreateInstance(
+ _In_ DWORD cInstances,
+ _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance,
+ _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection);
+
+ IFACEMETHOD(GetCount)(_Out_ UINT32 *pcInstance);
+ IFACEMETHOD(GetAt)(_In_ UINT32 uIndex, _COM_Outptr_ IRadioInstance **ppRadioInstance);
+
+private:
+ CAtlList<IRadioInstance *> _listRadioInstances;
+};
diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.def b/network/radio/RadioManagerSample/cpp/SampleRM.def
new file mode 100644
index 00000000..535078cd
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRM.def
@@ -0,0 +1,8 @@
+LIBRARY SampleRM
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
+
diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.rc b/network/radio/RadioManagerSample/cpp/SampleRM.rc
new file mode 100644
index 00000000..2f491770
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRM.rc
@@ -0,0 +1,10 @@
+#include <ntverp.h>
+#include <winver.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Sample Radio Manager"
+#define VER_INTERNALNAME_STR "SampleRM.dll"
+
+#include <common.ver>
+
diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj
new file mode 100644
index 00000000..f26b9385
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{165D39D6-68AC-4E1F-89ED-483E13E84F9B}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{6D846F43-0EBE-4FCD-90E5-915DE0BCBA42}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>SampleRM</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>SampleRM</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>SampleRM</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>SampleRM</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <UseOfAtl>Dynamic</UseOfAtl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies>
+ <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="precompsrc.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Create</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="SampleInstanceCollection.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="SampleRadioInstance.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <ClCompile Include="SampleRadioManager.cpp">
+ <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>
+ <PreCompiledHeader>Use</PreCompiledHeader>
+ <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile>
+ </ClCompile>
+ <Midl Include="SampleRM.idl" />
+ <ResourceCompile Include="SampleRM.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj.Filters b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj.Filters
new file mode 100644
index 00000000..837a0aab
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj.Filters
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{6C044E6F-8320-46E5-9EBE-BDB0427DF29D}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{55F7F46D-B2E7-422F-8140-2F6D4D30D4FE}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{EB9B7D59-264D-421A-8077-FA89E50F57CF}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="precompsrc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SampleInstanceCollection.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SampleRadioInstance.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SampleRadioManager.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <Midl Include="SampleRM.idl">
+ <Filter>Source Files</Filter>
+ </Midl>
+ <None Include="SampleRM.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="SampleRM.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioInstance.cpp b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.cpp
new file mode 100644
index 00000000..08f7e285
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.cpp
@@ -0,0 +1,523 @@
+#include "precomp.h"
+#pragma hdrstop
+
+HRESULT CSampleRadioInstance_CreateInstance(
+ _In_ PCWSTR pszKeyName,
+ _In_ ISampleRadioManagerInternal *pParentManager,
+ _COM_Outptr_ ISampleRadioInstanceInternal **ppRadioInstance)
+{
+ return CSampleRadioInstance::CreateInstance(pszKeyName, pParentManager, ppRadioInstance);
+}
+
+PCWSTR CSampleRadioInstance::s_pszInstanceName = L"Name";
+PCWSTR CSampleRadioInstance::s_pszInstanceRadioState = L"RadioState";
+PCWSTR CSampleRadioInstance::s_pszPreviousRadioState = L"PreviousRadioState";
+PCWSTR CSampleRadioInstance::s_pszMultiComm = L"IsMultiComm";
+PCWSTR CSampleRadioInstance::s_pszAssocatingDevice = L"IsAssociatingDevice";
+
+CSampleRadioInstance::CSampleRadioInstance()
+ : _pParentManager(nullptr),
+ _fClosing(false),
+ _fIsMultiCommDevice(false)
+{
+}
+
+void CSampleRadioInstance::FinalRelease()
+{
+ if ((nullptr != _hRegChangeEvent) && (nullptr != _hEventThread))
+ {
+ {
+ // Critical section scope.
+ CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection);
+ _fClosing = true;
+ SetEvent(_hRegChangeEvent);
+ }
+ WaitForSingleObject(_hEventThread, INFINITE);
+ }
+
+ _Cleanup();
+}
+
+// static
+HRESULT CSampleRadioInstance::CreateInstance(
+ _In_ PCWSTR pszKeyName,
+ _In_ ISampleRadioManagerInternal *pParentManager,
+ _COM_Outptr_ ISampleRadioInstanceInternal **ppRadioInstance)
+{
+ HRESULT hr;
+ CComObject<CSampleRadioInstance> *pRadioInstance;
+ CComPtr<ISampleRadioInstanceInternal> spRadioInstanceInternal;
+
+ *ppRadioInstance = nullptr;
+
+ hr = CComObject<CSampleRadioInstance>::CreateInstance(&pRadioInstance);
+ if (SUCCEEDED(hr) && (pRadioInstance != nullptr))
+ {
+ hr = pRadioInstance->QueryInterface(IID_PPV_ARGS(&spRadioInstanceInternal));
+ }
+ if (SUCCEEDED(hr) && (pRadioInstance != nullptr))
+ {
+ hr = pRadioInstance->_Init(pszKeyName, pParentManager);
+ }
+ if (SUCCEEDED(hr))
+ {
+ *ppRadioInstance = spRadioInstanceInternal.Detach();
+ }
+
+ return hr;
+}
+
+HRESULT CSampleRadioInstance::_Init(_In_ PCWSTR pszKeyName, _In_ ISampleRadioManagerInternal *pParentManager)
+{
+ HRESULT hr;
+ DWORD dwError;
+ WCHAR szInstanceName[128] = {};
+ DWORD cchInstanceName = ARRAYSIZE(szInstanceName);
+
+ _ATLTRY
+ {
+ _strInstanceId = pszKeyName;
+ }
+ _ATLCATCH(e)
+ {
+ return e;
+ }
+
+ _pParentManager = pParentManager;
+
+ dwError = _hKeyRoot.Open(HKEY_LOCAL_MACHINE, _strInstanceId, KEY_ALL_ACCESS);
+
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ dwError = _hKeyRoot.QueryStringValue(s_pszInstanceName, szInstanceName, &cchInstanceName);
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ _ATLTRY
+ {
+ _strInstanceName = szInstanceName;
+ }
+ _ATLCATCH(e)
+ {
+ UNREFERENCED_PARAMETER(e);
+ dwError = ERROR_OUTOFMEMORY;
+ }
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ DWORD dwTemp = 0;
+ dwError = _hKeyRoot.QueryDWORDValue(s_pszMultiComm, dwTemp);
+ // only when key read successfully with non zero value, we regard device as multicomm chip
+ if ((ERROR_SUCCESS == dwError) && (0 != dwTemp))
+ {
+ _fIsMultiCommDevice = true;
+ }
+
+ // ignore the case when there is no IsMultiComm value in the registry, set ERROR_SUCCESS to continue with _Init
+ dwError = ERROR_SUCCESS;
+ }
+ }
+ }
+
+ // register the regkey value change event
+ if (ERROR_SUCCESS == dwError)
+ {
+ HANDLE hRegChangeEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ if ((NULL == hRegChangeEvent) || (INVALID_HANDLE_VALUE == hRegChangeEvent))
+ {
+ dwError = GetLastError();
+ }
+ else
+ {
+ _hRegChangeEvent.Attach(hRegChangeEvent);
+ }
+ }
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ HANDLE hThread= ::CreateThread(nullptr,
+ 0,
+ CSampleRadioInstance::s_ThreadInstanceChange,
+ reinterpret_cast<PVOID>(this),
+ 0,
+ nullptr);
+
+ if ((NULL == hThread) || (INVALID_HANDLE_VALUE == hThread))
+ {
+ dwError = GetLastError();
+ }
+ else
+ {
+ _hEventThread.Attach(hThread);
+ }
+
+ }
+
+ hr = HRESULT_FROM_WIN32(dwError);
+
+ if (FAILED(hr))
+ {
+ _Cleanup();
+ }
+
+ return hr;
+}
+
+void CSampleRadioInstance::_Cleanup()
+{
+ if (nullptr != _pParentManager)
+ {
+ _pParentManager = nullptr;
+ }
+}
+
+IFACEMETHODIMP CSampleRadioInstance::GetRadioManagerSignature(_Out_ GUID *pguidSignature)
+{
+ if (nullptr == pguidSignature)
+ {
+ return E_INVALIDARG;
+ }
+
+ *pguidSignature = __uuidof(SampleRadioManager);
+
+ return S_OK;
+}
+
+IFACEMETHODIMP CSampleRadioInstance::GetInstanceSignature(_Out_ BSTR *pbstrID)
+{
+ if (nullptr == pbstrID)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = S_OK;
+
+ *pbstrID = _strInstanceId.AllocSysString();
+ if (nullptr == *pbstrID)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ return hr;
+}
+
+IFACEMETHODIMP CSampleRadioInstance::GetFriendlyName(_In_ LCID /* lcid*/, _Out_ BSTR *pbstrName)
+{
+ if (nullptr == pbstrName)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = S_OK;
+
+ *pbstrName = _strInstanceName.AllocSysString();
+ if (nullptr == *pbstrName)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ return hr;
+}
+
+IFACEMETHODIMP CSampleRadioInstance::GetRadioState(_Out_ DEVICE_RADIO_STATE *pRadioState)
+{
+ if (nullptr == pRadioState)
+ {
+ return E_INVALIDARG;
+ }
+
+ DWORD dwRadioState;
+ DEVICE_RADIO_STATE radioState = DRS_RADIO_ON;
+
+ *pRadioState = DRS_RADIO_ON;
+
+ // Read radio state directly from device. we do not save radio state in our module to avoid out of sync
+ DWORD dwError = _hKeyRoot.QueryDWORDValue(s_pszInstanceRadioState, dwRadioState);
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ if ((dwRadioState > DRS_RADIO_MAX) || (dwRadioState == DRS_RADIO_INVALID))
+ {
+ radioState = DRS_HW_RADIO_ON_UNCONTROLLABLE;
+ }
+ else
+ {
+ radioState = static_cast<DEVICE_RADIO_STATE>(dwRadioState);
+ }
+
+ *pRadioState = radioState;
+ }
+
+ return HRESULT_FROM_WIN32(dwError);
+}
+
+
+IFACEMETHODIMP CSampleRadioInstance::SetRadioState(_In_ DEVICE_RADIO_STATE radioState, _In_ UINT32 uTimeoutSec)
+{
+ if ((radioState != DRS_RADIO_ON) && (radioState != DRS_SW_RADIO_OFF))
+ {
+ return E_INVALIDARG; // invalid input
+ }
+
+ DEVICE_RADIO_STATE drsCurrent;
+ bool fRefAdded = false;
+ HRESULT hr = GetRadioState(&drsCurrent);
+
+ // fail to get current radio state or current radio state is uncontrollable
+ if (FAILED(hr) || (drsCurrent & DRS_HW_RADIO_ON_UNCONTROLLABLE))
+ {
+ return E_FAIL;
+ }
+
+ if ((drsCurrent & DRS_SW_RADIO_OFF) == radioState)
+ {
+ return S_OK; // current software radio is same as target software radio
+ }
+
+ // Keep all other bits same, only change the last bit of radio state to represent software radio change
+ DEVICE_RADIO_STATE drsState = static_cast<DEVICE_RADIO_STATE>((drsCurrent & DRS_HW_RADIO_OFF) | radioState);
+
+ CAutoPtr<SET_DEVICE_RADIO_JOB> spSetDeviceRadioJob;
+
+ spSetDeviceRadioJob.Attach(new SET_DEVICE_RADIO_JOB);
+ if (nullptr == spSetDeviceRadioJob)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ spSetDeviceRadioJob->hr = E_FAIL;
+ spSetDeviceRadioJob->drsTarget = drsState;
+ spSetDeviceRadioJob->pInstance = this;
+
+ // Let working thread hold ref on object such that object won't be released before working thread return.
+ this->AddRef();
+ fRefAdded = true;
+
+ HANDLE hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ if (nullptr == hEvent)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else
+ {
+ spSetDeviceRadioJob->hEvent.Attach(hEvent);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (!QueueUserWorkItem(CSampleRadioInstance::s_ThreadSetRadio, spSetDeviceRadioJob, WT_EXECUTEDEFAULT))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ DWORD dwIgnore;
+ hr = CoWaitForMultipleHandles(0,
+ uTimeoutSec * 1000,
+ 1,
+ reinterpret_cast<LPHANDLE>(&(spSetDeviceRadioJob->hEvent)),
+ &dwIgnore);
+ if (RPC_S_CALLPENDING == hr)
+ {
+ spSetDeviceRadioJob.Detach();
+ }
+ else
+ {
+ hr = spSetDeviceRadioJob->hr;
+ }
+ }
+
+ if (fRefAdded)
+ {
+ this->Release();
+ }
+ return hr;
+}
+
+IFACEMETHODIMP_(BOOL) CSampleRadioInstance::IsMultiComm()
+{
+ return _fIsMultiCommDevice ? TRUE : FALSE;
+}
+
+IFACEMETHODIMP_(BOOL) CSampleRadioInstance::IsAssociatingDevice()
+{
+ BOOL fIsAssociatingDevice = FALSE;
+ DWORD dwAssociatingDevice = 0;
+
+ DWORD dwError = _hKeyRoot.QueryDWORDValue(s_pszAssocatingDevice, dwAssociatingDevice);
+
+ // When key read successfully with non zero value, we regard device associating now.
+ if ((ERROR_SUCCESS == dwError) && (0 != dwAssociatingDevice))
+ {
+ fIsAssociatingDevice = TRUE;
+ }
+
+ return fIsAssociatingDevice;
+}
+
+IFACEMETHODIMP CSampleRadioInstance::OnSysRadioChange(_In_ SYSTEM_RADIO_STATE sysRadioState)
+{
+ if ((sysRadioState != SRS_RADIO_ENABLED) && (sysRadioState != SRS_RADIO_DISABLED))
+ {
+ return E_INVALIDARG;
+ }
+
+ DEVICE_RADIO_STATE drsCurrent;
+ DWORD dwError = ERROR_SUCCESS;
+ DEVICE_RADIO_STATE drsTarget = DRS_RADIO_ON;
+ DEVICE_RADIO_STATE drsPrevious = DRS_RADIO_ON;
+ DWORD dwPreviousState;
+ bool fSetRadioState = false;
+
+ HRESULT hr = GetRadioState(&drsCurrent);
+
+ // fail to get current radio state or current radio state is uncontrollable, ignore this call
+ if (FAILED(hr) || (drsCurrent & DRS_HW_RADIO_ON_UNCONTROLLABLE))
+ {
+ return S_OK;
+ }
+
+ if (SRS_RADIO_ENABLED == sysRadioState)
+ {
+ // If device current software radio is already on during system radio enabled,
+ // we ignore the saved previous radio state and do nothing.
+ // radio state will be updated only when current state is off during system radio enabling.
+ if (DRS_RADIO_ON != (drsCurrent & DRS_SW_RADIO_OFF))
+ {
+ // System radio enable, need get previous radio state and set to previous radio state.
+ // If fail to get previous radio state, assume previous radio state is software radio on.
+ dwError = _hKeyRoot.QueryDWORDValue(s_pszPreviousRadioState, dwPreviousState);
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ if ((DRS_RADIO_ON == dwPreviousState) || (DRS_SW_RADIO_OFF == dwPreviousState))
+ {
+ drsPrevious = static_cast<DEVICE_RADIO_STATE>(dwPreviousState);
+ }
+ }
+
+ if ((drsCurrent & DRS_SW_RADIO_OFF) != drsPrevious)
+ {
+ drsTarget = static_cast<DEVICE_RADIO_STATE>((drsCurrent & DRS_HW_RADIO_OFF) | drsPrevious);
+ fSetRadioState = true;
+ }
+ }
+ }
+ else
+ { // System radio disable, need record previous radio state.
+ _hKeyRoot.SetDWORDValue(s_pszPreviousRadioState, static_cast<DWORD>(drsCurrent));
+
+ if ((drsCurrent & DRS_SW_RADIO_OFF) != DRS_SW_RADIO_OFF)
+ {
+ drsTarget = static_cast<DEVICE_RADIO_STATE>((drsCurrent & DRS_HW_RADIO_OFF) | DRS_SW_RADIO_OFF);
+ fSetRadioState = true;
+ }
+ }
+
+ if (fSetRadioState)
+ {
+ dwError = _hKeyRoot.SetDWORDValue(s_pszInstanceRadioState, static_cast<DWORD>(drsTarget));
+ }
+
+ return HRESULT_FROM_WIN32(dwError);
+}
+
+HRESULT CSampleRadioInstance::_SetRadioState(_In_ DEVICE_RADIO_STATE radioState)
+{
+ DWORD dwError = _hKeyRoot.SetDWORDValue(s_pszInstanceRadioState, static_cast<DWORD>(radioState));
+
+ return HRESULT_FROM_WIN32(dwError);
+}
+
+void CSampleRadioInstance::_OnInstanceUpdate()
+{
+ DWORD dwError;
+ DWORD dwRadioState = 0;
+ DEVICE_RADIO_STATE drsCurrent;
+
+ dwError = _hKeyRoot.QueryDWORDValue(s_pszInstanceRadioState, dwRadioState);
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ if ((dwRadioState > DRS_RADIO_MAX) || (dwRadioState == DRS_RADIO_INVALID))
+ {
+ drsCurrent = DRS_HW_RADIO_ON_UNCONTROLLABLE;
+ }
+ else
+ {
+ drsCurrent = static_cast<DEVICE_RADIO_STATE>(dwRadioState);
+ }
+ CComBSTR sbstrID = _strInstanceId.AllocSysString();
+
+ if (nullptr != sbstrID)
+ {
+ _pParentManager->OnInstanceRadioChange(sbstrID, drsCurrent);
+ }
+ }
+}
+
+DWORD WINAPI CSampleRadioInstance::s_ThreadInstanceChange(LPVOID pThis)
+{
+ CSampleRadioInstance *pRadioInstance = reinterpret_cast<CSampleRadioInstance *>(pThis);
+ DWORD dwError = ERROR_SUCCESS;
+
+ {
+ CComCritSecLock<CComAutoCriticalSection> lock(pRadioInstance->_criticalSection);
+ if (pRadioInstance->_fClosing)
+ {
+ dwError = ERROR_APP_INIT_FAILURE;
+ }
+ else
+ {
+ dwError = pRadioInstance->_hKeyRoot.NotifyChangeKeyValue(FALSE,
+ REG_NOTIFY_CHANGE_LAST_SET,
+ pRadioInstance->_hRegChangeEvent,
+ TRUE);
+ }
+ }
+
+ if (ERROR_SUCCESS != dwError)
+ {
+ return dwError;
+ }
+
+
+ while (ERROR_SUCCESS == dwError)
+ {
+ WaitForSingleObject(pRadioInstance->_hRegChangeEvent, INFINITE);
+
+ {
+ CComCritSecLock<CComAutoCriticalSection> lock(pRadioInstance->_criticalSection);
+ if (pRadioInstance->_fClosing)
+ {
+ break;
+ }
+
+ ResetEvent(pRadioInstance->_hRegChangeEvent);
+
+ dwError = pRadioInstance->_hKeyRoot.NotifyChangeKeyValue(FALSE,
+ REG_NOTIFY_CHANGE_LAST_SET,
+ pRadioInstance->_hRegChangeEvent,
+ TRUE);
+ }
+ pRadioInstance->_OnInstanceUpdate();
+ }
+
+ return dwError;
+}
+
+DWORD WINAPI CSampleRadioInstance::s_ThreadSetRadio(LPVOID pThis)
+{
+ SET_DEVICE_RADIO_JOB *pJob = reinterpret_cast<SET_DEVICE_RADIO_JOB *>(pThis);
+
+ pJob->hr = pJob->pInstance->_SetRadioState(pJob->drsTarget);
+
+ SetEvent(pJob->hEvent);
+ return ERROR_SUCCESS;
+}
diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioInstance.h b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.h
new file mode 100644
index 00000000..176aca3c
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.h
@@ -0,0 +1,71 @@
+#pragma once
+
+class ATL_NO_VTABLE CSampleRadioInstance :
+ public CComObjectRootEx<CComMultiThreadModel>,
+ public CComCoClass<CSampleRadioInstance>,
+ public IRadioInstance,
+ public ISampleRadioInstanceInternal
+{
+public:
+ DECLARE_CLASSFACTORY()
+ DECLARE_NOT_AGGREGATABLE(CSampleRadioInstance)
+ DECLARE_NO_REGISTRY()
+
+ BEGIN_COM_MAP(CSampleRadioInstance)
+ COM_INTERFACE_ENTRY(IRadioInstance)
+ COM_INTERFACE_ENTRY(ISampleRadioInstanceInternal)
+ END_COM_MAP()
+
+ CSampleRadioInstance();
+
+ void FinalRelease();
+
+ static HRESULT CreateInstance(
+ _In_ PCWSTR pszKeyName,
+ _In_ ISampleRadioManagerInternal *pParentManager,
+ _COM_Outptr_ ISampleRadioInstanceInternal **pRadioInstance);
+
+ // IRadioInstance
+ IFACEMETHOD(GetRadioManagerSignature)(_Out_ GUID *pguidSignature);
+ IFACEMETHOD(GetInstanceSignature)(_Out_ BSTR *pbstrID);
+ IFACEMETHOD(GetFriendlyName)(_In_ LCID lcid, _Out_ BSTR *pbstrName);
+ IFACEMETHOD(GetRadioState)(_Out_ DEVICE_RADIO_STATE *pRadioState);
+ IFACEMETHOD(SetRadioState)(_In_ DEVICE_RADIO_STATE radioState, _In_ UINT32 uTimeoutSec);
+ IFACEMETHOD_(BOOL, IsMultiComm)();
+ IFACEMETHOD_(BOOL, IsAssociatingDevice)();
+
+ // ISampleRadioInstanceInternal
+ IFACEMETHOD(OnSysRadioChange)(_In_ SYSTEM_RADIO_STATE sysRadioSate);
+
+private:
+ HRESULT _Init(_In_ PCWSTR pszKeyName, _In_ ISampleRadioManagerInternal *pParentManager);
+ void _Cleanup();
+ void _OnInstanceUpdate();
+ HRESULT _SetRadioState(_In_ DEVICE_RADIO_STATE radioState);
+ static DWORD WINAPI s_ThreadInstanceChange(LPVOID pThis);
+ static DWORD WINAPI s_ThreadSetRadio(LPVOID pThis);
+
+ ISampleRadioManagerInternal *_pParentManager;
+ CComAutoCriticalSection _criticalSection;
+ CString _strInstanceId;
+ CString _strInstanceName;
+ bool _fIsMultiCommDevice;
+
+ CHandle _hEventThread;
+ bool _fClosing; // object is closing
+ CHandle _hRegChangeEvent;
+ CRegKey _hKeyRoot;
+ static PCWSTR s_pszInstanceName;
+ static PCWSTR s_pszInstanceRadioState;
+ static PCWSTR s_pszPreviousRadioState;
+ static PCWSTR s_pszMultiComm;
+ static PCWSTR s_pszAssocatingDevice;
+};
+
+typedef struct _SET_DEVICE_RADIO_JOB{
+ HRESULT hr;
+ CHandle hEvent;
+ CSampleRadioInstance *pInstance;
+ DEVICE_RADIO_STATE drsTarget;
+} SET_DEVICE_RADIO_JOB;
+
diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioManager.cpp b/network/radio/RadioManagerSample/cpp/SampleRadioManager.cpp
new file mode 100644
index 00000000..53bc4757
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRadioManager.cpp
@@ -0,0 +1,570 @@
+#include "precomp.h"
+#pragma hdrstop
+
+PCWSTR CSampleRadioManager::s_pszRootKey = L"SYSTEM\\CurrentControlSet\\Control\\RadioManagement\\Misc\\SampleRadioManager";
+
+CSampleRadioManager::CSampleRadioManager()
+ : _fClosing(false)
+{
+}
+
+HRESULT CSampleRadioManager::FinalConstruct()
+{
+ DWORD dwError;
+ HRESULT hr = S_OK;
+ WCHAR szSubKeyName[128];
+ DWORD cchSubKeyName;
+
+ dwError = _hKeyRoot.Open(HKEY_LOCAL_MACHINE, s_pszRootKey, KEY_ALL_ACCESS);
+
+
+ if (ERROR_SUCCESS == dwError)
+ {
+
+ // Enumerate all instances
+ DWORD dwCount = 0;
+ while (true)
+ {
+ cchSubKeyName = ARRAYSIZE(szSubKeyName);
+ dwError = _hKeyRoot.EnumKey(dwCount, szSubKeyName, &cchSubKeyName, NULL);
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ CString strSubKeyName;
+ _ATLTRY
+ {
+ strSubKeyName.Format(L"%s\\%s", s_pszRootKey, szSubKeyName);
+ }
+ _ATLCATCH(e)
+ {
+ hr = e;
+ }
+ if (SUCCEEDED(hr))
+ {
+ hr = _AddInstance(strSubKeyName, nullptr);
+ }
+
+ dwCount++;
+ }
+ else
+ {
+ dwError = ERROR_SUCCESS;
+ break;
+ }
+ }
+
+ }
+
+ // register the regkey subkey add/remove event
+ if (ERROR_SUCCESS == dwError)
+ {
+ HANDLE hRegChangeEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ if (nullptr == hRegChangeEvent)
+ {
+ dwError = GetLastError();
+ }
+ else
+ {
+ _hRegChangeEvent.Attach(hRegChangeEvent);
+ }
+ }
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ HANDLE hThread = ::CreateThread(nullptr,
+ 0,
+ CSampleRadioManager::s_ThreadRegChange,
+ reinterpret_cast<PVOID>(this),
+ 0,
+ nullptr);
+
+ if (nullptr == hThread)
+ {
+ dwError = GetLastError();
+ }
+ else
+ {
+ _hEventThread.Attach(hThread);
+ }
+ }
+
+ hr = HRESULT_FROM_WIN32(dwError);
+
+ if (FAILED(hr))
+ {
+ _Cleanup();
+ }
+
+ return hr;
+}
+
+void CSampleRadioManager::FinalRelease()
+{
+ if ((nullptr != _hRegChangeEvent) && (nullptr != _hEventThread))
+ {
+ {
+ CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection);
+
+ _fClosing = true;
+ SetEvent(_hRegChangeEvent); // inform reg listening thread obj is leaving
+ }
+
+ WaitForSingleObject(_hEventThread, INFINITE); // wait reg listening thread finish
+ }
+
+ _Cleanup();
+}
+
+void CSampleRadioManager::_Cleanup()
+{
+ POSITION p;
+ while (nullptr != (p = _listRadioInstances.GetHeadPosition()))
+ {
+ INSTANCE_LIST_OBJ *pListObj = _listRadioInstances.GetAt(p);
+ if (nullptr != pListObj)
+ {
+ _listRadioInstances.SetAt(p, nullptr);
+ _listRadioInstances.RemoveHeadNoReturn();
+ delete pListObj;
+ }
+ }
+}
+
+IFACEMETHODIMP CSampleRadioManager::GetRadioInstances(_Out_ IRadioInstanceCollection **ppCollection)
+{
+ CAutoVectorPtr<IRadioInstance *> rgpIRadioInstance;
+ HRESULT hr = S_OK;
+ DWORD cInstance;
+
+ if (nullptr == ppCollection)
+ {
+ return E_INVALIDARG;
+ }
+
+ *ppCollection = nullptr;
+
+ CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection);
+ cInstance = static_cast<DWORD>(_listRadioInstances.GetCount());
+ if (cInstance > 0)
+ {
+ if (!rgpIRadioInstance.Allocate(cInstance))
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ if (SUCCEEDED(hr))
+ {
+ ZeroMemory(rgpIRadioInstance, sizeof(rgpIRadioInstance[0]) * cInstance);
+ DWORD dwIndex = 0;
+
+ for (POSITION p = _listRadioInstances.GetHeadPosition(); nullptr != p; _listRadioInstances.GetNext(p))
+ {
+ hr = (_listRadioInstances.GetAt(p))->spRadioInstance.QueryInterface(&(rgpIRadioInstance[dwIndex]));
+ if (FAILED(hr))
+ {
+ break;
+ }
+ else
+ {
+ dwIndex++;
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CRadioInstanceCollection_CreateInstance(cInstance, rgpIRadioInstance, ppCollection);
+ }
+
+ for (DWORD dwIndex = 0; dwIndex < cInstance; dwIndex++)
+ {
+ if (nullptr != rgpIRadioInstance[dwIndex])
+ {
+ rgpIRadioInstance[dwIndex]->Release();
+ }
+ }
+
+ return hr;
+}
+
+IFACEMETHODIMP CSampleRadioManager::OnSystemRadioStateChange(
+ _In_ SYSTEM_RADIO_STATE sysRadioState,
+ _In_ UINT32 uTimeoutSec)
+{
+ HRESULT hr = S_OK;
+ CAutoPtr<SET_SYS_RADIO_JOB> spSetSysRadioJob;
+ bool fRefAdded = false;
+
+ spSetSysRadioJob.Attach(new SET_SYS_RADIO_JOB);
+ if (nullptr == spSetSysRadioJob)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ spSetSysRadioJob->hr = E_FAIL;
+ spSetSysRadioJob->srsTarget = sysRadioState;
+ spSetSysRadioJob->pSampleRM = this;
+
+ // Add ref to object to avoid object release before working thread return
+ this->AddRef();
+ fRefAdded = true;
+
+ HANDLE hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ if (nullptr == hEvent)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else
+ {
+ spSetSysRadioJob->hEvent.Attach(hEvent);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (!QueueUserWorkItem(CSampleRadioManager::s_ThreadSetSysRadio, spSetSysRadioJob, WT_EXECUTEDEFAULT))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ DWORD dwIgnore;
+ hr = CoWaitForMultipleHandles(0,
+ uTimeoutSec * 1000,
+ 1,
+ reinterpret_cast<LPHANDLE>(&(spSetSysRadioJob->hEvent)),
+ &dwIgnore);
+ if (RPC_S_CALLPENDING == hr)
+ {
+ spSetSysRadioJob.Detach();
+ }
+ else
+ {
+ hr = spSetSysRadioJob->hr;
+ }
+ }
+
+ if (fRefAdded)
+ {
+ this->Release();
+ }
+
+ return hr;
+}
+
+IFACEMETHODIMP CSampleRadioManager::OnInstanceRadioChange(
+ _In_ BSTR bstrRadioInstanceID,
+ _In_ DEVICE_RADIO_STATE radioState)
+{
+ return _FireEventOnInstanceRadioChange(bstrRadioInstanceID, radioState);
+}
+
+HRESULT CSampleRadioManager::_FireEventOnInstanceAdd(_In_ IRadioInstance *pRadioInstance)
+{
+ HRESULT hr;
+
+ Lock();
+ for (IUnknown** ppUnkSrc = m_vec.begin(); ppUnkSrc < m_vec.end(); ppUnkSrc++)
+ {
+ if ((nullptr != ppUnkSrc) && (nullptr != *ppUnkSrc))
+ {
+ CComPtr<IMediaRadioManagerNotifySink> spSink;
+
+ hr = (*ppUnkSrc)->QueryInterface(IID_PPV_ARGS(&spSink));
+ if (SUCCEEDED(hr))
+ {
+ spSink->OnInstanceAdd(pRadioInstance);
+ }
+ }
+ }
+ Unlock();
+
+ return S_OK;
+}
+
+HRESULT CSampleRadioManager::_FireEventOnInstanceRemove(_In_ BSTR bstrRadioInstanceID)
+{
+ HRESULT hr;
+
+ Lock();
+ for (IUnknown** ppUnkSrc = m_vec.begin(); ppUnkSrc < m_vec.end(); ppUnkSrc++)
+ {
+ if ((nullptr != ppUnkSrc) && (nullptr != *ppUnkSrc))
+ {
+ CComPtr<IMediaRadioManagerNotifySink> spSink;
+
+ hr = (*ppUnkSrc)->QueryInterface(IID_PPV_ARGS(&spSink));
+ if (SUCCEEDED(hr))
+ {
+ spSink->OnInstanceRemove(bstrRadioInstanceID);
+ }
+ }
+ }
+ Unlock();
+
+ return S_OK;
+}
+
+HRESULT CSampleRadioManager::_FireEventOnInstanceRadioChange(
+ _In_ BSTR bstrRadioInstanceID,
+ _In_ DEVICE_RADIO_STATE radioState
+ )
+{
+ HRESULT hr;
+
+ Lock();
+ for (IUnknown** ppUnkSrc = m_vec.begin(); ppUnkSrc < m_vec.end(); ppUnkSrc++)
+ {
+ if ((nullptr != ppUnkSrc) && (nullptr != *ppUnkSrc))
+ {
+ CComPtr<IMediaRadioManagerNotifySink> spSink;
+
+ hr = (*ppUnkSrc)->QueryInterface(IID_PPV_ARGS(&spSink));
+ if (SUCCEEDED(hr))
+ {
+ spSink->OnInstanceRadioChange(bstrRadioInstanceID, radioState);
+ }
+ }
+ }
+ Unlock();
+
+ return S_OK;
+}
+
+
+HRESULT CSampleRadioManager::_AddInstance(_In_ PCWSTR pszKeyName, _Out_opt_ IRadioInstance **ppRadioInstance)
+{
+ HRESULT hr = S_OK;
+ CComPtr<ISampleRadioInstanceInternal> spRadioInstance;
+ CAutoPtr<INSTANCE_LIST_OBJ> spInstanceObj;
+
+ CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection);
+
+ spInstanceObj.Attach(new INSTANCE_LIST_OBJ);
+ if (nullptr == spInstanceObj)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ CComPtr<ISampleRadioManagerInternal> spRMInternal = this;
+ hr = CSampleRadioInstance_CreateInstance(pszKeyName, spRMInternal, &spRadioInstance);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ spInstanceObj->fExisting = true;
+ spInstanceObj->spRadioInstance = spRadioInstance;
+
+ _ATLTRY
+ {
+ spInstanceObj->strRadioInstanceID = pszKeyName;
+ _listRadioInstances.AddTail(spInstanceObj);
+ spInstanceObj.Detach();
+ }
+ _ATLCATCH(e)
+ {
+ hr = e;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (ppRadioInstance != nullptr)
+ {
+ hr = spRadioInstance->QueryInterface(IID_PPV_ARGS(ppRadioInstance));
+ }
+ }
+ }
+
+ return hr;
+}
+
+void CSampleRadioManager::_OnInstanceAddRemove()
+{
+ DWORD dwError;
+ HRESULT hr= S_OK;
+ WCHAR szSubKeyName[128];
+ DWORD cchSubKeyName;
+ POSITION p;
+
+ // Set all instances as invalid
+ for (p = _listRadioInstances.GetHeadPosition(); p != nullptr; _listRadioInstances.GetNext(p))
+ {
+ INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p);
+ pRadioInstanceObj->fExisting = false;
+ }
+
+ DWORD dwCount = 0;
+ while (true)
+ {
+ cchSubKeyName = ARRAYSIZE(szSubKeyName);
+ dwError = _hKeyRoot.EnumKey(dwCount, szSubKeyName, &cchSubKeyName, NULL);
+
+ if (ERROR_SUCCESS == dwError)
+ {
+ CString strKeyName;
+ _ATLTRY
+ {
+ strKeyName.Format(L"%s\\%s",s_pszRootKey,szSubKeyName);
+ }
+ _ATLCATCH(e)
+ {
+ hr = e;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ for (p = _listRadioInstances.GetHeadPosition(); p != nullptr; _listRadioInstances.GetNext(p))
+ {
+ INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p);
+ if (pRadioInstanceObj->strRadioInstanceID == strKeyName)
+ {
+ break;
+ }
+ }
+
+ // find new instance
+ if (nullptr == p)
+ {
+ CComPtr<IRadioInstance> spRadioInstance;
+ hr = _AddInstance(strKeyName, &spRadioInstance);
+ if(SUCCEEDED(hr))
+ {
+ _FireEventOnInstanceAdd(spRadioInstance);
+ }
+ }
+ else
+ {
+ // The instance still valid.
+ INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p);
+ pRadioInstanceObj->fExisting = true;
+ }
+ }
+
+ dwCount++;
+ }
+ else
+ {
+ dwError = ERROR_SUCCESS;
+ break;
+ }
+ }
+
+ // Remove deleted instance from list
+ p = _listRadioInstances.GetHeadPosition();
+ while (nullptr != p)
+ {
+ INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p);
+ if ((pRadioInstanceObj != nullptr) && !pRadioInstanceObj->fExisting)
+ {
+ POSITION pTmp = p;
+ _listRadioInstances.GetPrev(pTmp);
+
+ _listRadioInstances.RemoveAt(p);
+ CComBSTR bstrTmp = pRadioInstanceObj->strRadioInstanceID.AllocSysString();
+ if (nullptr != bstrTmp)
+ {
+ _FireEventOnInstanceRemove(bstrTmp);
+ }
+ delete pRadioInstanceObj;
+ p = pTmp;
+ }
+
+ if (nullptr != p)
+ {
+ _listRadioInstances.GetNext(p);
+ }
+ else
+ {
+ p = _listRadioInstances.GetHeadPosition();
+ }
+ }
+}
+
+HRESULT CSampleRadioManager::_SetSysRadioState(_In_ SYSTEM_RADIO_STATE sysRadioState)
+{
+ // Since set regkey is fast enough, this implemtation is to set instance radio sequentially.
+ // If set instance radio takes long time and there are multiple instance within one RM,
+ // it is better to do it parallelly.
+ HRESULT hr = S_OK;
+ CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection);
+ for (POSITION p = _listRadioInstances.GetHeadPosition(); nullptr != p; _listRadioInstances.GetNext(p))
+ {
+ INSTANCE_LIST_OBJ *pInstanceObj = _listRadioInstances.GetAt(p);
+ hr = pInstanceObj->spRadioInstance->OnSysRadioChange(sysRadioState);
+ if (FAILED(hr))
+ {
+ break;
+ }
+ }
+ return hr;
+}
+
+DWORD WINAPI CSampleRadioManager::s_ThreadRegChange(LPVOID pThis)
+{
+ CSampleRadioManager *pRadioMgr = reinterpret_cast<CSampleRadioManager *>(pThis);
+ DWORD dwError = ERROR_SUCCESS;
+
+ {
+ CComCritSecLock<CComAutoCriticalSection> lock(pRadioMgr->_criticalSection);
+ if (pRadioMgr->_fClosing)
+ {
+ dwError = ERROR_APP_INIT_FAILURE;
+ }
+ else
+ {
+ dwError = pRadioMgr->_hKeyRoot.NotifyChangeKeyValue(FALSE,
+ REG_NOTIFY_CHANGE_NAME,
+ pRadioMgr->_hRegChangeEvent,
+ TRUE);
+ }
+ }
+
+ if (ERROR_SUCCESS != dwError)
+ {
+ return dwError;
+ }
+
+ while (ERROR_SUCCESS == dwError)
+ {
+ if (WaitForSingleObject(pRadioMgr->_hRegChangeEvent, INFINITE) == WAIT_FAILED)
+ {
+ break;
+ }
+
+ {
+ CComCritSecLock<CComAutoCriticalSection> lock(pRadioMgr->_criticalSection);
+ if (pRadioMgr->_fClosing) // main thread is leaving
+ {
+ break;
+ }
+
+ ResetEvent(pRadioMgr->_hRegChangeEvent);
+
+ dwError = pRadioMgr->_hKeyRoot.NotifyChangeKeyValue(FALSE,
+ REG_NOTIFY_CHANGE_NAME,
+ pRadioMgr->_hRegChangeEvent,
+ TRUE);
+ }
+ // Receive reg subkey add/remove event. update list
+ pRadioMgr->_OnInstanceAddRemove();
+ }
+
+ return dwError;
+}
+
+DWORD WINAPI CSampleRadioManager::s_ThreadSetSysRadio(LPVOID pThis)
+{
+ SET_SYS_RADIO_JOB *pJob = reinterpret_cast<SET_SYS_RADIO_JOB *>(pThis);
+
+ pJob->hr = pJob->pSampleRM->_SetSysRadioState(pJob->srsTarget);
+
+ SetEvent(pJob->hEvent);
+ return ERROR_SUCCESS;
+}
+
diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioManager.h b/network/radio/RadioManagerSample/cpp/SampleRadioManager.h
new file mode 100644
index 00000000..a39673ed
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/SampleRadioManager.h
@@ -0,0 +1,79 @@
+#pragma once
+
+typedef struct {
+ CString strRadioInstanceID;
+ bool fExisting;
+ CComPtr<ISampleRadioInstanceInternal> spRadioInstance;
+} INSTANCE_LIST_OBJ;
+
+EXTERN_C const IID IID_IMediaRadioManagerNotifySink;
+
+class ATL_NO_VTABLE CSampleRadioManager :
+ public CComObjectRootEx<CComMultiThreadModel>,
+ public CComCoClass<CSampleRadioManager, &CLSID_SampleRadioManager>,
+ public IConnectionPointContainerImpl<CSampleRadioManager>,
+ public IConnectionPointImpl<CSampleRadioManager, &IID_IMediaRadioManagerNotifySink>,
+ public IMediaRadioManager,
+ public ISampleRadioManagerInternal
+{
+public:
+
+ DECLARE_CLASSFACTORY()
+ DECLARE_NOT_AGGREGATABLE(CSampleRadioManager)
+
+ DECLARE_NO_REGISTRY()
+
+ BEGIN_COM_MAP(CSampleRadioManager)
+ COM_INTERFACE_ENTRY(IMediaRadioManager)
+ COM_INTERFACE_ENTRY(ISampleRadioManagerInternal)
+ COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
+ END_COM_MAP()
+
+ BEGIN_CONNECTION_POINT_MAP(CSampleRadioManager)
+ CONNECTION_POINT_ENTRY(IID_IMediaRadioManagerNotifySink)
+ END_CONNECTION_POINT_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ CSampleRadioManager();
+
+ HRESULT FinalConstruct();
+ void FinalRelease();
+
+ // IMediaRadioManager interface
+ IFACEMETHOD(GetRadioInstances)(_Out_ IRadioInstanceCollection **ppCollection);
+ IFACEMETHOD(OnSystemRadioStateChange)(_In_ SYSTEM_RADIO_STATE sysRadioState, _In_ UINT32 uTimeoutSec);
+
+ // ISampleRadioManagerInternal interface
+ IFACEMETHOD(OnInstanceRadioChange)(_In_ BSTR bstrRadioInstanceID, _In_ DEVICE_RADIO_STATE radioState);
+
+private:
+ HRESULT _FireEventOnInstanceAdd(_In_ IRadioInstance *pRadioInstance);
+ HRESULT _FireEventOnInstanceRemove(_In_ BSTR bstrRadioInstanceID);
+ HRESULT _FireEventOnInstanceRadioChange(_In_ BSTR bstrRadioInstanceID, _In_ DEVICE_RADIO_STATE radioState);
+
+ void _Cleanup();
+ HRESULT _AddInstance(_In_ PCWSTR pszKeyName, _Out_opt_ IRadioInstance **ppRadioInstance);
+ void _OnInstanceAddRemove();
+ HRESULT _SetSysRadioState(_In_ SYSTEM_RADIO_STATE sysRadioState);
+ static DWORD WINAPI s_ThreadRegChange(LPVOID pThis);
+ static DWORD WINAPI s_ThreadSetSysRadio(LPVOID pThis);
+
+ CComAutoCriticalSection _criticalSection;
+ CAtlList<INSTANCE_LIST_OBJ *> _listRadioInstances;
+
+ CRegKey _hKeyRoot;
+ CHandle _hRegChangeEvent;
+ CHandle _hEventThread;
+ bool _fClosing; // object is closing
+
+ static PCWSTR s_pszRootKey;
+};
+
+typedef struct _SET_SYS_RADIO_JOB{
+ HRESULT hr;
+ CHandle hEvent;
+ CSampleRadioManager *pSampleRM;
+ SYSTEM_RADIO_STATE srsTarget;
+} SET_SYS_RADIO_JOB;
+
diff --git a/network/radio/RadioManagerSample/cpp/dllmain.cpp b/network/radio/RadioManagerSample/cpp/dllmain.cpp
new file mode 100644
index 00000000..61d6898b
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/dllmain.cpp
@@ -0,0 +1,57 @@
+#include "precomp.h"
+#pragma hdrstop
+
+OBJECT_ENTRY_AUTO(__uuidof(SampleRadioManager), CSampleRadioManager);
+
+class CSampleRadioModule : public CAtlDllModuleT<CSampleRadioModule>
+{
+public:
+};
+
+static CSampleRadioModule s_AtlModule;
+
+//+---------------------------------------------------------------------------
+// DLL Entry Point
+//
+
+EXTERN_C BOOL WINAPI DllMain
+(
+ HINSTANCE /*hInstance*/,
+ DWORD dwReason,
+ LPVOID pvReserved
+)
+{
+ return s_AtlModule.DllMain(dwReason, pvReserved);
+}
+
+STDAPI DllCanUnloadNow(void)
+{
+ return s_AtlModule.DllCanUnloadNow();
+}
+
+STDAPI DllGetClassObject(
+ _In_ REFCLSID rclsid,
+ _In_ REFIID riid,
+ _Outptr_ LPVOID* ppv
+ )
+{
+ return s_AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+//+---------------------------------------------------------------------------
+// Adds entries to the system registry. Needed because the binary need copy to test machine.
+// If binary is deployed by manifest, these functions are not needed.
+STDAPI
+DllRegisterServer ()
+{
+ s_AtlModule.DllRegisterServer(FALSE);
+ return S_OK;
+}
+
+STDAPI
+DllUnregisterServer ()
+{
+ HRESULT hr = s_AtlModule.DllUnregisterServer();
+ return hr;
+}
diff --git a/network/radio/RadioManagerSample/cpp/precomp.h b/network/radio/RadioManagerSample/cpp/precomp.h
new file mode 100644
index 00000000..346a3fe6
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/precomp.h
@@ -0,0 +1,17 @@
+#include <windows.h>
+#include <Winreg.h>
+
+// ATL includes
+#include <ATLBase.h>
+#include <ATLCom.h>
+#include <ATLColl.h>
+#include <ATLStr.h>
+
+
+// radio mamanager includes
+#include "RadioMgr.h"
+#include "SampleRM.h"
+#include "internalInterfaces.h"
+#include "SampleRadioInstance.h"
+#include "SampleInstanceCollection.h"
+#include "SampleRadioManager.h"
diff --git a/network/radio/RadioManagerSample/cpp/precompsrc.cpp b/network/radio/RadioManagerSample/cpp/precompsrc.cpp
new file mode 100644
index 00000000..5944cf51
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/precompsrc.cpp
@@ -0,0 +1 @@
+#include "precomp.h" \ No newline at end of file
diff --git a/network/radio/RadioManagerSample/cpp/sampleRM.idl b/network/radio/RadioManagerSample/cpp/sampleRM.idl
new file mode 100644
index 00000000..64ec3fc5
--- /dev/null
+++ b/network/radio/RadioManagerSample/cpp/sampleRM.idl
@@ -0,0 +1,21 @@
+import "oaidl.idl";
+import "RadioMgr.idl";
+
+[
+ uuid(4BE52AA0-EF10-420F-9341-681FBCCD772C),
+ version(1.0),
+ helpstring("Sample Radio Manager library")
+]
+library SampleRadioManagerLib
+{
+ importlib("stdole2.tlb");
+
+ [
+ uuid(41DC5063-AFAF-47DF-86B3-4B2ED82A82CF),
+ helpstring("Sample Media Radio Manager")
+ ]
+ coclass SampleRadioManager
+ {
+ [default] interface IMediaRadioManager;
+ }
+}