mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
696 lines
18 KiB
696 lines
18 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 2000.
|
|
//
|
|
// File: A N N O U N C E . C P P
|
|
//
|
|
// Contents: SSDP Announcement list
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: mbend 8 Nov 2000
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.h>
|
|
#pragma hdrstop
|
|
|
|
#include "announce.h"
|
|
#include "search.h"
|
|
#include "ssdpfunc.h"
|
|
#include "ssdpnetwork.h"
|
|
#include "ncbase.h"
|
|
#include "upthread.h"
|
|
|
|
#define BUF_SIZE 40
|
|
|
|
HRESULT HrInitializeSsdpRequestFromMessage(
|
|
SSDP_REQUEST * pRequest,
|
|
const SSDP_MESSAGE *pMsg);
|
|
|
|
static LIST_ENTRY listAnnounce;
|
|
CRITICAL_SECTION CSListAnnounce;
|
|
static CHAR *AliveHeader = "ssdp:alive";
|
|
static CHAR *ByebyeHeader = "ssdp:byebye";
|
|
static CHAR *MulticastUri = "*";
|
|
|
|
static const DWORD c_dwUPnPMajorVersion = 1;
|
|
static const DWORD c_dwUPnPMinorVersion = 0;
|
|
static const DWORD c_dwHostMajorVersion = 1;
|
|
static const DWORD c_dwHostMinorVersion = 0;
|
|
|
|
CSsdpService::CSsdpService() : m_timer(*this)
|
|
{
|
|
ZeroMemory(&m_ssdpRequest, sizeof(m_ssdpRequest));
|
|
}
|
|
|
|
CSsdpService::~CSsdpService()
|
|
{
|
|
FreeSsdpRequest(&m_ssdpRequest);
|
|
}
|
|
|
|
PCONTEXT_HANDLE_TYPE * CSsdpService::GetContext()
|
|
{
|
|
return m_ppContextHandle;
|
|
}
|
|
|
|
BOOL CSsdpService::FIsUsn(const char * szUsn)
|
|
{
|
|
BOOL bMatch = FALSE;
|
|
if(m_ssdpRequest.Headers[SSDP_USN])
|
|
{
|
|
if(0 == lstrcmpA(m_ssdpRequest.Headers[SSDP_USN], szUsn))
|
|
{
|
|
bMatch = TRUE;
|
|
}
|
|
}
|
|
return bMatch;
|
|
}
|
|
|
|
void CSsdpService::OnRundown(CSsdpService * pService)
|
|
{
|
|
CSsdpServiceManager::Instance().HrServiceRundown(pService);
|
|
}
|
|
|
|
void CSsdpService::TimerFired()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
char * szAlive = NULL;
|
|
hr = m_strAlive.HrGetMultiByteWithAlloc(&szAlive);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
GetNetworkLock();
|
|
SendOnAllNetworks(szAlive, NULL);
|
|
FreeNetworkLock();
|
|
delete [] szAlive;
|
|
|
|
// Repeat three times
|
|
--m_nRetryCount;
|
|
if(0 == m_nRetryCount)
|
|
{
|
|
// To-Do: The current limit on life time is 49.7 days. (32 bits in milliseconds)
|
|
// 32 bit in seconds should be enough.
|
|
// Need to add field remaining time ...
|
|
|
|
m_nRetryCount = 3;
|
|
|
|
long nTimeout = m_nLifetime * 1000/2 - 2 * (RETRY_INTERVAL * (NUM_RETRIES - 1));
|
|
|
|
hr = m_timer.HrSetTimerInFired(nTimeout);
|
|
}
|
|
else
|
|
{
|
|
hr = m_timer.HrSetTimerInFired(RETRY_INTERVAL);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::TimerFired");
|
|
}
|
|
|
|
BOOL CSsdpService::TimerTryToLock()
|
|
{
|
|
return m_critSec.FTryEnter();
|
|
}
|
|
|
|
void CSsdpService::TimerUnlock()
|
|
{
|
|
m_critSec.Leave();
|
|
}
|
|
|
|
HRESULT CSsdpService::HrInitialize(
|
|
SSDP_MESSAGE * pssdpMsg,
|
|
DWORD dwFlags,
|
|
PCONTEXT_HANDLE_TYPE * ppContextHandle)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrInitializeSsdpRequestFromMessage(&m_ssdpRequest, pssdpMsg);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_nLifetime = pssdpMsg->iLifeTime;
|
|
m_nRetryCount = 3;
|
|
m_dwFlags = dwFlags;
|
|
m_ppContextHandle = ppContextHandle;
|
|
*m_ppContextHandle = NULL;
|
|
m_ssdpRequest.RequestUri = MulticastUri;
|
|
|
|
OSVERSIONINFO osvi = {0};
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
if(!GetVersionEx(&osvi))
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Yes this is a constant but it is just used temporarily
|
|
m_ssdpRequest.Headers[SSDP_SERVER] = "Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0";
|
|
char * szAlive = NULL;
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_ssdpRequest.Headers[SSDP_NTS] = AliveHeader;
|
|
if (!ComposeSsdpRequest(&m_ssdpRequest, &szAlive))
|
|
{
|
|
hr = E_FAIL;
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::HrInitialize - ComposeSsdpRequest failed!");
|
|
}
|
|
else
|
|
{
|
|
hr = m_strAlive.HrAssign(szAlive);
|
|
delete [] szAlive;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
char * szByebye = NULL;
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_ssdpRequest.Headers[SSDP_NTS] = ByebyeHeader;
|
|
if(!ComposeSsdpRequest(&m_ssdpRequest, &szByebye))
|
|
{
|
|
hr = E_FAIL;
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::HrInitialize - ComposeSsdpRequest failed!");
|
|
}
|
|
else
|
|
{
|
|
hr = m_strByebye.HrAssign(szByebye);
|
|
delete [] szByebye;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Generate an empty Ext header on the response to M-SEARCH
|
|
m_ssdpRequest.Headers[SSDP_EXT] = "";
|
|
char * szResponse = NULL;
|
|
|
|
if (!ComposeSsdpResponse(&m_ssdpRequest, &szResponse))
|
|
{
|
|
hr = E_FAIL;
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::HrInitialize - ComposeSsdpResponse failed!");
|
|
}
|
|
else
|
|
{
|
|
hr = m_strResponse.HrAssign(szResponse);
|
|
delete [] szResponse;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Important: Set to NULL to prevent freeing memory.
|
|
m_ssdpRequest.Headers[SSDP_NTS] = NULL;
|
|
m_ssdpRequest.RequestUri = NULL;
|
|
// Important: Set to NULL to prevent freeing memory.
|
|
m_ssdpRequest.Headers[SSDP_EXT] = NULL;
|
|
m_ssdpRequest.Headers[SSDP_SERVER] = NULL;
|
|
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::HrInitialize");
|
|
return hr;
|
|
}
|
|
HRESULT CSsdpService::HrStartTimer()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CLock lock(m_critSec);
|
|
|
|
hr = m_timer.HrSetTimer(0);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
*m_ppContextHandle = this;
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::HrStartTimer");
|
|
return hr;
|
|
}
|
|
|
|
long CalcMX (SSDP_REQUEST * pSsdpRequest)
|
|
{
|
|
LONG lMin, lMX;
|
|
|
|
#define MINIMUM_MX_UUID 1
|
|
#define MINIMUM_MX_DST 2
|
|
#define MINIMUM_MX_ROOT 3
|
|
#define MAXIMUM_MX 12
|
|
#define UUID_COLON "uuid:"
|
|
#define URN_SERVICE "urn:schemas-upnp-org:service:"
|
|
#define URN_DEVICE "urn:schemas-upnp-org:device:"
|
|
|
|
Assert (pSsdpRequest != NULL);
|
|
if (strncmp (pSsdpRequest->Headers[SSDP_ST], UUID_COLON, sizeof(UUID_COLON) - 1) == 0)
|
|
lMin = MINIMUM_MX_UUID;
|
|
else if (strcmp(pSsdpRequest->Headers[SSDP_ST], "upnp:rootdevice") == 0)
|
|
lMin = MINIMUM_MX_ROOT;
|
|
else if (strcmp(pSsdpRequest->Headers[SSDP_ST], "ssdp:all") == 0)
|
|
lMin = MINIMUM_MX_ROOT;
|
|
else if (
|
|
strncmp (pSsdpRequest->Headers[SSDP_ST], URN_SERVICE, sizeof(URN_SERVICE) - 1) == 0 ||
|
|
strncmp (pSsdpRequest->Headers[SSDP_ST], URN_DEVICE, sizeof(URN_DEVICE) - 1) == 0 )
|
|
lMin = MINIMUM_MX_DST;
|
|
else
|
|
lMin = MINIMUM_MX_UUID;
|
|
lMX = atol(pSsdpRequest->Headers[SSDP_MX]);
|
|
if (lMX > MAXIMUM_MX) lMX = MAXIMUM_MX;
|
|
else if (lMX < lMin) lMX = lMin;
|
|
return lMX;
|
|
}
|
|
|
|
HRESULT CSsdpService::HrAddSearchResponse(SSDP_REQUEST * pSsdpRequest,
|
|
SOCKET * pSocket,
|
|
SOCKADDR_IN * pRemoteSocket)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CLock lock(m_critSec);
|
|
|
|
BOOL bSendRequest = FALSE;
|
|
|
|
if(pSsdpRequest->Headers[SSDP_ST])
|
|
{
|
|
if(0 == lstrcmpA(pSsdpRequest->Headers[SSDP_ST], "ssdp:all"))
|
|
{
|
|
bSendRequest = TRUE;
|
|
}
|
|
if(!bSendRequest && 0 == lstrcmpA(pSsdpRequest->Headers[SSDP_ST], m_ssdpRequest.Headers[SSDP_NT]))
|
|
{
|
|
bSendRequest = TRUE;
|
|
}
|
|
}
|
|
|
|
if(bSendRequest)
|
|
{
|
|
TraceTag(ttidSsdpAnnounce, "Adding search response for %s", m_ssdpRequest.Headers[SSDP_NT]);
|
|
|
|
char * szResponse = NULL;
|
|
hr = m_strResponse.HrGetMultiByteWithAlloc(&szResponse);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Takes ownership of string
|
|
hr = CSsdpSearchResponse::HrCreate(pSocket, pRemoteSocket,
|
|
szResponse,
|
|
CalcMX(pSsdpRequest));
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::HrAddSearchResponse");
|
|
return hr;
|
|
}
|
|
|
|
class CSsdpByebye : public CWorkItem
|
|
{
|
|
public:
|
|
static HRESULT Create(char * szByebye);
|
|
|
|
void TimerFired();
|
|
BOOL TimerTryToLock()
|
|
{
|
|
return m_critSec.FTryEnter();
|
|
}
|
|
void TimerUnlock()
|
|
{
|
|
m_critSec.Leave();
|
|
}
|
|
private:
|
|
CSsdpByebye(char * szByebye);
|
|
~CSsdpByebye();
|
|
CSsdpByebye(const CSsdpByebye &);
|
|
CSsdpByebye & operator=(const CSsdpByebye &);
|
|
|
|
DWORD DwRun();
|
|
|
|
char * m_szByebye;
|
|
long m_nRetryCount;
|
|
CTimer<CSsdpByebye> m_timer;
|
|
CUCriticalSection m_critSec;
|
|
};
|
|
|
|
CSsdpByebye::CSsdpByebye(char * szByebye)
|
|
: m_szByebye(szByebye), m_nRetryCount(3), m_timer(*this)
|
|
{
|
|
}
|
|
|
|
CSsdpByebye::~CSsdpByebye()
|
|
{
|
|
delete [] m_szByebye;
|
|
}
|
|
|
|
HRESULT CSsdpByebye::Create(char * szByebye)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CSsdpByebye * pByebye = new CSsdpByebye(szByebye);
|
|
if(!pByebye)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
delete [] szByebye;
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pByebye->m_timer.HrSetTimer(0);
|
|
if(FAILED(hr))
|
|
{
|
|
delete pByebye;
|
|
}
|
|
}
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpByebye::Create");
|
|
return hr;
|
|
}
|
|
|
|
void CSsdpByebye::TimerFired()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
GetNetworkLock();
|
|
|
|
SendOnAllNetworks(m_szByebye, NULL);
|
|
|
|
FreeNetworkLock();
|
|
|
|
--m_nRetryCount;
|
|
|
|
// We do this three times and then we kill ourselves
|
|
if(0 == m_nRetryCount)
|
|
{
|
|
// This will queue ourselves to autodelete
|
|
HrStart(true);
|
|
}
|
|
else
|
|
{
|
|
hr = m_timer.HrSetTimerInFired(RETRY_INTERVAL);
|
|
if(FAILED(hr))
|
|
{
|
|
// This will queue ourselves to autodelete
|
|
HrStart(true);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpByebye::TimerFired");
|
|
}
|
|
|
|
DWORD CSsdpByebye::DwRun()
|
|
{
|
|
// Wait for timer to exit before allowing this function to return (which causes delete this to happen)
|
|
CLock lock(m_critSec);
|
|
m_timer.HrDelete(INVALID_HANDLE_VALUE);
|
|
return 0;
|
|
}
|
|
|
|
HRESULT CSsdpService::HrCleanup(BOOL bByebye)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CLock lock(m_critSec);
|
|
hr = m_timer.HrDelete(INVALID_HANDLE_VALUE);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(bByebye)
|
|
{
|
|
char * szByebye = NULL;
|
|
hr = m_strByebye.HrGetMultiByteWithAlloc(&szByebye);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// This takes ownership of memory
|
|
CSsdpByebye::Create(szByebye);
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpService::HrCleanup");
|
|
return hr;
|
|
}
|
|
|
|
BOOL CSsdpService::FIsPersistent()
|
|
{
|
|
return (SSDP_SERVICE_PERSISTENT & m_dwFlags) != 0;
|
|
}
|
|
|
|
CSsdpServiceManager CSsdpServiceManager::s_instance;
|
|
|
|
CSsdpServiceManager::CSsdpServiceManager()
|
|
{
|
|
}
|
|
|
|
CSsdpServiceManager::~CSsdpServiceManager()
|
|
{
|
|
}
|
|
|
|
CSsdpServiceManager & CSsdpServiceManager::Instance()
|
|
{
|
|
return s_instance;
|
|
}
|
|
|
|
HRESULT CSsdpServiceManager::HrAddService(
|
|
SSDP_MESSAGE * pssdpMsg,
|
|
DWORD dwFlags,
|
|
PCONTEXT_HANDLE_TYPE * ppContextHandle)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CLock lock(m_critSec);
|
|
|
|
if(pssdpMsg && FindServiceByUsn(pssdpMsg->szUSN))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
TraceTag(ttidSsdpAnnounce, "CSsdpServiceManager::HrAddService - attempting to add duplicate USN");
|
|
}
|
|
|
|
CSsdpService * pService = NULL;
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
ServiceList serviceList;
|
|
hr = serviceList.HrPushFrontDefault();
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = serviceList.Front().HrInitialize(pssdpMsg, dwFlags, ppContextHandle);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = serviceList.Front().HrStartTimer();
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_serviceList.Prepend(serviceList);
|
|
pService = &m_serviceList.Front();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pService)
|
|
{
|
|
hr = CSsdpRundownSupport::Instance().HrAddRundownItem(pService);
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpServiceManager::HrAddService");
|
|
return hr;
|
|
}
|
|
|
|
CSsdpService * CSsdpServiceManager::FindServiceByUsn(char * szUSN)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CLock lock(m_critSec);
|
|
|
|
CSsdpService * pService = NULL;
|
|
|
|
ServiceList::Iterator iter;
|
|
if(S_OK == m_serviceList.GetIterator(iter))
|
|
{
|
|
CSsdpService * pServiceIter = NULL;
|
|
while(S_OK == iter.HrGetItem(&pServiceIter))
|
|
{
|
|
if(pServiceIter->FIsUsn(szUSN))
|
|
{
|
|
pService = pServiceIter;
|
|
break;
|
|
}
|
|
if(S_OK != iter.HrNext())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(!pService)
|
|
{
|
|
TraceTag(ttidSsdpAnnounce, "CSsdpServiceManager::FindServiceByUsn(%s) - not found!", szUSN);
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpServiceManager::FindServiceByUsn");
|
|
return pService;
|
|
}
|
|
|
|
HRESULT CSsdpServiceManager::HrAddSearchResponse(SSDP_REQUEST * pSsdpRequest,
|
|
SOCKET * pSocket,
|
|
SOCKADDR_IN * pRemoteSocket)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CLock lock(m_critSec);
|
|
|
|
ServiceList::Iterator iter;
|
|
if(S_OK == m_serviceList.GetIterator(iter))
|
|
{
|
|
CSsdpService * pService = NULL;
|
|
while(S_OK == iter.HrGetItem(&pService))
|
|
{
|
|
pService->HrAddSearchResponse(pSsdpRequest, pSocket, pRemoteSocket);
|
|
|
|
if(S_OK != iter.HrNext())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpServiceManager::HrAddSearchResponse");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSsdpServiceManager::HrRemoveService(CSsdpService * pService, BOOL bByebye)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrRemoveServiceInternal(pService, bByebye, FALSE);
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpServiceManager::HrRemoveService");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSsdpServiceManager::HrServiceRundown(CSsdpService * pService)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrRemoveServiceInternal(pService, TRUE, TRUE);
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpServiceManager::HrCleanupAnouncements");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSsdpServiceManager::HrCleanupAnouncements()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CLock lock(m_critSec);
|
|
|
|
// TODO: Implement this!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpServiceManager::HrCleanupAnouncements");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSsdpServiceManager::HrRemoveServiceInternal(CSsdpService * pService, BOOL bByebye, BOOL bRundown)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
BOOL bFound = FALSE;
|
|
|
|
ServiceList serviceList;
|
|
|
|
{
|
|
CLock lock(m_critSec);
|
|
|
|
ServiceList::Iterator iter;
|
|
if(S_OK == m_serviceList.GetIterator(iter))
|
|
{
|
|
CSsdpService * pServiceIter = NULL;
|
|
while(S_OK == iter.HrGetItem(&pServiceIter))
|
|
{
|
|
if(pServiceIter == pService)
|
|
{
|
|
if(!bRundown || !pService->FIsPersistent())
|
|
{
|
|
iter.HrMoveToList(serviceList);
|
|
bFound = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
if(S_OK != iter.HrNext())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(bFound)
|
|
{
|
|
ServiceList::Iterator iter;
|
|
if(S_OK == serviceList.GetIterator(iter))
|
|
{
|
|
CSsdpService * pServiceIter = NULL;
|
|
while(S_OK == iter.HrGetItem(&pServiceIter))
|
|
{
|
|
if(!bRundown)
|
|
{
|
|
CSsdpRundownSupport::Instance().RemoveRundownItem(pServiceIter);
|
|
}
|
|
hr = pServiceIter->HrCleanup(bByebye);
|
|
if(S_OK != iter.HrNext())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "CSsdpServiceManager::HrRemoveServiceInternal");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrInitializeSsdpRequestFromMessage(
|
|
SSDP_REQUEST * pRequest,
|
|
const SSDP_MESSAGE *pMsg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ZeroMemory(pRequest, sizeof(*pRequest));
|
|
|
|
pRequest->Method = SSDP_NOTIFY;
|
|
|
|
pRequest->Headers[SSDP_HOST] = reinterpret_cast<char*>(
|
|
midl_user_allocate(sizeof(CHAR) * (
|
|
lstrlenA(SSDP_ADDR) +
|
|
1 + // colon
|
|
6 + // port number
|
|
1)));
|
|
if (!pRequest->Headers[SSDP_HOST])
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
wsprintfA(pRequest->Headers[SSDP_HOST], "%s:%d", SSDP_ADDR, SSDP_PORT);
|
|
|
|
hr = HrCopyString(pMsg->szType, &pRequest->Headers[SSDP_NT]);
|
|
if(SUCCEEDED(hr) || !pMsg->szType)
|
|
{
|
|
hr = HrCopyString(pMsg->szUSN, &pRequest->Headers[SSDP_USN]);
|
|
if(SUCCEEDED(hr) || !pMsg->szUSN)
|
|
{
|
|
hr = HrCopyString(pMsg->szAltHeaders, &pRequest->Headers[SSDP_AL]);
|
|
if(SUCCEEDED(hr) || !pMsg->szAltHeaders)
|
|
{
|
|
hr = HrCopyString(pMsg->szLocHeader, &pRequest->Headers[SSDP_LOCATION]);
|
|
if(SUCCEEDED(hr) || pMsg->szLocHeader)
|
|
{
|
|
char szBuf[256];
|
|
wsprintfA(szBuf, "max-age=%d", pMsg->iLifeTime);
|
|
hr = HrCopyString(szBuf, &pRequest->Headers[SSDP_CACHECONTROL]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
FreeSsdpRequest(pRequest);
|
|
ZeroMemory(pRequest, sizeof(*pRequest));
|
|
}
|
|
|
|
TraceHr(ttidSsdpAnnounce, FAL, hr, FALSE, "HrInitializeSsdpRequestFromMessage");
|
|
return hr;
|
|
}
|
|
|