📄 upnphost.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.
//
/*++
File Name:
upnphost.cpp
Abstract:
This file implements the UPnP Registrar coclass
Author: GeorgeJ
Created: Nov 2000
--*/
#include "upnphostp.h"
#include "upnpmem.h"
#include "auto_xxx.hxx"
// combook.cpp should be included in this file only
#include "combook.cpp"
#define ttidRegistrar 1
HINSTANCE g_hMod; // Dll module handle
// map CLSID to GetClassObject/UpdateRegistry routine
BEGIN_COCLASS_TABLE(ClassTable)
IMPLEMENTS_COCLASS(UPnPRegistrar)
END_COCLASS_TABLE()
// implement ModuleAddRef/ModuleRelease/ModuleIsStopping/ModuleIsIdle
IMPLEMENT_DLL_MODULE_ROUTINES()
// implement DllGetClassObject/DllCanUnloadNow/Dll[Un]RegisterServer
IMPLEMENT_DLL_ENTRY_POINTS(g_hMod, ClassTable, 0, FALSE)
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("UPNPHOST"), {
TEXT("Misc"), TEXT("Registrar"), TEXT("Automation proxy"), TEXT("Events"),
TEXT(""),TEXT(""),TEXT(""),TEXT(""),
TEXT(""),TEXT("Control"),TEXT(""),TEXT(""),
TEXT(""),TEXT(""),TEXT("Trace"),TEXT("Error") },
0x00008000
};
#endif
extern "C"
BOOL
WINAPI
DllMain(IN PVOID DllHandle,
IN ULONG Reason,
IN PVOID Context OPTIONAL)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
if(!UpnpHeapCreate())
return FALSE;
DisableThreadLibraryCalls((HINSTANCE)DllHandle);
DEBUGREGISTER((HMODULE)DllHandle);
g_hMod = (HINSTANCE)DllHandle;
break;
case DLL_PROCESS_DETACH:
UpnpHeapDestroy();
break;
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: AddDevice
//
// Purpose: Create and publish the UPnP device tree.
// Register for callbacks from the service layer.
// The device has a locally unique name specified
// by member bstrDeviceId
//
// Arguments:
// pszXMLDesc [in] XML device description template
//
// Returns:
// HRESULT
//
HRESULT
DeviceProxy::AddDevice(LPWSTR pszXMLDesc)
{
UPNPDEVICEINFO devInfo;
BOOL fRet;
devInfo.cbStruct = sizeof(devInfo);
devInfo.pszDeviceDescription = pszXMLDesc;
devInfo.pszDeviceName = m_bstrDeviceId;
// if the UDN is not NULL, it is assumed to be a UUID
devInfo.pszUDN = m_bstrUDN;
devInfo.cachecontrol = m_nLifeTime;
// all callbacks get a pointer to the DeviceProxy instance
// as the 2nd Parameter
devInfo.pvUserDevContext = this;
devInfo.pfCallback = DevCallback;
fRet = UpnpAddDevice(&devInfo);
if (fRet)
{
// send out the SSDP announcements
fRet = UpnpPublishDevice(m_bstrDeviceId);
}
if (!fRet)
{
return HrFromLastWin32Error();
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: RemoveDevice
//
// Purpose: Unpublish and unregister the device tree.
//
// Arguments:
//
// Returns:
// HRESULT
//
HRESULT
DeviceProxy::RemoveDevice()
{
BOOL fRet;
// no need to explicitly call Unpublish
fRet = UpnpRemoveDevice(m_bstrDeviceId);
if (!fRet)
return HrFromLastWin32Error();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: DevCallback (static method)
//
// Purpose: UPNPCALLBACK prototype that is invoked by the
// device hosting layer when interesting events
// occur. In particular, the callback is invoked when
// control requests are received from remote control points.
//
// Arguments:
// callbackId [in] specifies the type of callback event
// pvUserContext [in] DeviceProxy pointer
// pvSvcParam [in] depends on callbackId
//
// Returns:
// TRUE if success; FALSE if something bad happens
//
DWORD DeviceProxy::DevCallback(
UPNPCB_ID callbackId,
PVOID pvUserContext, // app context (from UPNPDEVICEINFO)
PVOID pvSvcParam) // depends on CALLBACKID
{
DeviceProxy *pDevProxy = (DeviceProxy *)pvUserContext;
switch (callbackId)
{
case UPNPCB_INIT:
return pDevProxy->InitCallback();
break;
case UPNPCB_SUBSCRIBING:
return pDevProxy->SubscribeCallback((UPNPSUBSCRIPTION*)pvSvcParam);
break;
case UPNPCB_CONTROL:
return pDevProxy->ControlCallback((UPNPSERVICECONTROL*)pvSvcParam);
break;
case UPNPCB_SHUTDOWN:
return pDevProxy->ShutdownCallback();
break;
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Method: FindDevProxyByName
//
// Purpose: Locate the named device proxy in the registrar
// list and return a pointer
//
// Arguments:
// pszDevId [in] local name for device tree
//
// Returns:
// NULL if the object is not found, else pointer to the DeviceProxy
//
DeviceProxy *
UPnPRegistrar::FindDevProxyByName(PCWSTR pszDevId)
{
LIST_ENTRY *pLink;
for (pLink = m_DevProxyList.Flink; pLink != &m_DevProxyList; pLink = pLink->Flink)
{
DeviceProxy *pDev;
pDev = CONTAINING_RECORD(pLink, DeviceProxy, m_link);
if (wcscmp(pszDevId, pDev->Name()) == 0)
return pDev;
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// Function: HrCreateDeviceIdentifier
//
// Purpose: Generate a Unique Device Identifier string.
// uses SysAllocString for memory.
// The identifier is a 64 bit mini-GUID.
//
// Arguments:
// pbstrDevId [out] BSTR UDN (without the uuid: prefix)
//
// Returns:
// HRESULT
//
HRESULT
UPnPRegistrar::HrCreateDeviceIdentifier(BSTR *pbstrDevId)
{
WCHAR wsz[64];
LONGLONG uuid64 = GenerateUUID64();
*pbstrDevId = NULL;
// we need a device Id that is unique and a valid filename
// so no illegal characters like ':'
wsprintfW(wsz, L"%04x%04x-%04x-%04x-0000-000000000000", (WORD)uuid64, *((WORD*)&uuid64 + 1), *((WORD*)&uuid64 + 2), *((WORD*)&uuid64 + 3));
if (*pbstrDevId = SysAllocString(wsz))
return S_OK;
else
return E_OUTOFMEMORY;
}
//+---------------------------------------------------------------------------
//
// Function: IUPnPRegistrar::RegisterRunningDevice
//
// Purpose: Publish an already instantiated UPnP device tree.
// See public docs for more info
//
// Arguments:
// bstrXMLDesc [in] XML device description template
// punkDeviceControl [in] IUPnPDeviceControl interface of the object
// bstrInitString [in] optional string to be passed back to object on init
// bstrResourcePath [in] NULL - not used for WinCE. The resources should
// be under the \windows\upnp directory.
// nLifeTime [in] lifetime in seconds. Maybe 0 for system default
// pbstrDeviceIdentifier [out] id generated by UPnP service for use in
// UnregisterDevice and ReregisterDevice
// Returns:
// HRESULT
//
STDMETHODIMP
UPnPRegistrar::RegisterRunningDevice(
/*[in]*/ BSTR bstrXMLDesc,
/*[in]*/ IUnknown * punkDeviceControl,
/*[in]*/ BSTR bstrInitString,
/*[in]*/ BSTR bstrResourcePath,
/*[in]*/ long nLifeTime,
/*[out, retval]*/ BSTR * pbstrDeviceIdentifier)
{
HRESULT hr = S_OK;
BSTR bstrDeviceId = NULL;
*pbstrDeviceIdentifier = NULL;
// construct pbstrDeviceIdentifier
hr = HrCreateDeviceIdentifier( &bstrDeviceId);
if (SUCCEEDED(hr))
{
// add device
hr = ReregisterRunningDevice(
bstrDeviceId,
bstrXMLDesc,
punkDeviceControl,
bstrInitString,
bstrResourcePath,
nLifeTime
);
if (SUCCEEDED(hr))
{
*pbstrDeviceIdentifier = bstrDeviceId;
}
else
{
SysFreeString(bstrDeviceId);
}
}
return hr;
}
static const int MaxInstances = 30;
//+---------------------------------------------------------------------------
//
// Function: IUPnPRegistrar::RegisterDevice
//
// Purpose: Publish UPnP device tree with delayed instantiaton of the
// device implementation
// See public docs for more info
//
// Arguments:
// pszXMLDesc [in] XML device description template
// bstrProgIDDeviceControlClass [in] CLSID of COM device implementation
// bstrInitString [in] optional string to be passed back to object on init
// bstrContainerId [in] NULL - not used on WinCE
// bstrResourcePath [in] NULL - not used for WinCE. The resources should
// be under the \windows\upnp directory.
// nLifeTime [in] lifetime in seconds. Maybe 0 for system default
// pbstrDeviceIdentifier [out] id generated by UPnP service for use in
// UnregisterDevice and ReregisterDevice
// Returns:
// HRESULT
//
STDMETHODIMP UPnPRegistrar::RegisterDevice(
/*[in]*/ BSTR bstrXMLDesc,
/*[in]*/ BSTR bstrProgIDDeviceControlClass,
/*[in]*/ BSTR bstrInitString,
/*[in]*/ BSTR bstrContainerId,
/*[in]*/ BSTR bstrResourcePath,
/*[in]*/ long nLifeTime,
/*[out, retval]*/ BSTR * pbstrDeviceIdentifier)
{
HRESULT hr = E_FAIL;
BSTR bstrDeviceId = NULL;
*pbstrDeviceIdentifier = NULL;
if (bstrXMLDesc == NULL
|| bstrProgIDDeviceControlClass == NULL
|| pbstrDeviceIdentifier == NULL)
{
return E_INVALIDARG;
}
// construct pbstrDeviceIdentifier
hr = HrCreateDeviceIdentifier( &bstrDeviceId);
if (SUCCEEDED(hr))
{
hr = ReregisterDevice(
bstrDeviceId,
bstrXMLDesc,
bstrProgIDDeviceControlClass,
bstrInitString,
bstrContainerId,
bstrResourcePath,
nLifeTime);
if (SUCCEEDED(hr))
{
*pbstrDeviceIdentifier = bstrDeviceId;
}
else
SysFreeString(bstrDeviceId);
}
return hr;
}
static const WCHAR c_szuuidprefix[] = L"uuid:";
//+---------------------------------------------------------------------------
//
// Function:
//
// Purpose: Create and publish the UPnP device tree.
//
// Arguments:
// pszXMLDesc [in] XML device description template
//
// Returns:
// HRESULT
//
STDMETHODIMP UPnPRegistrar::ReregisterRunningDevice(
/*[in]*/ BSTR bstrDeviceIdentifier,
/*[in]*/ BSTR bstrXMLDesc,
/*[in]*/ IUnknown * punkDeviceControl,
/*[in]*/ BSTR bstrInitString,
/*[in]*/ BSTR bstrResourcePath,
/*[in]*/ long nLifeTime)
{
HRESULT hr = S_OK;
DeviceProxy *pDevProxy;
WCHAR *pszUDN;
pDevProxy = FindDevProxyByName(bstrDeviceIdentifier);
if (pDevProxy)
{
return E_FAIL; // TODO: proper error
}
// construct UDN as "uuid:<bstrDeviceIdentifier>"
pszUDN = new WCHAR[wcslen(bstrDeviceIdentifier) + celems(c_szuuidprefix)];
if (!pszUDN)
{
return E_OUTOFMEMORY;
}
wcscpy(pszUDN, c_szuuidprefix);
wcscat(pszUDN, bstrDeviceIdentifier);
pDevProxy = new DeviceProxy(
bstrDeviceIdentifier,
bstrInitString,
bstrResourcePath,
bstrXMLDesc,
nLifeTime,
punkDeviceControl,
pszUDN
);
if (pDevProxy)
{
hr = pDevProxy->AddDevice(bstrXMLDesc);
if (SUCCEEDED(hr))
{
pDevProxy->AddToList(&m_DevProxyList);
}
else
delete pDevProxy;
}
else
hr = E_OUTOFMEMORY;
delete[] pszUDN;
return hr;
}
#define __OPT_PLAT_FLAG (defined (ARMV4T))
#define __OPT_VER_OFF
#define __OPT_BUGNUMSTRING "26316"
#include <optimizer.h>
//+---------------------------------------------------------------------------
//
// Function:
//
// Purpose: Create and publish the UPnP device tree.
//
// Arguments:
// pszXMLDesc [in] XML device description template
//
// Returns:
// HRESULT
//
STDMETHODIMP UPnPRegistrar::ReregisterDevice(
/*[in]*/ BSTR bstrDeviceIdentifier,
/*[in]*/ BSTR bstrXMLDesc,
/*[in]*/ BSTR bstrProgIDDeviceControlClass,
/*[in]*/ BSTR bstrInitString,
/*[in]*/ BSTR bstrContainerId,
/*[in]*/ BSTR bstrResourcePath,
/*[in]*/ long nLifeTime)
{
HRESULT hr = E_FAIL;
HANDLE hUPnPHostingEvent;
TraceTag(ttidRegistrar, "UPnPRegistrar::ReregisterDevice");
if ( bstrDeviceIdentifier == NULL
|| bstrXMLDesc == NULL
|| bstrProgIDDeviceControlClass == NULL
)
{
return E_INVALIDARG;
}
// make sure the hosting service is around
hUPnPHostingEvent = CreateEvent(NULL,FALSE,FALSE,UPNPLOADEREVENTNAME);
if (hUPnPHostingEvent == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -