Resolving a Peer Name
This topic discusses methods for resolving a peer name using the PNRP Namespace Provider APIs.
When you resolve a peer name, you must provide the following information:
- Peer name
- Resolve criteria
- Cloud name in which to resolve the peer name
- IP address, which is optional and is used as a hint
Resolving a Peer Name
After you provide a peer name, resolve criteria, cloud name, and the optional IP address, the following steps must be taken to complete the resolution of a peer name:
- Call WSALookupServiceBegin to begin the process and return a handle.
- Call WSALookupServiceNext to resolve the peer name.
- Call WSALookupServiceEnd to complete the process.
An Example of Resolving a Peer Name
The following code snippet shows you how to resolve a peer name. There is an assumption in the sample that a TCP/IP address will be returned.
#define UNICODE
#include <initguid.h>
#include <p2p.h>
#pragma comment( lib, "ws2_32.lib")
// Function: PnrpResolve
//
// Purpose: Resolve the given name within a PNRP cloud
//
// Arguments:
// pwzName : name to resolve in PNRP, generally the graph id
// pwzCloud : name of cloud to resolve in, NULL = global cloud
// pAddr : pointer to result buffer
//
// Returns: HRESULT
//
HRESULT PnrpResolve(PWSTR pwzName, PWSTR pwzCloud, SOCKADDR_IN6* pAddr)
{
HRESULT hr = S_OK;
PNRPINFO pnrpInfo = {0};
BLOB blPnrpData = {0};
WSAQUERYSET querySet = {0};
WSAQUERYSET* pResults = NULL;
WSAQUERYSET tempResultSet = {0};
HANDLE hLookup = NULL;
BOOL fFound = FALSE;
DWORD dwError;
INT iRet;
ULONG i;
DWORD dwSize = 0;
//
// fill in the WSAQUERYSET
//
pnrpInfo.dwSize = sizeof(pnrpInfo);
pnrpInfo.nMaxResolve = 1;
pnrpInfo.dwTimeout = 30;
pnrpInfo.enResolveCriteria = PNRP_RESOLVE_CRITERIA_NON_CURRENT_PROCESS_PEER_NAME;
blPnrpData.cbSize = sizeof(pnrpInfo);
blPnrpData.pBlobData = (BYTE*)&pnrpInfo;
querySet.dwSize = sizeof(querySet);
querySet.dwNameSpace = NS_PNRPNAME;
querySet.lpServiceClassId = (LPGUID)&SVCID_PNRPNAME;
querySet.lpszServiceInstanceName = pwzName;
querySet.lpszContext = pwzCloud;
querySet.lpBlob = &blPnrpData;
// start resolve
iRet = WSALookupServiceBegin(
&querySet,
LUP_RETURN_NAME | LUP_RETURN_ADDR | LUP_RETURN_COMMENT,
&hLookup);
if (iRet != 0)
{
hr = HRESULT_FROM_WIN32(WSAGetLastError());
}
if (SUCCEEDED(hr))
{
dwSize = sizeof(tempResultSet);
// retrieve the required size
iRet = WSALookupServiceNext(hLookup, 0, &dwSize, &tempResultSet);
dwError = WSAGetLastError();
if (dwError == WSAEFAULT)
{
// allocate space for the results
pResults = (WSAQUERYSET*)malloc(dwSize);
if (pResults == NULL)
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = HRESULT_FROM_WIN32(dwError);
}
}
if (SUCCEEDED(hr))
{
// retrieve the addresses
iRet = WSALookupServiceNext(hLookup, 0, &dwSize, pResults);
if (iRet != 0)
{
hr = HRESULT_FROM_WIN32(WSAGetLastError());
}
}
if (SUCCEEDED(hr))
{
// return the first IPv6 address found
for (i = 0; i < pResults->dwNumberOfCsAddrs; i++)
{
if (pResults->lpcsaBuffer[i].iProtocol == IPPROTO_TCP &&
pResults->lpcsaBuffer[i].RemoteAddr.iSockaddrLength == sizeof(SOCKADDR_IN6))
{
CopyMemory(pAddr, pResults->lpcsaBuffer[i].RemoteAddr.lpSockaddr, sizeof(SOCKADDR_IN6));
fFound = TRUE;
break;
}
}
if (!fFound)
{
// unable to find an IPv6 address
hr = HRESULT_FROM_WIN32(WSA_E_NO_MORE);
}
}
if (hLookup != NULL)
{
WSALookupServiceEnd(hLookup);
}
if (pResults != NULL)
{
free(pResults);
}
return hr;
}