📄 finder.h
字号:
//
// 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.
//
#ifndef _FINDER_H_
#define _FINDER_H_
#define DLLSVC 1
#include <combook.h>
#include "DispatchImpl.hxx"
#include "ConnectionPoint.h"
#include "list.hxx"
#include "DeviceDescription.h"
#include "ssdpapi.h"
#include "upnpmem.h"
class FinderCallback : ConnectionPoint::ICallback
{
~FinderCallback()
{
if(bstrSearchTarget)
SysFreeString(bstrSearchTarget);
if(cb.pCallback)
cb.pCallback->Release();
}
public:
FinderCallback()
: dwSig(0),
fDispatch(FALSE),
bstrSearchTarget(NULL),
dwFlags(0),
hFind(NULL),
pNext(NULL),
dwCookie(0),
lRefCount(1),
fReleasing(FALSE)
{
cb.pCallback = NULL;
cb.pDispatch = NULL;
hEventRelease = CreateEvent(NULL, FALSE, FALSE, NULL);
}
BOOL Valid()
{
return hEventRelease.valid();
}
void Release()
{
ASSERT(lRefCount >= 1);
long refCnt = InterlockedDecrement(&lRefCount);
if(refCnt == 0)
delete this;
else
SetEvent(hEventRelease);
ASSERT(lRefCount >= 1 || fReleasing);
}
void FinalRelease()
{
ASSERT(lRefCount >= 1);
fReleasing = TRUE;
stop_listening();
// poll every 30s to make sure that the lRefCount hasn't decreased without a signal
// this will resolve hang issues if there is a problem with AddRef/Release code
while(lRefCount > 1)
WaitForSingleObject(hEventRelease, 30000);
ASSERT(lRefCount == 1);
Release();
}
void AddRef()
{
ASSERT(lRefCount >= 1);
InterlockedIncrement(&lRefCount);
}
void Lock()
{
cs.lock();
}
void Unlock()
{
cs.unlock();
}
void RemoveReportedDevice(LPCSTR pszUSN)
{
Lock();
for(ce::list<FinderCallback::Device>::iterator it = listReported.begin(), itEnd = listReported.end(); it != itEnd; ++it)
if(it->strUSN == pszUSN)
{
listReported.erase(it);
break;
}
Unlock();
}
DWORD dwSig;
union Callback
{
IUPnPDeviceFinderCallback *pCallback;
IDispatch *pDispatch;
};
Callback cb;
BOOL fDispatch;
BSTR bstrSearchTarget;
DWORD dwFlags;
HANDLE hFind;
FinderCallback *pNext;
struct Device
{
Device(LPCSTR pszUSN, LPCSTR pszLocation, LPCSTR pszNls)
: strUSN(pszUSN),
strLocation(pszLocation),
strNls(pszNls)
{}
ce::string strUSN;
ce::string strLocation;
ce::string strNls;
};
ce::list<Device> listReported;
void start_listening()
{
if(g_pConnectionPoint)
g_pConnectionPoint->advise(bstrSearchTarget, 0, this, &dwCookie);
}
void stop_listening()
{
if(g_pConnectionPoint)
g_pConnectionPoint->unadvise(dwCookie);
dwCookie = 0;
}
protected:
class AsyncDeviceLoader : public IUPnPDescriptionDocumentCallback
{
public:
AsyncDeviceLoader(FinderCallback* pfcb, LPCSTR pszUSN, LPCSTR pszUrl, LPCSTR pszNls, UINT nLifeTime)
: m_pfcb(pfcb),
m_strUSN(pszUSN),
m_strLocHeader(pszUrl),
m_strNls(pszNls),
m_lRefCount(0)
{
m_pfcb->AddRef();
if(m_pDescription = new DeviceDescription(nLifeTime))
m_pDescription->AddRef();
}
~AsyncDeviceLoader()
{
if(m_pDescription)
m_pDescription->Release();
m_pfcb->Release();
}
HRESULT LoadAsync(LPCWSTR pszURL)
{
if(!m_pDescription)
return E_OUTOFMEMORY;
ce::auto_bstr bstrURL = SysAllocString(pszURL);
return m_pDescription->LoadAsync(bstrURL, this);
}
public:
// IUnknown
ULONG STDMETHODCALLTYPE AddRef()
{
InterlockedIncrement(&m_lRefCount);
return m_lRefCount;
}
ULONG STDMETHODCALLTYPE Release()
{
long refCnt = InterlockedDecrement(&m_lRefCount);
if(refCnt == 0)
{
delete this;
return 0;
}
else
return m_lRefCount;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
if(ce::InlineIsEqualGUID(iid, IID_IUnknown) ||
ce::InlineIsEqualGUID(iid, IID_IUPnPDescriptionDocumentCallback))
{
*ppvObject = this;
AddRef();
return S_OK;
}
else
return E_NOINTERFACE;
}
// IUPnPDescriptionDocumentCallback
virtual HRESULT STDMETHODCALLTYPE LoadComplete(/* [in] */HRESULT hrLoadResult);
private:
DeviceDescription* m_pDescription;
FinderCallback* m_pfcb;
ce::string m_strUSN, m_strLocHeader, m_strNls;
LONG m_lRefCount;
};
public:
void PerformCallback(SSDP_CALLBACK_TYPE cbType, BSTR bstrUDN, IUPnPDevice* pUPnPDevice);
void GetUPnPDeviceAsync(LPCSTR pszUSN, LPCSTR pszUrl, LPCSTR pszNls, UINT nLifeTime);
// ConnectionPoint::ICallback
private:
virtual void StateVariableChanged(LPCWSTR pwszName, LPCWSTR pwszValue);
virtual void ServiceInstanceDied(LPCWSTR pszUSN);
virtual void AliveNotification(LPCWSTR pszUSN, LPCWSTR pszLocation, LPCWSTR pszNls, DWORD dwLifeTime);
private:
DWORD dwCookie;
LONG lRefCount;
BOOL fReleasing;
ce::critical_section cs;
ce::auto_handle hEventRelease;
};
class CUPnPDeviceFinder : public ce::DispatchImpl<IUPnPDeviceFinder, &IID_IUPnPDeviceFinder>,
public SVSSynch
{
public:
CUPnPDeviceFinder()
: _pfcbFirst(NULL)
{}
DEFAULT_CLASS_REGISTRY_TABLE(CUPnPDeviceFinder,
TEXT("{E2085F28-FEB7-404A-B8E7-E659BDEAAA02}"), // CLSID
TEXT("UPnP DeviceFinder Class"), // friendly name
TEXT("UPnP.UPnPDeviceFinder.1"), // ProgID
TEXT("UPnP.UPnPDeviceFinder"), // version independent ProgID
TEXT("Both")) // threading model
// implement GetInterfaceTable
BEGIN_INTERFACE_TABLE(CUPnPDeviceFinder)
IMPLEMENTS_INTERFACE(IUPnPDeviceFinder)
IMPLEMENTS_INTERFACE(IDispatch)
END_INTERFACE_TABLE()
// implement QueryInterface/AddRef/Release
IMPLEMENT_UNKNOWN(CUPnPDeviceFinder);
// implement static CreateInstance(IUnknown *, REFIID, void**)
IMPLEMENT_CREATE_INSTANCE(CUPnPDeviceFinder);
// implement static GetClassObject(REFIID, void **) that uses a GenericClassFactory
IMPLEMENT_GENERIC_CLASS_FACTORY(CUPnPDeviceFinder);
public:
// IUPnPDeviceFinder
STDMETHOD(FindByType)(/* [in] */ BSTR bstrTypeURI,
/* [in] */ DWORD dwFlags,
/* [out, retval] */ IUPnPDevices ** pDevices);
STDMETHOD(CreateAsyncFind)(/* [in] */ BSTR bstrTypeURI,
/* [in] */ DWORD dwFlags,
/* [in] */ IUnknown __RPC_FAR *punkDeviceFinderCallback,
/* [retval][out] */ LONG __RPC_FAR *plFindData);
STDMETHOD(StartAsyncFind)(/* [in] */ LONG lFindData);
STDMETHOD(CancelAsyncFind)(/* [in] */ LONG lFindData);
STDMETHOD(FindByUDN)(/*[in]*/ BSTR bstrUDN,
/*[out, retval]*/ IUPnPDevice ** ppDevice);
protected:
HRESULT Find(BSTR bstrType, IUPnPDevices **ppDevices, IUPnPDevice **pDevice);
private:
FinderCallback *_pfcbFirst;
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -