Ricerca asincrona in C++
Il codice seguente può essere usato come base per un'applicazione C++ che cerca i dispositivi in modo asincrono. Il codice implementa l'interfaccia IUPnPDeviceFinderCallback creando una classe che eredita da essa.
Per implementare sia IUPnPDeviceFinderCallback che IUPnPDeviceFinderAddCallbackWithInterface, la classe deve ereditare da entrambe le interfacce. L'implementazione di IUPnPDeviceFinderAddCallbackWithInterface è facoltativa, ma se si sceglie di implementarla, è necessario implementare anche IUPnPDeviceFinderCallback.
#include <windows.h>
#include <upnp.h>
#include <stdio.h>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")
#pragma comment(lib, "user32.lib")
class CUPnPDeviceFinderCallback : public IUPnPDeviceFinderCallback
{
public:
CUPnPDeviceFinderCallback()
{
m_lRefCount = 0;
};
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject)
{
HRESULT hr = S_OK;
if(NULL == ppvObject)
{
hr = E_POINTER;
}
else
{
*ppvObject = NULL;
}
if(SUCCEEDED(hr))
{
if(IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IUPnPDeviceFinderCallback))
{
*ppvObject = static_cast<IUPnPDeviceFinderCallback*>(this);
AddRef();
}
else
{
hr = E_NOINTERFACE;
}
}
return hr;
};
STDMETHODIMP_(ULONG) AddRef()
{
return ::InterlockedIncrement(&m_lRefCount);
};
STDMETHODIMP_(ULONG) Release()
{
LONG lRefCount = ::InterlockedDecrement(&m_lRefCount);
if(0 == lRefCount)
{
delete this;
}
return lRefCount;
};
STDMETHODIMP DeviceAdded(LONG lFindData, IUPnPDevice* pDevice)
{
HRESULT hr = S_OK;
//You should save pDevice so that it is accessible outside the scope of this method.
BSTR UniqueDeviceName;
hr = pDevice->get_UniqueDeviceName(&UniqueDeviceName);
if (SUCCEEDED(hr))
{
BSTR FriendlyName;
hr = pDevice->get_FriendlyName(&FriendlyName);
if (SUCCEEDED(hr))
{
printf("Device Added: udn: %S, name: %S\n", FriendlyName, UniqueDeviceName);
::SysFreeString(FriendlyName);
}
::SysFreeString(UniqueDeviceName);
}
return hr;
};
STDMETHODIMP DeviceRemoved(LONG lFindData, BSTR bstrUDN)
{
printf("Device Removed: udn: %S", bstrUDN);
return S_OK;
};
STDMETHODIMP SearchComplete(LONG lFindData)
{
return S_OK;
};
private:
LONG m_lRefCount;
};
HRESULT FindUPnPDevice(BSTR TypeURI)
{
HRESULT hr = S_OK;
IUPnPDeviceFinderCallback* pUPnPDeviceFinderCallback = new CUPnPDeviceFinderCallback();
if(NULL != pUPnPDeviceFinderCallback)
{
pUPnPDeviceFinderCallback->AddRef();
IUPnPDeviceFinder* pUPnPDeviceFinder;
hr = CoCreateInstance(CLSID_UPnPDeviceFinder, NULL, CLSCTX_INPROC_SERVER,
IID_IUPnPDeviceFinder, reinterpret_cast<void**>(&pUPnPDeviceFinder));
if(SUCCEEDED(hr))
{
LONG lFindData;
hr = pUPnPDeviceFinder->CreateAsyncFind(TypeURI, 0, pUPnPDeviceFinderCallback, &lFindData);
if(SUCCEEDED(hr))
{
hr = pUPnPDeviceFinder->StartAsyncFind(lFindData);
if(SUCCEEDED(hr))
{
// STA threads must pump messages
MSG Message;
BOOL bGetMessage;
while(bGetMessage = GetMessage(&Message, NULL, 0, 0) && -1 != bGetMessage)
{
DispatchMessage(&Message);
}
}
pUPnPDeviceFinder->CancelAsyncFind(lFindData);
}
pUPnPDeviceFinder->Release();
}
pUPnPDeviceFinderCallback->Release();
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}