summaryrefslogtreecommitdiff
path: root/network/radio/RadioManagerSample
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
parent02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff)
samples update for //build
Diffstat (limited to 'network/radio/RadioManagerSample')
-rw-r--r--network/radio/RadioManagerSample/RadioManagerSample.sln28
-rw-r--r--network/radio/RadioManagerSample/ReadMe.md171
-rw-r--r--network/radio/RadioManagerSample/SampleRM.regbin0 -> 1982 bytes
-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
-rw-r--r--network/radio/RadioManagerSample/install.cmd3
-rw-r--r--network/radio/RadioManagerSample/readme.txt192
22 files changed, 2437 insertions, 0 deletions
diff --git a/network/radio/RadioManagerSample/RadioManagerSample.sln b/network/radio/RadioManagerSample/RadioManagerSample.sln
new file mode 100644
index 00000000..d5d0a144
--- /dev/null
+++ b/network/radio/RadioManagerSample/RadioManagerSample.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleRM", "cpp\SampleRM.vcxproj", "{165D39D6-68AC-4E1F-89ED-483E13E84F9B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|Win32.Build.0 = Debug|Win32
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|Win32.ActiveCfg = Release|Win32
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|Win32.Build.0 = Release|Win32
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|x64.ActiveCfg = Debug|x64
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|x64.Build.0 = Debug|x64
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|x64.ActiveCfg = Release|x64
+ {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/network/radio/RadioManagerSample/ReadMe.md b/network/radio/RadioManagerSample/ReadMe.md
new file mode 100644
index 00000000..4c481bbd
--- /dev/null
+++ b/network/radio/RadioManagerSample/ReadMe.md
@@ -0,0 +1,171 @@
+Windows Radio Management Sample
+===============================
+
+The Radio Manager sample demonstrates how to structure a Radio Manager for use with the Windows 8.1 Radio Management APIs.
+
+Starting with Windows 8.1, the operating system contains a set of APIs which are used as a software mechanism to control the various radios found on the machine. The APIs work by communicating with a Radio Manager, which is a COM object that relays commands from the APIs to turn the radio on or off, and reports back radio information to the APIs. This feature is designed in such a way that a separate Radio Manager is required for each radio media type. For example, a WLAN radio will be controlled by a different Radio Manager than a GPS radio. If there are 2 WLAN radios and a GPS radio, the 2 WLAN radios will be controlled by one Radio Manager, and the GPS radio will be controlled by a different Radio Manager. The Radio Manager must be able to run correctly within Local Service Account context. Under this context, the Radio Manager will have the minimum privilege on the local computer.
+
+When the user turns the radio off (either by using the specific radio software switch or the airplane mode switch), radio transmission must be turned off. The device can be powered off as long as the radio switch does not disappear from the UI. It is very important that the radio manager developer ensures that when the device is powered off, the radio switch does not disappear from the UI. If the radio switch disappears from the UI when the radio is turned off by the user, then user has no way to turn the radio back on! If it is desired to conserve power by cutting power to the device when the radio is turned off, but the device cannot be completely powered off because it disappears from the UI, then the solution would be to put the device in a low power state (e.g. D3).
+
+**Important**  The radio manager MUST be given a name. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
+
+
+Installation
+------------
+
+The sample contains a script, *install.cmd*, which copies the radio manager DLL to the system directory, registers as a COM component, and configures the registry.
+
+Copy the *install.cmd*, *SampleRM.reg* and *SampleRM.dll* files to a directory. Run *install.cmd*.
+
+Code Tour
+---------
+
+File
+
+Description
+
+install.cmd
+
+Installation script. Copies and registers the dll and executes SampleRM.reg.
+
+SampleRM.reg
+
+script to install the Sample Radio Manager into the registry, along with 2 radio instances.
+
+SampleRM.sln
+
+The Visual Studio solution file for building the Sample Radio Manager dll.
+
+sampleRM.idl
+
+The interface definition for the Sample Radio Manager.
+
+RadioMgr.idl
+
+The interface definition for a Windows Radio Manager.
+
+SampleRadioManager.h
+
+Header file for the functions required for a Radio Manager.
+
+SampleRadioInstance.h
+
+Header file for the functions required for a Radio Instance.
+
+SampleInstanceCollection.h
+
+Header file for the functions required for a Collection of Radio Instances.
+
+precomp.h
+
+Common header file.
+
+InternalInterfaces.h
+
+Header file for internal interface used for this sample.
+
+dllmain.cpp
+
+Standard dllmain.
+
+SampleRadioManager.cpp
+
+Implementation details for the Sample Radio Manager. Important concepts include:
+
+- Utilizing [IMediaRadioManagerNotifySink](http://msdn.microsoft.com/en-us/library/windows/hardware/hh406534) for radio instance events
+- Adding/Removing radio instances
+- Queuing and deploying worker jobs for system events
+
+SampleRadioInstance.cpp
+
+Implementation details for the Sample Radio Instance. Important concepts include:
+
+- Accessors & Modifiers for radio information
+- Instance change functions
+
+SampleInstanceCollection.cpp
+
+Implementation details for the Sample Instance Collection. Important concepts include:l
+
+- Radio Instance discovery and retrieval
+
+RadioMgr\_interface.cpp
+
+Helper source file to include the MIDL-generated files.
+
+Run the sample
+--------------
+
+Operation
+---------
+
+This sample Radio Manager does not operate on an actual radio. Instead, it uses registry keys to act as virtual radios.
+
+Each "radio" instance can have the following values:
+
+Name
+
+RadioState
+
+PreviousRadioState
+
+IsMultiComm
+
+IsAssociatingDevice
+
+\*\*\* It is required that the registry key has AT LEAST a Name value, otherwise the Sample Radio Manager will fail to initialize. \*\*\*
+
+**Important**  The radio manager must be given a name and the registry key must have, as a minimum, a Name value. Otherwise, the Sample Radio Manager will fail to initialize. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
+
+When the Radio Manager is initialized, it uses these registry keys to retrieve the "radio" information. The radio state values can be any of the following enum values:
+
+<table>
+<colgroup>
+<col width="100%" />
+</colgroup>
+<thead>
+<tr class="header">
+<th align="left">C++</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td align="left"><pre><code>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;</code></pre></td>
+</tr>
+</tbody>
+</table>
+
+For IsMultiComm and IsAssociatingDevice, a value of 0 means 'no' and 1 means 'yes'.
+
+Adding and Setting a Radio Instance
+-----------------------------------
+
+To add a new radio instance, add a new instance key to the registry key like the following entry:
+
+``` {.syntax xml:space="preserve"}
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\RadioManagement\Misc\SampleRadioManager\SampleRadioX]
+"RadioState"=dword:00000000
+"Name"="SampleRadioX"
+"IsMultiComm"=dword:00000000
+```
+
+Editing a Radio Instance
+------------------------
+
+Simply change the values in the registry. For example, change the radio state from DRS\_RADIO\_ON to DRS\_SW\_RADIO\_OFF by changing the 'RadioState' value from 0 to 1.
+
+Removing a Radio Instance
+-------------------------
+
+Delete the corresponding registry key.
+
diff --git a/network/radio/RadioManagerSample/SampleRM.reg b/network/radio/RadioManagerSample/SampleRM.reg
new file mode 100644
index 00000000..3ba004f1
--- /dev/null
+++ b/network/radio/RadioManagerSample/SampleRM.reg
Binary files differ
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;
+ }
+}
diff --git a/network/radio/RadioManagerSample/install.cmd b/network/radio/RadioManagerSample/install.cmd
new file mode 100644
index 00000000..59b84572
--- /dev/null
+++ b/network/radio/RadioManagerSample/install.cmd
@@ -0,0 +1,3 @@
+copy SampleRM.dll %windir%\system32\
+regsvr32 SampleRM.dll
+SampleRM.reg
diff --git a/network/radio/RadioManagerSample/readme.txt b/network/radio/RadioManagerSample/readme.txt
new file mode 100644
index 00000000..2bdd69bd
--- /dev/null
+++ b/network/radio/RadioManagerSample/readme.txt
@@ -0,0 +1,192 @@
+Sample Radio Manager
+====================
+Demonstrates how to structure a Radio Manager for use with the Windows 8 Radio Management APIs.
+
+On Windows 8 and later, the operating system contains a set of APIs which are used as a software mechanism
+to control the various radios found on the machine. The APIs work by communicating with a Radio Manager,
+which is a COM object that relays commands from the APIs to turn the radio on or off, and reports back
+radio information to the APIs. This feature is designed in such a way that a separate Radio Manager is
+required for each radio media type. For example, a WLAN radio will be controlled by a different Radio
+Manager than a GPS radio. If there are 2 WLAN radios and a GPS radio, the 2 WLAN radios will be controlled
+by one Radio Manager, and the GPS radio will be controlled by a different Radio Manager. The Radio Manager
+must be able to run correctly within Local Service Account context. Under this context, the Radio Manager
+will have the minimum privilege on the local computer.
+
+When the user turns the radio off (either by using the specific radio software switch or the airplane mode switch),
+radio transmission must be turned off. The device can be powered off as long as the radio switch does not disappear
+from the UI. It is very important that the radio manager developer ensures that when the device is powered off, the
+radio switch does not disappear from the UI. If the radio switch disappears from the UI when the radio is turned off
+by the user, then user has no way to turn the radio back on! If it is desired to conserve power by cutting power to
+the device when the radio is turned off, but the device cannot be completely powered off because it disappears from
+the UI, then the solution would be to put the device in a low power state (e.g. D3).
+
+IMPORTANT! The radio manager must be given a name � this is the name of the radio switch that is displayed to the
+user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example,
+for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should
+be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's
+name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
+
+
+
+Sample Language Implementations
+===============================
+This sample is available in the following language implementations:
+ C++
+
+
+Installation Files
+==================
+install.cmd
+- Installation script. Copies and registers the dll and executes SampleRM.reg
+
+SampleRM.reg
+- script to install the Sample Radio Manager into the registry, along with 2 radio instances
+
+
+Source Files
+============
+SampleRM.sln
+- The Visual Studio 2010 solution file for building the Sample Radio Manager dll
+
+sampleRM.idl
+- The interface definition for the Sample Radio Manager
+
+RadioMgr.idl
+- The interface definition for a Windows Radio Manager
+
+SampleRadioManager.h
+- Header file for the functions required for a Radio Manager
+
+SampleRadioInstance.h
+- Header file for the functions required for a Radio Instance
+
+SampleInstanceCollection.h
+- Header file for the functions required for a Collection of Radio Instances
+
+precomp.h
+- Common header file
+
+InternalInterfaces.h
+- Header file for internal interface used for this sample
+
+dllmain.cpp
+- Standard dllmain
+
+SampleRadioManager.cpp
+- Implementation details for the Sample Radio Manager. Important concepts include:
+ - Utilizing IMediaRadioManagerNotifySink for radio instance events
+ - Adding/Removing radio instances
+ - Queuing and deploying worker jobs for system events
+
+SampleRadioInstance.cpp
+- Implementation details for the Sample Radio Instance. Important concepts include:
+ - Accessors & Modifiers for radio information
+ - Instance change functions
+
+SampleInstanceCollection.cpp
+- Implementation details for the Sample Instance Collection. Important concepts include:
+ - Radio Instance discovery and retrieval
+
+RadioMgr_interface.cpp
+- Helper source file to include the MIDL-generated files.
+
+
+How the sample works
+====================
+This sample Radio Manager does not operate on an actual radio. Instead, it uses registry keys to act as
+virtual radios. Each "radio" instance can have the following values:
+ -Name
+ -RadioState
+ -PreviousRadioState
+ -IsMultiComm
+ -IsAssociatingDevice
+
+***It is required that the registry key has AT LEAST a Name value, otherwise the Sample Radio Manager will
+fail to initialize***
+
+IMPORTANT! The radio manager must be given a name � this is the name of the radio switch that is displayed to the
+user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example,
+for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should
+be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's
+name or some other word related to the functionality of the radio (e.g. "Location" OR "port").
+
+
+When the Radio Manager is initialized, it uses these registry keys to retrieve the "radio" information.
+The radio state values can be any of the following enum values:
+
+ 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;
+
+For IsMultiComm and IsAssociatingDevice, a value of 0 means 'no' and 1 means 'yes.
+
+
+To Add a Radio Instance
+=======================
+Add a new item to the registry:
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\RadioManagement\Misc\SampleRadioManager\SampleRadioX]
+"RadioState"=dword:00000000
+"Name"="SampleRadioX"
+"IsMultiComm"=dword:00000000
+
+To Edit a Radio Instance
+========================
+Simply change the values in the registry. For example, change the radio state from DRS_RADIO_ON to DRS_SW_RADIO_OFF
+by changing the 'RadioState' value from 0 to 1.
+
+
+To Remove a Radio Instance
+==========================
+Delete the corresponding registry key.
+
+
+Prerequisites for viewing and building solution
+===============================================
+1. Windows 7
+2. Visual Studio 2010
+
+
+To build the sample using Visual Studio 2010 (preferred method):
+===============================================================
+1. Open File Explorer and navigate to the directory.
+2. Double-click the icon for the SampleRM.sln (solution) file to open the file in Visual Studio.
+3. In the Build menu, select Build Solution. The dll will be built in the default \Debug or \Release directory
+
+
+Prerequisites for installing Radio Manager
+==========================================
+1. Windows 8
+2. The VC++ 2010 Redistributable package must be installed for this dll to load.
+
+
+Installing Radio Manager
+========================
+1. Copy the install.cmd, SampleRM.reg and SampleRM.dll files to a directory
+2. Run install.cmd
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+