C++ での非同期検索
次のコードは、デバイスを非同期的に検索する C++ アプリケーションの基礎として使用できます。 このコードでは、 IUPnPDeviceFinderCallback インターフェイスを実装します。このインターフェイスから継承するクラスを作成します。
IUPnPDeviceFinderCallback と IUPnPDeviceFinderAddCallbackWithInterface の両方を実装するには、クラスが両方のインターフェイスから継承する必要があります。 IUPnPDeviceFinderAddCallbackWithInterface の実装は省略可能ですが、実装する場合は、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;
}