diff options
| author | Dave Wilson <[email protected]> | 2015-04-29 09:48:49 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-04-29 10:47:29 -0700 |
| commit | d40232638faaab19de557e70a3ee938da7a35295 (patch) | |
| tree | 14e61c973745949af186b7940e3a53d25322f5de /network/radio/RadioManagerSample/cpp | |
| parent | 02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff) | |
samples update for //build
Diffstat (limited to 'network/radio/RadioManagerSample/cpp')
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; + } +} |
