333 lines
8.8 KiB
C++
333 lines
8.8 KiB
C++
|
#include "pch.h"
|
||
|
#pragma hdrstop
|
||
|
#include "api.h"
|
||
|
#include "upnphost.h"
|
||
|
#include "CInternetGatewayDevice.h"
|
||
|
#include "beaconrc.h"
|
||
|
|
||
|
HRESULT BeaconEnabled(void);
|
||
|
|
||
|
static const WCHAR c_szSharedAccessClientKeyPath[] = L"System\\CurrentControlSet\\Control\\Network\\SharedAccessConnection";
|
||
|
static BSTR g_DeviceId = NULL;
|
||
|
static BOOL g_bStarted = FALSE;
|
||
|
static INATEventsSink* g_pNATEventsSink;
|
||
|
|
||
|
CRITICAL_SECTION g_RegistrationProtection;
|
||
|
CRITICAL_SECTION g_NATEventsProtection;
|
||
|
|
||
|
HRESULT GetXMLPath(BSTR* pPath)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
*pPath = NULL;
|
||
|
|
||
|
WCHAR szXMLDirectory[] = L"ICSXML";
|
||
|
WCHAR szSystemDirectory[MAX_PATH + 1 + (sizeof(szXMLDirectory) / sizeof(WCHAR))];
|
||
|
UINT uiSize = GetSystemDirectory(szSystemDirectory, MAX_PATH);
|
||
|
if(0 != uiSize)
|
||
|
{
|
||
|
if(L'\\' != szSystemDirectory[uiSize])
|
||
|
{
|
||
|
szSystemDirectory[uiSize] = L'\\';
|
||
|
uiSize++;
|
||
|
}
|
||
|
|
||
|
lstrcpy(&szSystemDirectory[uiSize], szXMLDirectory);
|
||
|
*pPath = SysAllocString(szSystemDirectory);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT GetDescriptionDocument(INT nResource, BSTR* pDocument)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
*pDocument = NULL;
|
||
|
|
||
|
HRSRC hrsrc = FindResource(_Module.GetResourceInstance(), MAKEINTRESOURCE(nResource), L"XML"); // REVIEW change this from 1
|
||
|
if(hrsrc)
|
||
|
{
|
||
|
HGLOBAL hGlobal = LoadResource(_Module.GetResourceInstance(), hrsrc);
|
||
|
if(hGlobal)
|
||
|
{
|
||
|
void* pvData = LockResource(hGlobal);
|
||
|
if(pvData)
|
||
|
{
|
||
|
long nLength = SizeofResource(_Module.GetResourceInstance(), hrsrc);
|
||
|
WCHAR * sz = new WCHAR[nLength + 1];
|
||
|
if(NULL != sz)
|
||
|
{
|
||
|
if(0 != MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, reinterpret_cast<char*>(pvData), nLength, sz, nLength))
|
||
|
{
|
||
|
sz[nLength] = 0;
|
||
|
*pDocument = SysAllocString(sz);
|
||
|
if(NULL != *pDocument)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
delete [] sz;
|
||
|
}
|
||
|
}
|
||
|
FreeResource(hGlobal);
|
||
|
}
|
||
|
}
|
||
|
return hr;
|
||
|
|
||
|
}
|
||
|
|
||
|
HRESULT WINAPI InitializeBeaconSvr()
|
||
|
{
|
||
|
__try
|
||
|
{
|
||
|
InitializeCriticalSection(&g_RegistrationProtection);
|
||
|
InitializeCriticalSection(&g_NATEventsProtection);
|
||
|
} __except(EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT WINAPI TerminateBeaconSvr()
|
||
|
{
|
||
|
DeleteCriticalSection(&g_RegistrationProtection);
|
||
|
DeleteCriticalSection(&g_NATEventsProtection);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT WINAPI StartBeaconSvr(void)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&g_RegistrationProtection);
|
||
|
|
||
|
g_bStarted = TRUE;
|
||
|
|
||
|
if(NULL == g_DeviceId)
|
||
|
{
|
||
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); // Ensure we are in the MTA
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = BeaconEnabled();
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
IUPnPRegistrar* pRegistrar;
|
||
|
hr = CoCreateInstance(CLSID_UPnPRegistrar, NULL, CLSCTX_SERVER, IID_IUPnPRegistrar, reinterpret_cast<void**>(&pRegistrar));
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
|
||
|
CComObject<CInternetGatewayDevice>* pGatewayDevice;
|
||
|
hr = CComObject<CInternetGatewayDevice>::CreateInstance(&pGatewayDevice);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
pGatewayDevice->AddRef();
|
||
|
|
||
|
BSTR bstrData;
|
||
|
hr = GetDescriptionDocument(NCM_LAN == pGatewayDevice->m_pWANCommonInterfaceConfigService->m_MediaType ? IDXML_LAN : IDXML_RAS, &bstrData);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
BSTR bstrInitString = SysAllocString(L"Init");
|
||
|
if(NULL != bstrInitString)
|
||
|
{
|
||
|
BSTR pPath;
|
||
|
hr = GetXMLPath(&pPath);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pRegistrar->RegisterRunningDevice(bstrData, static_cast<IUPnPDeviceControl*>(pGatewayDevice), bstrInitString, pPath, 1800, &g_DeviceId);
|
||
|
|
||
|
SysFreeString(pPath);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
SysFreeString(bstrInitString);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
SysFreeString(bstrData);
|
||
|
}
|
||
|
pGatewayDevice->Release();
|
||
|
}
|
||
|
pRegistrar->Release();
|
||
|
}
|
||
|
}
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&g_RegistrationProtection);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT WINAPI SignalBeaconSvr(void)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
// go ahead and dump the whole object since the services need for the client are different.
|
||
|
|
||
|
if(TRUE == g_bStarted)
|
||
|
{
|
||
|
hr = StopBeaconSvr();
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = StartBeaconSvr();
|
||
|
}
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT WINAPI StopBeaconSvr(void)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
IUPnPRegistrar* pRegistrar;
|
||
|
|
||
|
|
||
|
EnterCriticalSection(&g_RegistrationProtection);
|
||
|
|
||
|
if(NULL != g_DeviceId)
|
||
|
{
|
||
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); // Ensure we are in the MTA
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CoCreateInstance(CLSID_UPnPRegistrar, NULL, CLSCTX_SERVER, IID_IUPnPRegistrar, reinterpret_cast<void**>(&pRegistrar));
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pRegistrar->UnregisterDevice(g_DeviceId, TRUE);
|
||
|
pRegistrar->Release();
|
||
|
}
|
||
|
SysFreeString(g_DeviceId);
|
||
|
|
||
|
g_DeviceId = NULL;
|
||
|
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
g_bStarted = FALSE;
|
||
|
|
||
|
LeaveCriticalSection(&g_RegistrationProtection);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT BeaconEnabled(void)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
HKEY hKey;
|
||
|
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szSharedAccessClientKeyPath, NULL, KEY_QUERY_VALUE, &hKey))
|
||
|
{
|
||
|
DWORD dwType;
|
||
|
DWORD dwValue;
|
||
|
DWORD dwSize = sizeof(dwValue);
|
||
|
if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"DisableBeacon", NULL, &dwType, reinterpret_cast<LPBYTE>(&dwValue), &dwSize))
|
||
|
{
|
||
|
if(REG_DWORD == dwType && 0 != dwValue)
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
// This function must be called on an MTA thread
|
||
|
HRESULT AdviseNATEvents(INATEventsSink* pNATEventsSink)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
if(NULL == g_pNATEventsSink)
|
||
|
{
|
||
|
g_pNATEventsSink = pNATEventsSink;
|
||
|
g_pNATEventsSink->AddRef();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// This function must be called on an MTA thread
|
||
|
HRESULT UnadviseNATEvents(INATEventsSink* pNatEventsSink)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
if(NULL != g_pNATEventsSink)
|
||
|
{
|
||
|
g_pNATEventsSink->Release();
|
||
|
g_pNATEventsSink = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT WINAPI FireNATEvent_PublicIPAddressChanged(void)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); // Ensure we are in the MTA
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
if(NULL != g_pNATEventsSink)
|
||
|
{
|
||
|
g_pNATEventsSink->PublicIPAddressChanged();
|
||
|
}
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT WINAPI FireNATEvent_PortMappingsChanged(void)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE); // Ensure we are in the MTA
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
if(NULL != g_pNATEventsSink)
|
||
|
{
|
||
|
g_pNATEventsSink->PortMappingsChanged();
|
||
|
}
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&g_NATEventsProtection);
|
||
|
|
||
|
return hr;
|
||
|
}
|