📄 devtree.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "pch.h"
#pragma hdrstop
#pragma warning (disable : 4509)
BOOL RegisterUpnpServiceImpl(PSSDP_MESSAGE pSsdpMessage, DWORD flags, HANDLE* phService);
#define MAX_STRING 256
//
// string dup utility functions that use new instead of malloc as the allocator
//
PSTR
StrDupWtoA(LPCWSTR pwszSource)
{
PSTR psza;
size_t nBytes;
if (!pwszSource)
return NULL;
nBytes = wcslen(pwszSource)+1;
if (psza = new CHAR [nBytes])
wcstombs(psza,pwszSource,nBytes);
return psza;
}
PWSTR
StrDupAtoW(LPCSTR pszaSource)
{
size_t nBytes;
PWSTR pwsz;
if (!pszaSource)
return NULL;
nBytes = strlen(pszaSource)+1;
if (pwsz = new WCHAR [nBytes])
{
mbstowcs(pwsz,pszaSource, nBytes);
}
return pwsz;
}
PWSTR
StrDupW(LPCWSTR pwszSource)
{
PWSTR pwsz;
size_t nBytes;
if (!pwszSource)
return NULL;
nBytes = wcslen(pwszSource)+1;
if (pwsz = new WCHAR [nBytes])
memcpy(pwsz,pwszSource,nBytes*sizeof(WCHAR));
return pwsz;
}
PWSTR
CreateUDN(void)
{
PWSTR pszUDN;
LONGLONG uuid64 = GenerateUUID64();
// GUID guid;
//CeGenerateGUID(&guid);
pszUDN = new WCHAR [42];
if (!pszUDN) return NULL;
wsprintfW(pszUDN, L"uuid:%04x%04x-%04x-%04x-0000-000000000000", (WORD)uuid64, *((WORD*)&uuid64 + 1), *((WORD*)&uuid64 + 2), *((WORD*)&uuid64 + 3));
return pszUDN;
}
HANDLE RegisterSSDPService(
DWORD dwLifeTime,
PCWSTR pStrDescUrl,
PCWSTR pStrUDN,
PCWSTR pStrType)
{
HANDLE hReturn = NULL;
SSDP_MESSAGE msg;
CHAR aStrBuffer [MAX_STRING];
CHAR aStrUdn [MAX_STRING];
CHAR aStrType [MAX_STRING];
CHAR aStrDescUrl [MAX_STRING];
memset(&msg, 0, sizeof(msg));
wcstombs ( aStrDescUrl ,pStrDescUrl, MAX_STRING);
wcstombs (aStrUdn, pStrUDN, MAX_STRING);
wcstombs (aStrType, pStrType, MAX_STRING);
if (pStrUDN == pStrType)
{
// uuid:deviceUUID
strcpy(aStrBuffer, aStrUdn);
}
else
{
// one of the following :-
// uuid:deviceUUID::upnp:rootDevice
// uuid:deviceUUID::urn:schemas-upnp-org:device:deviceType:v
// uuid:deviceUUID::urn:schemas-upnp-org:service:serviceType:v
sprintf(aStrBuffer, "%s::%s", aStrUdn, aStrType);
}
msg.iLifeTime = dwLifeTime;
msg.szLocHeader = aStrDescUrl;
msg.szType = aStrType;
msg.szUSN = aStrBuffer;
RegisterUpnpServiceImpl(&msg, 0, &hReturn);
return hReturn;
}
#if UNDER_CE
//
// hack to do Initialize in a worker thread,
// because OLE mucks with TLS
//
// static
DWORD
HostedDeviceTree::Initialize2(void *param)
{
struct HDTInitInfo *pHDTI = (struct HDTInitInfo *)(param);
pHDTI->fRet = pHDTI->pHDT->Initialize(&pHDTI->devInfo, pHDTI->hOwnerProc, pHDTI->hOwner);
return 0;
}
#endif
BOOL
HostedDeviceTree::Initialize(UPNPDEVICEINFO *pDevInfo, HANDLE hOwnerProc, HANDLE hOwner)
{
BOOL fRet = TRUE;
if (pDevInfo->pszUDN && pDevInfo->pszUDN[0])
// UDN was specified -> use it
m_pszUDN = StrDupW(pDevInfo->pszUDN);
else
// generate a UDN
m_pszUDN = ::CreateUDN();
m_pfCallback = pDevInfo->pfCallback;
m_pvCallbackContext = pDevInfo->pvUserDevContext;
m_hOwner = hOwner;
m_hOwnerProc = hOwnerProc;
m_pszName = StrDupW(pDevInfo->pszDeviceName);
if(pDevInfo->cachecontrol != 0)
m_dwLifeTime = max(pDevInfo->cachecontrol, MINIMUM_PUBLISH_INTERVAL);
INT nChars;
Assert(!m_pszDescFileName);
// conjure up a suitable filename for the published device description file
// "\windows\upnp\" "MyDevice" ".xml"
nChars = celems(c_szLocalWebRootDir)+wcslen(m_pszName)+5;
m_pszDescFileName = new WCHAR [nChars];
if (!m_pszDescFileName)
fRet = FALSE;
else
{
nChars -= wsprintfW(m_pszDescFileName, L"%s%s.xml",c_szLocalWebRootDir, m_pszName );
Assert(nChars >=0);
}
if (fRet)
// parse device description
fRet = Parse(pDevInfo->pszDeviceDescription);
if (fRet)
m_state = DevTreeInitialized;
return fRet;
}
BOOL
HostedDeviceTree::Publish()
{
BOOL fRet;
TraceTag(ttidPublish, "%s: [%08x] Publish\n", __FUNCTION__, this);
if (m_state >= DevTreePublished)
return FALSE; // already published
if (m_state < DevTreeInitialized)
return FALSE; // not yet initialized
// determine the device description URL
if (!m_pszDescURL)
{
int nChars;
// skip past the web root path e.g) \windows\upnp
PCWSTR pch = m_pszDescFileName+celems(c_szLocalWebRootDir)-1;
nChars = wcslen(pch) + celems(c_szHttpPrefix) + celems(c_szReplaceAddrGuid) + celems(c_szURLPrefix) + 1;
m_pszDescURL = new WCHAR [nChars];
if (!m_pszDescURL)
return FALSE;
nChars -= wsprintfW(m_pszDescURL, L"%s%S%s%s", c_szHttpPrefix, c_szReplaceAddrGuid, c_szURLPrefix, pch);
Assert(nChars > 0);
}
fRet = FALSE;
Lock();
// publish the rootdevice
m_hSSDPRoot = RegisterSSDPService(m_dwLifeTime, m_pszDescURL, UDN(), L"upnp:rootdevice");
if (VALIDSSDPH(m_hSSDPRoot))
{
// Register each of the devices and services with SSDP in order to send out the announcements
fRet = m_pRootDevice->SsdpRegister(m_dwLifeTime, m_pszDescURL);
if (!fRet)
{
DeregisterUpnpService(m_hSSDPRoot, TRUE);
m_hSSDPRoot = INVALID_HANDLE_VALUE;
}
}
if (fRet)
m_state = DevTreePublished;
Unlock();
TraceTag(ttidPublish, "%s: [%08x] Published\n", __FUNCTION__, this);
return fRet;
}
BOOL
HostedDeviceTree::Unpublish()
{
BOOL fRet = FALSE;
TraceTag(ttidPublish, "%s: [%08x] Unpublish\n", __FUNCTION__, this);
Lock();
if (m_state >= DevTreePublished)
{
if (VALIDSSDPH(m_hSSDPRoot))
{
fRet = DeregisterUpnpService(m_hSSDPRoot,TRUE);
m_hSSDPRoot = INVALID_HANDLE_VALUE;
}
fRet &= m_pRootDevice->SsdpUnregister();
m_state = DevTreeInitialized;
}
Unlock();
TraceTag(ttidPublish, "%s: [%08x] Unpublished\n", __FUNCTION__, this);
return fRet;
}
BOOL
HostedDeviceTree::SubmitPropertyEvent(
PCWSTR szUDN,
PCWSTR szServiceId,
DWORD dwFlags,
DWORD nArgs,
UPNPPARAM *rgArgs)
{
HostedService *pService;
BOOL fRet = FALSE;
TraceTag(ttidTrace, "%s: [%08x] Submit Property Event UDN[%S] ServiceID[%S]\n", __FUNCTION__, this, szUDN, szServiceId);
Lock();
if (m_state >= DevTreeInitialized)
{
pService = FindService(szUDN, szServiceId);
if (pService)
{
fRet = pService->SubmitPropertyEvent(dwFlags, nArgs, rgArgs);
}
}
Unlock();
TraceTag(ttidTrace, "%s: [%08x] Submited Property Event UDN[%S] ServiceID[%S]\n", __FUNCTION__, this, szUDN, szServiceId);
return fRet;
}
HostedDeviceTree::~HostedDeviceTree()
{
delete m_pRootDevice;
delete m_pTempDevice;
delete m_pszURLBase;
delete m_pszDescURL;
delete m_pszDescFileName;
delete m_pszName;
delete m_pszUDN;
DeleteCriticalSection(&m_cs);
}
BOOL HostedDeviceTree::Shutdown(DWORD dwFlags)
{
DWORD dwStatus;
TraceTag(ttidTrace, "%s: [%08x] Shutdown\n", __FUNCTION__, this);
Lock();
Unpublish();
m_state = DevTreeInvalid;
m_hShutdownEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
Unlock();
if (! (dwFlags & HDT_NO_CALLBACKS))
{
// notify device owner that his device is going away
DoDeviceCallback(NULL, UPNPCB_SHUTDOWN, NULL, NULL, NULL);
}
DecRef(); // normally decrements to zero
dwStatus = WaitForSingleObject(m_hShutdownEvent, 15000);
AssertSz(dwStatus == WAIT_OBJECT_0, "HostedDeviceTree not released on shutdown!");
CloseHandle(m_hShutdownEvent);
m_hShutdownEvent = NULL;
DeleteFile(m_pszDescFileName);
TraceTag(ttidTrace, "%s: [%08x] Shutdown Complete\n", __FUNCTION__, this);
return TRUE;
}
// CreateUDN
void HostedDeviceTree::CreateUDN(LPWSTR *ppUDN)
{
Assert(ppUDN);
Assert(!*ppUDN);
if(!m_nUDNSuffix)
{
// root device
*ppUDN = StrDupW(m_pszUDN);
}
else
{
// embedded device
int cchUDN = wcslen(m_pszUDN) + 11; // max size of integer string
*ppUDN = new WCHAR [cchUDN];
if (*ppUDN)
{
cchUDN -= wsprintfW(*ppUDN, L"%.37s%04x", m_pszUDN, m_nUDNSuffix);
Assert(cchUDN > 0);
}
}
m_nUDNSuffix++;
}
HostedDevice::~HostedDevice()
{
delete m_pNextDev;
delete m_pFirstChildDev;
delete m_pFirstService;
delete m_pszUDN;
delete m_pszOrigUDN;
delete m_pszDeviceType;
}
BOOL HostedDevice::SsdpRegister(DWORD dwLifeTime, PCWSTR pszDescURL )
{
BOOL fRet = TRUE;
// publish the UDN
m_hSSDPUDN = RegisterSSDPService(dwLifeTime, pszDescURL, m_pszUDN, m_pszUDN);
// publish the device Type
m_hSSDPDevType = RegisterSSDPService(dwLifeTime, pszDescURL, m_pszUDN, m_pszDeviceType);
if (VALIDSSDPH(m_hSSDPUDN) && VALIDSSDPH(m_hSSDPDevType))
{
HostedService *pService;
fRet = TRUE;
for (pService=m_pFirstService;pService;pService=pService->NextService())
{
fRet = pService->SsdpRegister(dwLifeTime, pszDescURL, m_pszUDN);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -