windows-nt/Source/XPSP1/NT/net/homenet/beacon/server/api.cpp
2020-09-26 16:20:57 +08:00

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;
}