📄 finder.cpp
字号:
pfcb->Lock();
}
else
ASSERT(FALSE);
pfcb->Unlock();
pfcb->Release();
}
void FinderCallback::PerformCallback(SSDP_CALLBACK_TYPE cbType, BSTR bstrUDN, IUPnPDevice* pUPnPDevice)
{
HRESULT hr;
if(fDispatch)
{
ce::variant varResult;
ce::variant avarArgs[3];
avarArgs[0].vt = VT_I4;
switch(cbType)
{
case SSDP_ALIVE:
case SSDP_FOUND:
ASSERT(pUPnPDevice);
// 1st argument is pointer to device object
avarArgs[2].vt = VT_DISPATCH;
pUPnPDevice->QueryInterface(IID_IDispatch, (LPVOID *)(&avarArgs[2].pdispVal));
// 2nd argument is device UDN
avarArgs[1] = bstrUDN;
// 3rd argument is type of callback
V_I4(&avarArgs[0]) = 0;
break;
case SSDP_BYEBYE:
// 1st argument not used for "device removed" callback
// 2nd argument is device UDN
avarArgs[1] = bstrUDN;
// 3rd argument is type of callback - string "1" indicates "device removed"
V_I4(&avarArgs[0]) = 1;
break;
case SSDP_DONE:
// 1st argument not used for "search complete" callback
// 2nd argument not used for "search complete" callback
// 3rd argument is type of callback - string "2" indicates "search complete"
V_I4(&avarArgs[0]) = 2;
DEBUGMSG(ZONE_CALLBACK, (L"UPNP:ServiceCallback-Search complete.\n"));
break;
default:
ASSERT(FALSE);
break;
}
DISPPARAMS dispParams = {0};
dispParams.rgvarg = &avarArgs[0];
dispParams.cArgs = 3;
hr = cb.pDispatch->Invoke(DISPID_VALUE, IID_NULL, 0, DISPATCH_METHOD, &dispParams, &varResult, NULL, NULL);
if (hr != S_OK)
{
DEBUGMSG(ZONE_ERROR, (L"UPNP:Invoke on DeviceFinderCallback returns 0x%08x\n", hr));
}
}
else
{
switch(cbType)
{
case SSDP_ALIVE:
case SSDP_FOUND:
ASSERT(pUPnPDevice);
hr = cb.pCallback->DeviceAdded((LONG)this, pUPnPDevice);
break;
case SSDP_BYEBYE:
hr = cb.pCallback->DeviceRemoved((LONG)this, bstrUDN);
break;
case SSDP_DONE:
hr = cb.pCallback->SearchComplete((LONG)this);
DEBUGMSG(ZONE_CALLBACK, (L"UPNP:ServiceCallback-Search complete.\n"));
break;
default:
ASSERT(FALSE);
break;
}
}
}
// Find
HRESULT CUPnPDeviceFinder::Find(BSTR bstrSearchTarget, IUPnPDevices **ppDevices, IUPnPDevice **ppDevice)
{
ASSERT((ppDevices != NULL) ^ (ppDevice != NULL)); //exactly one of them has to be NULL
HRESULT hr = E_FAIL;
ce::auto_xxx<HANDLE, BOOL (__stdcall *)(HANDLE), FindServicesClose, INVALID_HANDLE_VALUE> hFind;
ce::string strSearchTarget;
// ANSI code page for URI
ce::WideCharToMultiByte(CP_ACP, bstrSearchTarget, -1, &strSearchTarget);
// find services
hFind = FindServices(strSearchTarget, NULL, TRUE);
if(!hFind.valid())
{
DEBUGMSG(ZONE_ERROR, (L"FindServices returns INVALID_HANDLE_VALUE\n"));
return HrFromLastWin32Error();
}
Devices* pDevices = NULL;
if(ppDevices)
{
// create output collection
pDevices = new Devices();
if(!pDevices)
return E_OUTOFMEMORY;
}
PSSDP_MESSAGE pService = NULL;
// iterate through found services
for(BOOL bContinue = GetFirstService(hFind, &pService); bContinue && pService; bContinue = GetNextService(hFind, &pService))
{
IFDBG(DumpSSDPMessage(pService));
IUPnPDevice *pUPnPDevice = NULL;
// get device for the service
if(SUCCEEDED(hr = GetUPnPDevice(pService->szUSN, pService->szLocHeader, pService->iLifeTime, &pUPnPDevice)))
{
ASSERT(pUPnPDevice);
if(ppDevice)
{
// searching by UDN - there should be just one result
// return as soon as we find one
*ppDevice = pUPnPDevice;
break;
}
else
{
ASSERT(pDevices);
// searching by type - there might be multiply results
// add found device to collection
ce::auto_bstr bstrUDN;
pUPnPDevice->get_UniqueDeviceName(&bstrUDN);
pDevices->AddItem(bstrUDN, pUPnPDevice);
}
pUPnPDevice->Release();
}
}
if(pDevices)
if(SUCCEEDED(hr))
hr = pDevices->QueryInterface(IID_IUPnPDevices, (void**)ppDevices);
else
delete pDevices;
return hr;
}
// FindByType
STDMETHODIMP
CUPnPDeviceFinder::FindByType( /* [in] */ BSTR bstrTypeURI,
/* [in] */ DWORD dwFlags,
/* [out, retval] */ IUPnPDevices ** ppDevices)
{
DEBUGMSG(ZONE_FINDER, (L"IUPnPDeviceFinder::FindByType(bstrTypeURI=%s, dwFlags=0x%08x).\n", bstrTypeURI, dwFlags));
return Find(bstrTypeURI, ppDevices, NULL);
}
// FindByUDN
STDMETHODIMP
CUPnPDeviceFinder::FindByUDN( /*[in]*/ BSTR bstrUDN,
/*[out, retval]*/ IUPnPDevice ** ppDevice)
{
DEBUGMSG(ZONE_FINDER, (L"IUPnPDeviceFinder::FindByUDN(bstrTypeUDN=%s).\n", bstrUDN));
return Find(bstrUDN, NULL, ppDevice);
}
// CreateAsyncFind
STDMETHODIMP
CUPnPDeviceFinder::CreateAsyncFind( /* [in] */ BSTR bstrTypeURI,
/* [in] */ DWORD dwFlags,
/* [in] */ IUnknown __RPC_FAR *punkDeviceFinderCallback,
/* [retval][out] */ LONG __RPC_FAR *plFindData)
{
CHECK_POINTER(plFindData);
CHECK_POINTER(punkDeviceFinderCallback);
CHECK_POINTER(bstrTypeURI);
FinderCallback *pfcb = new FinderCallback;
if (!pfcb)
return E_OUTOFMEMORY;
pfcb->dwSig = FINDERCBSIG;
pfcb->bstrSearchTarget = SysAllocString(bstrTypeURI);
pfcb->dwFlags = dwFlags;
pfcb->fDispatch = FALSE;
if(!pfcb->Valid())
{
pfcb->Release();
return E_FAIL;
}
if (FAILED(punkDeviceFinderCallback->QueryInterface(IID_IUPnPDeviceFinderCallback, (LPVOID *)&(pfcb->cb.pCallback))))
{
pfcb->fDispatch = TRUE;
if (FAILED(punkDeviceFinderCallback->QueryInterface(IID_IDispatch, (LPVOID *)&(pfcb->cb.pDispatch))))
{
DEBUGMSG(ZONE_ERROR|ZONE_FINDER, (L"IUPnPDeviceFinder::CreateAsyncFind:punkDeviceFinderCallback supports neither IDispatch nor IUPnPDeviceFinderCallback.\n"));
pfcb->Release();
return E_FAIL;
}
}
pfcb->hFind = INVALID_HANDLE_VALUE;
Lock();
pfcb->pNext = _pfcbFirst;
_pfcbFirst = pfcb;
Unlock();
*plFindData = (LONG)pfcb;
return S_OK;
}
// StartAsyncFind
STDMETHODIMP
CUPnPDeviceFinder::StartAsyncFind(/* [in] */ LONG lFindData)
{
Lock();
FinderCallback *pfcb = _pfcbFirst;
FinderCallback *pfcbPrev = NULL;
// look for the async find object
while (pfcb && (lFindData != (LONG )pfcb))
{
pfcbPrev = pfcb;
pfcb = pfcb->pNext;
}
if (!pfcb)
{
DEBUGMSG(ZONE_ERROR|ZONE_FINDER, (L"IUPnPDeviceFinder::StartAsyncFind:Invalid cookie-%d.\n", lFindData));
Unlock();
return E_INVALIDARG;
}
ce::string strSearchTarget;
// ANSI code page for search target
ce::WideCharToMultiByte(CP_ACP, pfcb->bstrSearchTarget, -1, &strSearchTarget);
pfcb->start_listening();
pfcb->hFind = FindServicesCallback(strSearchTarget, NULL, TRUE, ServiceCallback, pfcb);
DEBUGMSG(ZONE_FINDER, (L"IUPnPDeviceFinder::StartAsyncFind:FindServicesCallback returns handle=0x%08x.\n", pfcb->hFind));
// The find is cancelled if StartAsyncFind fails
HRESULT hr = S_OK;
if (pfcb->hFind == INVALID_HANDLE_VALUE)
{
pfcb->stop_listening();
hr = HrFromLastWin32Error();
if (!pfcbPrev)
_pfcbFirst = pfcb->pNext;
else
pfcbPrev->pNext = pfcb->pNext;
pfcb->Release();
}
Unlock();
return hr;
}
// CancelAsyncFind
STDMETHODIMP
CUPnPDeviceFinder::CancelAsyncFind(/* [in] */ LONG lFindData)
{
Lock();
FinderCallback *pfcb = _pfcbFirst;
FinderCallback *pfcbPrev = NULL;
// look for the async find object
while (pfcb && (lFindData != (LONG )pfcb))
{
pfcbPrev = pfcb;
pfcb = pfcb->pNext;
}
if (!pfcb)
{
DEBUGMSG(ZONE_ERROR|ZONE_FINDER, (L"IUPnPDeviceFinder::CancelAsyncFind:Invalid cookie-%d.\n", lFindData));
Unlock();
return E_INVALIDARG;
}
// release find object resources
if (pfcb->hFind != INVALID_HANDLE_VALUE)
FindServicesClose(pfcb->hFind);
// remove find object from the list
if (!pfcbPrev)
_pfcbFirst = pfcb->pNext;
else
pfcbPrev->pNext = pfcb->pNext;
Unlock();
// release find object
pfcb->FinalRelease();
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -