Moore's Mind

Wednesday, October 05, 2005

Tripp Parks's WebLog : Most Annoying API

Tripp Park posted this message about the most annoying Windows API to use.

All I can say is: " I feel your pain ".

I've been working on implementing the Peer Name Resolution functions from C# via Interop and this one is definitely giving me some trouble. PNRP is the foundation for finding peers via the PeerGraph and PeerGroup API sets.

The following code *does not* appear to work.

CSADDR_INFO csaAddr = new CSADDR_INFO();
PNRPINFO pnrpInfo = new PNRPINFO();
BLOB blPnrpData = new BLOB();
WSAQUERYSET querySet = new WSAQUERYSET();
//
// fill a CSADDR_INFO structure from the address
//
csaAddr.iProtocol = 6; // IPPROTO_TCP
csaAddr.iSocketType = 1; // SOCK_STREAM;
csaAddr.LocalAddr.iSockaddrLength = Marshal.SizeOf(typeof(SOCKADDR_IN6));
SOCKADDR_IN6 address = new SOCKADDR_IN6();
address.sin6_addr = Registration.Address.GetAddressBytes();
csaAddr.LocalAddr.lpSockaddr = Marshal.AllocHGlobal(csaAddr.LocalAddr.iSockaddrLength);
Marshal.StructureToPtr(address, csaAddr.LocalAddr.lpSockaddr, false);
//
// build the WSAQUERYSET required to register
//
pnrpInfo.dwSize = Marshal.SizeOf(typeof(PNRPINFO));
pnrpInfo.dwLifetime = Lifetime;
pnrpInfo.lpwszIdentity = Registration.PeerId;
blPnrpData.cbSize = Marshal.SizeOf(typeof(PNRPINFO));
blPnrpData.pBlobData = Marshal.AllocHGlobal(blPnrpData.cbSize);
Marshal.StructureToPtr(pnrpInfo, blPnrpData.pBlobData, false);
querySet.dwSize = Marshal.SizeOf(typeof(WSAQUERYSET));
querySet.dwNameSpace = 38; // NS_PNRPNAME
querySet.dwNumberOfCsAddrs = 1; // one address

querySet.lpServiceClassId = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
Marshal.StructureToPtr(SVCID_PNRPNAMEV1, querySet.lpServiceClassId, false);

querySet.lpszServiceInstanceName = Registration.Name;
querySet.lpszContext = Registration.CloudName;
querySet.lpszComment = Registration.Comment;

querySet.lpcsaBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CSADDR_INFO)));
Marshal.StructureToPtr(csaAddr, querySet.lpcsaBuffer, false);

querySet.lpBlob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BLOB)));
Marshal.StructureToPtr(blPnrpData, querySet.lpBlob, false);

IntPtr qryptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WSAQUERYSET)));
Marshal.StructureToPtr(querySet, qryptr, false);

uint hr = PnrpNative.WSASetService(qryptr, WSAESETSERVICEOP.Register, 0);
if (hr != 0) throw new System.Net.Sockets.SocketException((int)hr);

Here are the structure definitions:


[StructLayout(LayoutKind.Sequential)]
internal struct SOCKET_ADDRESS
{
public IntPtr lpSockaddr; // LPSOCKADDR
public int iSockaddrLength;
};
[StructLayout(LayoutKind.Sequential)]
internal struct CSADDR_INFO
{
public SOCKET_ADDRESS LocalAddr;
public SOCKET_ADDRESS RemoteAddr;
public int iSocketType;
public int iProtocol;
};
[StructLayout(LayoutKind.Sequential)]
internal struct BLOB
{
public int cbSize;
public IntPtr pBlobData;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
internal struct WSAQUERYSET
{
public int dwSize;
public string lpszServiceInstanceName;
public IntPtr lpServiceClassId; // LPGUID
public IntPtr lpVersion; // LPWSAVERSION
public string lpszComment;
public int dwNameSpace;
public IntPtr lpNSProviderId; // LPGUID
public string lpszContext;
public int dwNumberOfProtocols;
public IntPtr lpafpProtocols; // LPAFPROTOCOLS
public IntPtr lpszQueryString; // can be NULL
public int dwNumberOfCsAddrs;
public IntPtr lpcsaBuffer; // LPCSADDR_INFO
public int dwOutputFlags;
public IntPtr lpBlob; // LPBLOB
};


[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
internal struct PNRPINFO
{
public int dwSize;
public string lpwszIdentity;
public int nMaxResolve;
public int dwTimeout;
public int dwLifetime;
public PNRP_RESOLVE_CRITERIA enResolveCriteria;
public int dwFlags;
public SOCKET_ADDRESS saHint;
public PNRP_REGISTERED_ID_STATE enNameState;
}

If anyone get's this working, please share...

5 Comments:

  • At 5:51 AM, Blogger darrylant said…

    Creating and promoting your own Podcast
    Posted on Wednesday, October 05 2005 @ 05:31:16 CEST by LSDsmurf The TechZone has posted a Step-by-Step Guide to Making and Promoting Your Own Podcast Think of it like an audio blog; a podcast is a recorded ...
    Hello, I seemed to have stumbled upon your blog by accident but it sure does make interest reading. I was actually surfing for more information on hotel in motel oregon sale. Still I’m glad I stopped by!

     
  • At 3:15 PM, Blogger Tripp Parks said…

    I do have it working, but lets see if we can track down whats happening here.

    PnrpNative.WSASetService doesnt return an hresult, its a winsock api, which either returns 0 or -1 (INVALID_SOCKET), you then have to call WSAGetLastError(which you also need to marshal. It will probably return 271e indicating invalid argument

    I dont see anything obvious thats causing the error, Whats the peer name you are trying to register?

    do you have a small program that demonstrates the failure?

     
  • At 8:36 AM, Blogger Ad. said…

    Turns out I was setting the ServiceInstance to an invalid value. I've got it working now.

     
  • At 2:16 PM, Blogger Rod Pendergrass said…

    I enjoyed reading some of your posts. I have a
    hypertension remedies site. It
    covers everything about hypertension remedies. Come and check it out if you get time :-)

    Rod

     
  • At 2:16 PM, Blogger Vm said…

    IBM says it won't advertise on blogs...but wants its workers to be bloggers
    IBM, the world's largest computer company says that it has decided not to advertise on blogs.
    equity line of credit

     

Post a Comment

<< Home