summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/gtadrnr.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/gtadrnr.c')
-rw-r--r--private/nw/svcdlls/nwwks/client/gtadrnr.c1935
1 files changed, 1935 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/gtadrnr.c b/private/nw/svcdlls/nwwks/client/gtadrnr.c
new file mode 100644
index 000000000..7b2227c11
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/gtadrnr.c
@@ -0,0 +1,1935 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ gtsadrnr.c
+
+Abstract:
+
+ This module contains the code to support the new RnR APIs. Some
+ support code is in getaddr.c, but the interface routines and
+ routines specific to RnR2 are herein.
+
+Author:
+
+ ArnoldM 4-Dec-1995
+Revision History:
+
+ ArnoldM Created
+
+--*/
+
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include "ncp.h"
+#include <rpc.h>
+#include <winsock2.h>
+#include <ws2spi.h>
+#include <wsipx.h>
+#include <rnrdefs.h>
+#include <svcguid.h>
+#include <rnraddrs.h>
+
+
+//-------------------------------------------------------------------//
+// //
+// Globals in getaddr.c and provider .c //
+// //
+//-------------------------------------------------------------------//
+
+DWORD
+NwpGetAddressByName(
+ IN LPWSTR Reserved,
+ IN WORD nServiceType,
+ IN LPWSTR lpServiceName,
+ IN OUT LPSOCKADDR_IPX lpsockaddr
+);
+
+DWORD
+NwpGetAddressViaSap(
+ IN WORD nServiceType,
+ IN LPWSTR lpServiceName,
+ IN DWORD nProt,
+ IN OUT LPVOID lpCsAddrBuffer,
+ IN OUT LPDWORD lpdwBufferLength,
+ IN HANDLE hCancellationEvent,
+ OUT LPDWORD lpcAddress
+);
+
+DWORD
+NwpRnR2AddServiceType(
+ IN LPWSTR lpServiceTypeName,
+ IN LPGUID lpClassType,
+ IN WORD wSapId,
+ IN WORD wPort
+);
+
+
+DWORD
+SapFreeSapSocket(
+ SOCKET s
+ );
+
+PSAP_RNR_CONTEXT
+SapMakeContext
+ (
+ IN HANDLE Handle,
+ DWORD dwExcess
+ );
+
+BOOL
+NwpLookupSapInRegistry(
+ IN LPGUID lpServiceType,
+ OUT PWORD pnSapType,
+ OUT PWORD pwPort,
+ IN OUT PDWORD pfConnectionOriented
+);
+
+PSAP_RNR_CONTEXT
+SapGetContext(
+ HANDLE h
+ );
+
+DWORD
+DoASap(
+ IN PSAP_RNR_CONTEXT psrcContext,
+ IN WORD QueryType,
+ IN PBYTE * ppData,
+ IN LPWSAQUERYSETW lpqsResults,
+ IN PLONG pl,
+ IN PDWORD pdw
+ );
+
+VOID
+SapReleaseContext(
+ IN PSAP_RNR_CONTEXT psrcContext
+ );
+
+DWORD
+SapGetSapSocket(
+ SOCKET * ps
+ );
+
+DWORD
+PrepareForSap(
+ IN PSAP_RNR_CONTEXT psrc
+ );
+
+DWORD
+SapGetSapForType(
+ PSAP_BCAST_CONTROL psbc,
+ WORD nServiceType
+ );
+
+DWORD
+FillBufferWithCsAddr(
+ IN LPBYTE pAddress,
+ IN DWORD nProt,
+ IN OUT LPVOID lpCsAddrBuffer,
+ IN OUT LPDWORD lpdwBufferLength,
+ OUT LPDWORD pcAddress
+ );
+
+DWORD
+pSapSetService2(
+ IN DWORD dwOperation,
+ IN LPWSTR lpszServiceInstanceName,
+ IN PBYTE pbAddress,
+ IN LPGUID pServiceType,
+ IN WORD nServiceType
+ );
+
+DWORD
+NwpGetRnRAddress(
+ PHANDLE phServer,
+ PWCHAR pwszContext,
+ PLONG plIndex,
+ LPWSTR lpServiceName,
+ WORD nServiceType,
+ PDWORD pdwVersion,
+ DWORD dwInSize,
+ LPWSTR OutName,
+ SOCKADDR_IPX * pSockAddr
+ );
+
+
+DWORD
+NwpSetClassInfo(
+ IN LPWSTR lpwszClassName,
+ IN LPGUID lpClassId,
+ IN PCHAR lpbProp
+ );
+
+VOID
+pFreeAllContexts();
+
+extern DWORD oldRnRServiceRegister, oldRnRServiceDeRegister;
+//-------------------------------------------------------------------//
+// //
+// Local Function Prototypes //
+// //
+//-------------------------------------------------------------------//
+
+INT WINAPI
+pGetServiceClassInfo(
+ IN LPGUID lpProviderId,
+ IN OUT LPDWORD lpdwBufSize,
+ IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo,
+ IN PBOOL pfAdvert
+);
+
+DWORD
+NwpSetClassInfoAdvertise(
+ IN LPGUID lpClassType,
+ IN WORD wSapId
+);
+
+BOOL
+NSPpCheckCancel(
+ PVOID pvArg
+ );
+
+DWORD
+NSPpGotSap(
+ PSAP_BCAST_CONTROL psbc,
+ PSAP_IDENT_HEADER pSap,
+ PDWORD pdwErr
+ );
+
+INT WINAPI
+NSPLookupServiceBegin(
+ IN LPGUID lpProviderId,
+ IN LPWSAQUERYSETW lpqsRestrictions,
+ IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
+ IN DWORD dwControlFlags,
+ OUT LPHANDLE lphLookup
+ );
+
+INT WINAPI
+NSPLookupServiceNext(
+ IN HANDLE hLookup,
+ IN DWORD dwControlFlags,
+ IN OUT LPDWORD lpdwBufferLength,
+ OUT LPWSAQUERYSETW lpqsResults
+ );
+
+INT WINAPI
+NSPUnInstallNameSpace(
+ IN LPGUID lpProviderId
+ );
+
+INT WINAPI
+NSPCleanup(
+ IN LPGUID lpProviderId
+ );
+
+INT WINAPI
+NSPLookupServiceEnd(
+ IN HANDLE hLookup
+ );
+
+INT WINAPI
+NSPSetService(
+ IN LPGUID lpProviderId,
+ IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
+ IN LPWSAQUERYSETW lpqsRegInfo,
+ IN WSAESETSERVICEOP essOperation,
+ IN DWORD dwControlFlags
+ );
+
+INT WINAPI
+NSPInstallServiceClass(
+ IN LPGUID lpProviderId,
+ IN LPWSASERVICECLASSINFOW lpServiceClassInfo
+ );
+
+INT WINAPI
+NSPRemoveServiceClass(
+ IN LPGUID lpProviderId,
+ IN LPGUID lpServiceCallId
+ );
+
+INT WINAPI
+NSPGetServiceClassInfo(
+ IN LPGUID lpProviderId,
+ IN OUT LPDWORD lpdwBufSize,
+ IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
+ );
+//-------------------------------------------------------------------//
+// //
+// Data definitions //
+// //
+//-------------------------------------------------------------------//
+
+NSP_ROUTINE nsrVector = {
+ sizeof(NSP_ROUTINE),
+ 1, // major version
+ 1, // minor version
+ NSPCleanup,
+ NSPLookupServiceBegin,
+ NSPLookupServiceNext,
+ NSPLookupServiceEnd,
+ NSPSetService,
+ NSPInstallServiceClass,
+ NSPRemoveServiceClass,
+ NSPGetServiceClassInfo
+ };
+
+static
+GUID HostnameGuid = SVCID_HOSTNAME;
+
+static
+GUID InetHostname = SVCID_INET_HOSTADDRBYNAME;
+
+static
+GUID AddressGuid = SVCID_INET_HOSTADDRBYINETSTRING;
+
+static
+GUID IANAGuid = SVCID_INET_SERVICEBYNAME;
+
+#define GuidEqual(x,y) RtlEqualMemory(x, y, sizeof(GUID))
+
+
+//------------------------------------------------------------------//
+// //
+// Function Bodies //
+// //
+//------------------------------------------------------------------//
+
+DWORD
+NwpSetClassInfoAdvertise(
+ IN LPGUID lpClassType,
+ IN WORD wSapId
+)
+{
+/*++
+Routine Description:
+ Start a class info advertise. Called upon a SetService call
+--*/
+ PWCHAR pwszUuid;
+ SOCKADDR_IPX sock;
+
+ UuidToString(lpClassType, &pwszUuid);
+
+ memset(&sock, 0, sizeof(sock));
+
+ *(PWORD)&sock.sa_netnum = htons(wSapId); // encode the ID here
+
+ return(pSapSetService2( oldRnRServiceRegister,
+ pwszUuid,
+ (PBYTE)&sock,
+ lpClassType,
+ RNRCLASSSAPTYPE));
+}
+
+DWORD
+pRnRReturnString(
+ IN PWCHAR pwszSrc,
+ IN OUT PBYTE *ppData,
+ IN OUT PLONG plBytes
+ )
+{
+/*++
+Routine Description:
+ Utility routine to pack a string into the spare buffer space,
+ update pointers and counts. If the string fits, it is copied. If
+ not, the pointer and count are still updated so the caller can
+ compute the additional space needed
+--*/
+
+ PBYTE pSave = *ppData;
+ LONG lLen = (wcslen(pwszSrc) + 1) * sizeof(WCHAR);
+
+ *ppData = pSave + lLen; // update the buffer pointer
+
+ *plBytes = *plBytes - lLen; // and the count
+
+ if(*plBytes >= 0)
+ {
+ //
+ // it fits.
+ //
+
+ RtlMoveMemory(pSave,
+ pwszSrc,
+ lLen);
+ return(NO_ERROR);
+ }
+ return(WSAEFAULT);
+}
+
+DWORD
+pLocateSapIdAndProtocls(
+ IN LPGUID lpClassInfoType,
+ IN DWORD dwNumClassInfo,
+ IN LPWSANSCLASSINFOW lpClassInfoBuf,
+ OUT PWORD pwSapId,
+ OUT PDWORD pdwnProt
+ )
+/*++
+Routine Description:
+ Locate the SAP ID entry and return it. Also return
+ the protocols support.
+--*/
+{
+ DWORD err = NO_ERROR;
+
+ if(GuidEqual(lpClassInfoType, &HostnameGuid)
+ ||
+ GuidEqual(lpClassInfoType, &InetHostname) )
+ {
+ *pwSapId = 0x4;
+ }
+ else if(IS_SVCID_NETWARE(lpClassInfoType))
+ {
+ *pwSapId = SAPID_FROM_SVCID_NETWARE(lpClassInfoType);
+ }
+ else
+ {
+ for(; dwNumClassInfo; dwNumClassInfo--, lpClassInfoBuf++)
+ {
+ //
+ // We have some class info data. Rummage through it
+ // looking for what we want
+ //
+
+ if(!_wcsicmp(SERVICE_TYPE_VALUE_SAPIDW, lpClassInfoBuf->lpszName)
+ &&
+ (lpClassInfoBuf->dwValueType == REG_DWORD)
+ &&
+ (lpClassInfoBuf->dwValueSize >= sizeof(WORD)))
+ {
+ //
+ // got it
+ //
+
+ *pwSapId = *(PWORD)lpClassInfoBuf->lpValue;
+ break;
+
+ }
+ }
+ if(!dwNumClassInfo)
+ {
+ err = WSA_INVALID_PARAMETER;
+ }
+ }
+ *pdwnProt = SPX_BIT | SPXII_BIT | IPX_BIT;
+ return(err);
+}
+DWORD
+pRnRReturnResults(
+ IN PWCHAR pwszString,
+ IN LPGUID pgdServiceClass,
+ IN DWORD dwVersion,
+ IN OUT PBYTE *ppData,
+ IN OUT PLONG plBytes,
+ IN PBYTE lpSockAddr,
+ IN DWORD nProt,
+ IN DWORD dwControlFlags,
+ OUT LPWSAQUERYSETW lpqsResults
+ )
+{
+/*++
+Routine Description:
+ Return the requested results
+--*/
+ DWORD err;
+
+ lpqsResults->dwNameSpace = NS_SAP;
+
+ if(dwControlFlags & LUP_RETURN_TYPE)
+ {
+
+ lpqsResults->lpServiceClassId = (LPGUID)*ppData;
+ *ppData += sizeof(GUID);
+ *plBytes -= sizeof(GUID);
+ if(*plBytes >= 0)
+ {
+ *lpqsResults->lpServiceClassId = *pgdServiceClass;
+ }
+ }
+
+ if(dwVersion
+ &&
+ (dwControlFlags & LUP_RETURN_VERSION) )
+ {
+ //
+ // have a verion, and the caller wants it
+ //
+
+ lpqsResults->lpVersion = (LPWSAVERSION)*ppData;
+ *ppData += sizeof(WSAVERSION);
+ *plBytes -= sizeof(WSAVERSION);
+ if(*plBytes >= 0)
+ {
+ //
+ // and it fits. So return it
+ //
+ lpqsResults->lpVersion->dwVersion = dwVersion;
+ lpqsResults->lpVersion->ecHow = COMP_EQUAL;
+ }
+ }
+
+ if(dwControlFlags & LUP_RETURN_ADDR)
+ {
+ DWORD dwCsAddrLen;
+
+ if(*plBytes >= 0)
+ {
+ dwCsAddrLen = (DWORD)*plBytes; // all of it for now
+ }
+ else
+ {
+ dwCsAddrLen = 0;
+ }
+ lpqsResults->lpcsaBuffer = (PVOID)*ppData;
+
+ err = FillBufferWithCsAddr(
+ lpSockAddr,
+ nProt,
+ (PVOID)lpqsResults->lpcsaBuffer,
+ &dwCsAddrLen,
+ &lpqsResults->dwNumberOfCsAddrs);
+
+ //
+ // see if it fit. Whether it did or not, compute the space available,
+ // align, and do the rest
+ //
+
+
+ if(err == NO_ERROR)
+ {
+ //
+ // if it worked, we have to compute the space taken
+ //
+
+ dwCsAddrLen = lpqsResults->dwNumberOfCsAddrs * (sizeof(CSADDR_INFO) +
+ 2*sizeof(SOCKADDR_IPX));
+ }
+ else if(err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ err = WSAEFAULT;
+ }
+
+ *plBytes = *plBytes - dwCsAddrLen;
+
+ *ppData = *ppData + dwCsAddrLen;
+ }
+ else
+ {
+ err = NO_ERROR;
+ }
+
+ //
+ // no padding needed.
+
+ if((dwControlFlags & LUP_RETURN_NAME))
+ {
+ lpqsResults->lpszServiceInstanceName = (LPWSTR)*ppData;
+ err = pRnRReturnString(
+ pwszString,
+ ppData,
+ plBytes);
+ }
+ if(pgdServiceClass)
+ {
+ //
+ // BUGBUG. Do we really return this?
+ //
+ }
+ return(err);
+}
+
+INT WINAPI
+NSPLookupServiceBegin(
+ IN LPGUID lpProviderId,
+ IN LPWSAQUERYSETW lpqsRestrictions,
+ IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
+ IN DWORD dwControlFlags,
+ OUT LPHANDLE lphLookup
+ )
+/*++
+Routine Description:
+ This is the RnR routine that begins a lookup.
+--*/
+{
+ PSAP_RNR_CONTEXT psrc;
+ int err;
+ DWORD nProt, nProt1;
+ OEM_STRING OemServiceName;
+ LPWSTR pwszContext;
+ WORD wSapid;
+ DWORD dwNumClassInfo;
+ LPWSANSCLASSINFOW lpClassInfoBuf;
+
+ if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW))
+ {
+ SetLastError(WSAEFAULT);
+ return(SOCKET_ERROR);
+ }
+
+ if(lpqsRestrictions->lpszContext
+ &&
+ (lpqsRestrictions->lpszContext[0] != 0)
+ &&
+ wcscmp(&lpqsRestrictions->lpszContext[0], L"\\") )
+ {
+ //
+ // if not the default context, we must copy it.
+ //
+ pwszContext = lpqsRestrictions->lpszContext;
+ }
+ else
+ {
+ //
+ // map all default contexts into "no context".
+ //
+ pwszContext = 0;
+ }
+
+ //
+ // Compute protocols to return, or return them all
+ //
+ if(lpqsRestrictions->lpafpProtocols)
+ {
+ //
+ // Make certain at least one IPX/SPX protocol is being requested
+ //
+
+ INT i;
+ DWORD dwNum = lpqsRestrictions->dwNumberOfProtocols;
+
+ nProt = 0;
+
+ for(i = 0; dwNum--;)
+ {
+
+ if((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_IPX)
+ ||
+ (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC)
+ )
+ {
+ switch(lpqsRestrictions->lpafpProtocols[i].iProtocol)
+ {
+ case NSPROTO_IPX:
+ nProt |= IPX_BIT;
+ break;
+ case NSPROTO_SPX:
+ nProt |= SPX_BIT;
+ break;
+ case NSPROTO_SPXII:
+ nProt |= SPXII_BIT;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if(!nProt)
+ {
+ //
+ // if the caller doesn't want IPX/SPX addresses, why bother?
+ //
+ SetLastError(WSANO_DATA);
+ return(SOCKET_ERROR);
+ }
+ }
+ else
+ {
+ nProt = IPX_BIT | SPX_BIT | SPXII_BIT;
+ }
+
+ if(dwControlFlags & LUP_CONTAINERS)
+ {
+ if(pwszContext)
+ {
+BadGuid:
+ SetLastError(WSANO_DATA);
+ return(SOCKET_ERROR); // can't handle containers in containers
+ }
+ wSapid = 0x4;
+ nProt1 = IPX_BIT;
+ err = NO_ERROR;
+ }
+ else
+ {
+
+ LPGUID pgClass = lpqsRestrictions->lpServiceClassId;
+
+ if(!pgClass
+ ||
+ GuidEqual(pgClass, &AddressGuid)
+ ||
+ GuidEqual(pgClass, &IANAGuid) )
+ {
+ goto BadGuid;
+ }
+
+ if(!lpqsRestrictions->lpszServiceInstanceName
+ ||
+ !*lpqsRestrictions->lpszServiceInstanceName)
+ {
+ SetLastError(WSA_INVALID_PARAMETER);
+ return(SOCKET_ERROR);
+ }
+ if(!lpServiceClassInfo)
+ {
+ dwNumClassInfo = 0;
+ }
+ else
+ {
+ dwNumClassInfo = lpServiceClassInfo->dwCount;
+ lpClassInfoBuf = lpServiceClassInfo->lpClassInfos;
+ }
+
+ err = pLocateSapIdAndProtocls(pgClass,
+ dwNumClassInfo,
+ lpClassInfoBuf,
+ &wSapid,
+ &nProt1);
+ if(err)
+ {
+ if(dwNumClassInfo)
+ {
+ SetLastError(err);
+ return(SOCKET_ERROR);
+ }
+ else
+ {
+ nProt1 = nProt;
+ wSapid = 0;
+ err = 0;
+ }
+ }
+ }
+
+ nProt &= nProt1; // the relevant protocols
+
+ if(!nProt)
+ {
+ SetLastError(WSANO_DATA);
+ return(SOCKET_ERROR);
+ }
+
+ //
+ // Make sure a class ID is given since we copy it
+ //
+
+ if(!lpqsRestrictions->lpServiceClassId)
+ {
+ //
+ // not. So, fail
+ //
+ SetLastError(WSA_INVALID_PARAMETER);
+ return(SOCKET_ERROR);
+ }
+
+ //
+ // It looks like a query we can handle. Make a context
+ // BUGBUG. What about version????
+ //
+
+ psrc = SapMakeContext(0,
+ sizeof(WSAVERSION) - sizeof(PVOID));
+
+ if(!psrc)
+ {
+ SetLastError(WSA_NOT_ENOUGH_MEMORY);
+ return(SOCKET_ERROR);
+ }
+
+ //
+ // save things
+ //
+
+ psrc->gdType = *lpqsRestrictions->lpServiceClassId;
+ psrc->dwControlFlags = dwControlFlags; // save for Next processing
+ psrc->wSapId = wSapid;
+
+ if(pwszContext)
+ {
+ wcscpy(psrc->wszContext, pwszContext);
+ }
+
+ //
+ // save the relevant restrictions
+ // if the name is a wild-card, don't copy it. A NULL name
+ // serves as a wild-card to NSPLookupServiceNext
+ //
+
+ if(lpqsRestrictions->lpszServiceInstanceName
+ &&
+ *lpqsRestrictions->lpszServiceInstanceName
+ &&
+ wcscmp(lpqsRestrictions->lpszServiceInstanceName, L"*"))
+ {
+ DWORD dwLen = wcslen(lpqsRestrictions->lpszServiceInstanceName);
+ if(dwLen > 48)
+ {
+ err = WSA_INVALID_PARAMETER;
+ goto Done;
+ }
+ else
+ {
+ RtlMoveMemory(psrc->chwName,
+ lpqsRestrictions->lpszServiceInstanceName,
+ dwLen * sizeof(WCHAR));
+ _wcsupr(psrc->chwName);
+ }
+ }
+
+ psrc->fConnectionOriented = (DWORD) -1;
+
+ *lphLookup = (HANDLE)psrc;
+ psrc->nProt = nProt;
+ psrc->gdProvider = *lpProviderId;
+ if(lpqsRestrictions->lpVersion)
+ {
+ *(LPWSAVERSION)&psrc->pvVersion = *lpqsRestrictions->lpVersion;
+ }
+
+Done:
+ SapReleaseContext(psrc);
+ if(err != NO_ERROR)
+ {
+ SapReleaseContext(psrc);
+ SetLastError(err);
+ err = SOCKET_ERROR;
+ }
+ return(err);
+}
+
+INT WINAPI
+NSPLookupServiceNext(
+ IN HANDLE hLookup,
+ IN DWORD dwControlFlags,
+ IN OUT LPDWORD lpdwBufferLength,
+ OUT LPWSAQUERYSETW lpqsResults
+ )
+/*++
+Routine Description:
+ The continuation of the LookupServiceBegin. Called to fetch
+ a matching item.
+Arguments:
+ See RnR spec
+--*/
+{
+ DWORD err = NO_ERROR;
+ PSAP_RNR_CONTEXT psrc;
+ SOCKADDR_IPX SockAddr;
+ WCHAR OutName[48];
+ PBYTE pData = (PBYTE)(lpqsResults + 1);
+ LONG lSpare;
+ LONG lLastIndex;
+ DWORD dwVersion;
+ WSAQUERYSETW wsaqDummy;
+ BOOL fDoStateMachine;
+
+ if(*lpdwBufferLength < sizeof(WSAQUERYSETW))
+ {
+ lpqsResults = &wsaqDummy;
+ }
+ lSpare = (LONG)*lpdwBufferLength - sizeof(WSAQUERYSETW);
+
+ memset(lpqsResults, 0, sizeof(WSAQUERYSETW));
+ lpqsResults->dwNameSpace = NS_SAP;
+ lpqsResults->dwSize = sizeof(WSAQUERYSETW);
+ psrc = SapGetContext(hLookup);
+ if(!psrc)
+ {
+
+ SetLastError(WSA_INVALID_HANDLE);
+ return(SOCKET_ERROR);
+ }
+
+ //
+ // This is a valid context. Determine whether this is the first
+ // call to this. If so, we need to determine whether to
+ // get the information from the bindery or by using SAP.
+ //
+
+ //
+ // make sure we have the class info info
+ //
+
+ if(!psrc->wSapId)
+ {
+ //
+ // Need to get it
+ //
+
+ UCHAR Buffer[1000];
+ LPWSASERVICECLASSINFOW lpcli = (LPWSASERVICECLASSINFOW)Buffer;
+ DWORD dwBufSize;
+ DWORD nProt1;
+
+ dwBufSize = 1000;
+ lpcli->lpServiceClassId = &psrc->gdType;
+
+ if( (err = NSPGetServiceClassInfo(&psrc->gdProvider,
+ &dwBufSize,
+ lpcli)) != NO_ERROR)
+ {
+ goto DoneNext;
+ }
+
+ err = pLocateSapIdAndProtocls(&psrc->gdType,
+ lpcli->dwCount,
+ lpcli->lpClassInfos,
+ &psrc->wSapId,
+ &nProt1);
+ if(err)
+ {
+ SetLastError(err);
+ goto DoneNext;
+ }
+
+ psrc->nProt &= nProt1;
+ if(!psrc->nProt)
+ {
+ //
+ // no protocols match
+ //
+
+ err = WSANO_DATA;
+ goto DoneNext;
+ }
+ }
+
+ //
+ // this is the state machine for querying. It selects the bindery or
+ // SAP as appropriate.
+ //
+
+
+ fDoStateMachine = TRUE; // enter the machine
+
+ do
+ {
+ //
+ // switch on the current machine state.
+ //
+ switch(psrc->dwUnionType)
+ {
+
+ case LOOKUP_TYPE_NIL:
+ psrc->u_type.bc.lIndex = -1;
+ psrc->dwUnionType = LOOKUP_TYPE_BINDERY;
+ break; // reenter state machine
+
+ case LOOKUP_TYPE_BINDERY:
+
+ //
+ // try the bindery
+ //
+
+
+ if(psrc->dwControlFlags & LUP_NEAREST)
+ {
+ err = NO_DATA; // skip the bindery
+ }
+ else
+ {
+ //
+ // otherwise, try the bindery
+ //
+
+
+ EnterCriticalSection(&psrc->u_type.sbc.csMonitor);
+
+ lLastIndex = psrc->u_type.bc.lIndex; // save it
+
+
+ err = NwpGetRnRAddress(
+ &psrc->hServer,
+ (psrc->wszContext[0] ?
+ &psrc->wszContext[0] :
+ 0),
+ &psrc->u_type.bc.lIndex,
+ (psrc->chwName[0] ?
+ psrc->chwName :
+ 0),
+ psrc->wSapId,
+ &dwVersion,
+ 48 * sizeof(WCHAR),
+ OutName,
+ &SockAddr);
+
+ LeaveCriticalSection(&psrc->u_type.sbc.csMonitor);
+ }
+
+ if(err != NO_ERROR)
+ {
+
+ if((psrc->u_type.bc.lIndex == -1))
+ {
+ err = PrepareForSap(psrc);
+ if(err)
+ {
+ //
+ // if we can't, exit the state machine
+ //
+ fDoStateMachine = FALSE;
+ }
+ }
+ else
+ {
+ //
+ // no more bindery entries. We will leave the state machine
+ //
+
+ if(err == ERROR_NO_MORE_ITEMS)
+ {
+ err = WSA_E_NO_MORE;
+ }
+ fDoStateMachine = FALSE;
+ }
+ break;
+ }
+ else
+ {
+ LPWSAVERSION lpVersion = (LPWSAVERSION)&psrc->pvVersion;
+
+ if(lpVersion->dwVersion && dwVersion)
+ {
+ //
+ // need to checkout for version matching
+ //
+
+ switch(lpVersion->ecHow)
+ {
+ case COMP_EQUAL:
+ if(lpVersion->dwVersion != dwVersion)
+ {
+ continue; //reenter machine
+ }
+ break;
+
+ case COMP_NOTLESS:
+ if(lpVersion->dwVersion > dwVersion)
+ {
+ continue;
+ }
+ break;
+
+ default:
+ continue; // error. If we don't
+ // know how to compare, we
+ // must reject it.
+ }
+ }
+
+ //
+ // have a suitable item.
+ // return the name and type and all
+ // that
+
+ err = pRnRReturnResults(
+ OutName,
+ &psrc->gdType,
+ dwVersion,
+ &pData,
+ &lSpare,
+ (PBYTE)SockAddr.sa_netnum,
+ psrc->nProt,
+ psrc->dwControlFlags,
+ lpqsResults);
+
+ if(err == WSAEFAULT)
+ {
+ //
+ // no room. Return buffer size required and
+ // restore the index
+ //
+
+ *lpdwBufferLength =
+ (DWORD)((LONG)*lpdwBufferLength - lSpare);
+ psrc->u_type.bc.lIndex = lLastIndex;
+
+ }
+ fDoStateMachine = FALSE;
+ }
+ break;
+
+ case LOOKUP_TYPE_SAP:
+
+ //
+ // Use SAP.
+ //
+
+ {
+ WORD QueryType;
+
+ if(psrc->dwControlFlags & LUP_NEAREST)
+ {
+ QueryType = QT_NEAREST_QUERY;
+ }
+ else
+ {
+ QueryType = QT_GENERAL_QUERY;
+ }
+
+ err = DoASap(psrc,
+ QueryType,
+ &pData,
+ lpqsResults,
+ &lSpare,
+ lpdwBufferLength);
+
+ if((err == WSA_E_NO_MORE)
+ &&
+ !(psrc->fFlags & SAP_F_END_CALLED)
+ &&
+ (QueryType == QT_NEAREST_QUERY)
+ &&
+ (psrc->dwControlFlags & LUP_DEEP)
+ &&
+ !psrc->u_type.sbc.psdHead)
+ {
+ //
+ // didn't find it locally. Turn off LUP_NEAREST
+ // and do this as a general query. This might bring
+ // it back to a SAP query, but this time
+ // without LUP_NEAREST. But starting anew
+ // allows the use of the bindery and that
+ // might find things quickly.
+ //
+ psrc->dwControlFlags &= ~LUP_NEAREST;
+ psrc->dwUnionType = LOOKUP_TYPE_NIL;
+ if(psrc->u_type.sbc.s)
+ {
+ SapFreeSapSocket(psrc->u_type.sbc.s);
+ psrc->u_type.sbc.s = 0;
+ }
+
+ }
+ else
+ {
+ fDoStateMachine = FALSE;
+ }
+ break;
+ }
+ } // switch
+ } while(fDoStateMachine);
+
+DoneNext:
+ SapReleaseContext(psrc);
+ if((err != NO_ERROR)
+ &&
+ (err != (DWORD)SOCKET_ERROR))
+ {
+ SetLastError(err);
+ err = (DWORD)SOCKET_ERROR;
+ }
+ return((INT)err);
+}
+
+BOOL
+NSPpCheckCancel(
+ PVOID pvArg
+ )
+/*++
+Routine Description:
+ Coroutine called to check if the SAP lookup has been cancelled.
+ For now, this always returns FALSE as we use the flags word in
+ the control block instead
+--*/
+{
+ return(FALSE);
+}
+
+
+DWORD
+NSPpGotSap(
+ PSAP_BCAST_CONTROL psbc,
+ PSAP_IDENT_HEADER pSap,
+ PDWORD pdwErr
+ )
+/*++
+Routine Description:
+ Coroutine called for each SAP reply received. This decides
+ whether to keep the data or not and returns a code telling
+ the SAP engine whether to proceed
+
+Arguments:
+ psbc -- the SAP_BCAST_CONTROL
+ pSap -- the SAP reply
+ pdwErr -- where to put an error code
+--*/
+{
+ PSAP_DATA psdData;
+ LPWSAQUERYSETW Results = (LPWSAQUERYSETW)psbc->pvArg;
+ PSAP_RNR_CONTEXT psrc = psbc->psrc;
+ DWORD dwRet = dwrcNil;
+ PCHAR pServiceName = (PCHAR)psrc->chName;
+
+ EnterCriticalSection(&psbc->csMonitor);
+
+ //
+ // First, check if this is a lookup for a particular name. If so,
+ // accept only the name.
+ //
+
+ if(*pServiceName)
+ {
+ if(strcmp(pServiceName, pSap->ServerName))
+ {
+ goto nota;
+ }
+ if(!(psrc->dwControlFlags & LUP_NEAREST))
+ {
+ dwRet = dwrcDone;
+ psbc->fFlags |= SBC_FLAG_NOMORE;
+ }
+ }
+
+ //
+ // see if we want to keep this guy
+ // We keep it if we don't already have it in the list
+ //
+
+
+ for(psdData = psbc->psdHead;
+ psdData;
+ psdData = psdData->sapNext)
+ {
+ if(RtlEqualMemory( psdData->socketAddr,
+ &pSap->Address,
+ IPX_ADDRESS_LENGTH))
+ {
+ goto nota; // we have it already
+ }
+ }
+
+ psdData = (PSAP_DATA)LocalAlloc(LPTR, sizeof(SAP_DATA));
+ if(!psdData)
+ {
+ goto nota; // can't save it
+ }
+
+ psdData->sapid = pSap->ServerType;
+ RtlMoveMemory(psdData->sapname,
+ pSap->ServerName,
+ 48);
+ RtlMoveMemory(psdData->socketAddr,
+ &pSap->Address,
+ IPX_ADDRESS_LENGTH);
+
+ if(psbc->psdTail)
+ {
+ psbc->psdTail->sapNext = psdData;
+ }
+ else
+ {
+ psbc->psdHead = psdData;
+ }
+ psbc->psdTail = psdData;
+ if(!psbc->psdNext1)
+ {
+ psbc->psdNext1 = psdData;
+ }
+
+nota:
+
+ LeaveCriticalSection(&psbc->csMonitor);
+
+ if((dwRet == dwrcNil)
+ &&
+ psbc->psdNext1)
+ {
+ dwRet = dwrcNoWait;
+ }
+ return(dwRet);
+}
+
+INT WINAPI
+NSPUnInstallNameSpace(
+ IN LPGUID lpProviderId
+ )
+{
+ return(NO_ERROR);
+}
+
+INT WINAPI
+NSPCleanup(
+ IN LPGUID lpProviderId
+ )
+{
+ //
+ // Make sure all contexts are released
+ //
+
+// pFreeAllContexts(); // done in Dll Process detach
+ return(NO_ERROR);
+}
+
+INT WINAPI
+NSPLookupServiceEnd(
+ IN HANDLE hLookup
+ )
+{
+ PSAP_RNR_CONTEXT psrc;
+
+ psrc = SapGetContext(hLookup);
+ if(!psrc)
+ {
+
+ SetLastError(WSA_INVALID_HANDLE);
+ return(SOCKET_ERROR);
+ }
+
+ psrc->fFlags |= SAP_F_END_CALLED;
+ SapReleaseContext(psrc); // get rid of it
+ SapReleaseContext(psrc); // and close it. Context cleanup is
+ // done on the last derefernce.
+ return(NO_ERROR);
+}
+
+INT WINAPI
+NSPSetService(
+ IN LPGUID lpProviderId,
+ IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
+ IN LPWSAQUERYSETW lpqsRegInfo,
+ IN WSAESETSERVICEOP essOperation,
+ IN DWORD dwControlFlags
+ )
+{
+/*++
+Routine Description:
+ The routine that implements the RnR SetService routine. Note that
+ context is ignored. There is no way to direct the registration to
+ a particular server.
+--*/
+ PBYTE pbAddress;
+ DWORD dwOperation;
+ PBYTE pbSocket;
+ DWORD dwAddrs;
+ DWORD err = NO_ERROR;
+ WORD wSapId;
+ DWORD nProt, dwAddress;
+ BOOL fAdvert = FALSE;
+ DWORD dwNumClassInfo;
+ LPWSANSCLASSINFOW lpClassInfoBuf;
+
+
+ //
+ // Verify all args present
+ //
+
+ if(!lpqsRegInfo->lpszServiceInstanceName
+ ||
+ !lpqsRegInfo->lpServiceClassId)
+ {
+ SetLastError(WSA_INVALID_PARAMETER);
+ return(SOCKET_ERROR);
+ }
+
+ if(!lpServiceClassInfo)
+ {
+ UCHAR Buffer[1000];
+ LPWSASERVICECLASSINFOW lpcli = (LPWSASERVICECLASSINFOW)Buffer;
+ DWORD dwBufSize;
+
+ dwBufSize = 1000;
+ lpcli->lpServiceClassId = lpqsRegInfo->lpServiceClassId;
+
+ if(pGetServiceClassInfo(lpProviderId,
+ &dwBufSize,
+ lpcli,
+ &fAdvert) != NO_ERROR)
+ {
+ return(SOCKET_ERROR);
+ }
+ dwNumClassInfo = lpcli->dwCount;
+ lpClassInfoBuf = lpcli->lpClassInfos;
+ }
+ else
+ {
+ dwNumClassInfo = lpServiceClassInfo->dwCount;
+ lpClassInfoBuf = lpServiceClassInfo->lpClassInfos;
+ }
+
+ //
+ // Find the IPX address in the input args
+ //
+
+ err = pLocateSapIdAndProtocls(lpqsRegInfo->lpServiceClassId,
+ dwNumClassInfo,
+ lpClassInfoBuf,
+ &wSapId,
+ &nProt);
+
+ if(err == NO_ERROR)
+ {
+ if(essOperation == RNRSERVICE_REGISTER)
+ {
+ PCSADDR_INFO pcsaAddress;
+
+ pcsaAddress = lpqsRegInfo->lpcsaBuffer;
+
+ try
+ {
+ for(dwAddrs = lpqsRegInfo->dwNumberOfCsAddrs;
+ dwAddrs;
+ dwAddrs--, pcsaAddress++)
+ {
+ if(pcsaAddress->LocalAddr.lpSockaddr->sa_family == AF_IPX)
+ {
+ pbSocket =
+ (PBYTE)pcsaAddress->LocalAddr.lpSockaddr;
+ break;
+ }
+ }
+ }
+ except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ err = GetExceptionCode();
+ }
+
+ if(err || !dwAddrs)
+ {
+ err = ERROR_INCORRECT_ADDRESS;
+ }
+ else if(fAdvert)
+ {
+ NwpSetClassInfoAdvertise(lpqsRegInfo->lpServiceClassId,
+ wSapId);
+ }
+ }
+ else
+ {
+ pbSocket = 0;
+ }
+ if(err == NO_ERROR)
+ {
+ //
+ // map the operation, and call the common worker
+ //
+
+ switch(essOperation)
+ {
+ case RNRSERVICE_REGISTER:
+ dwOperation = oldRnRServiceRegister;
+ break;
+ case RNRSERVICE_DEREGISTER:
+ case RNRSERVICE_DELETE:
+ dwOperation = oldRnRServiceDeRegister;
+ break;
+ default:
+ err = WSA_INVALID_PARAMETER;
+ break;
+ }
+ if(err == NO_ERROR)
+ {
+ err = pSapSetService2(
+ dwOperation,
+ lpqsRegInfo->lpszServiceInstanceName,
+ pbSocket,
+ lpqsRegInfo->lpServiceClassId,
+ wSapId);
+
+ }
+ }
+ }
+ if(err != NO_ERROR)
+ {
+ SetLastError(err);
+ err = (DWORD)SOCKET_ERROR;
+ }
+ return(err);
+}
+
+INT WINAPI
+NSPInstallServiceClass(
+ IN LPGUID lpProviderId,
+ IN LPWSASERVICECLASSINFOW lpServiceClassInfo
+ )
+{
+ LPWSANSCLASSINFOW pcli, pcli1 = 0;
+ DWORD dwIndex = lpServiceClassInfo->dwCount;
+ CHAR PropertyBuffer[128];
+ PBINDERYCLASSES pbc = (PBINDERYCLASSES)PropertyBuffer;
+ BYTE bData = (BYTE)&((PBINDERYCLASSES)0)->cDataArea[0];
+ PCHAR pszData = &pbc->cDataArea[0];
+ DWORD err;
+ WORD port = 0, sap;
+
+ //
+ // Find the SapId entry
+ //
+
+ for(pcli = lpServiceClassInfo->lpClassInfos;
+ dwIndex;
+ pcli++, dwIndex--)
+ {
+ WORD wTemp;
+
+ if(!_wcsicmp(pcli->lpszName, SERVICE_TYPE_VALUE_IPXPORTW)
+ &&
+ (pcli->dwValueSize == sizeof(WORD)))
+ {
+ //
+ // the value may not be aligned
+ //
+ ((PBYTE)&wTemp)[0] = ((PBYTE)pcli->lpValue)[0];
+ ((PBYTE)&wTemp)[1] = ((PBYTE)pcli->lpValue)[1];
+ port = wTemp;
+ } else if(!_wcsicmp(pcli->lpszName, SERVICE_TYPE_VALUE_SAPIDW)
+ &&
+ (pcli->dwValueSize >= sizeof(WORD)))
+ {
+ ((PBYTE)&wTemp)[0] = ((PBYTE)pcli->lpValue)[0];
+ ((PBYTE)&wTemp)[1] = ((PBYTE)pcli->lpValue)[1];
+ sap = wTemp;
+ pcli1 = pcli;
+ }
+ }
+
+ if(!(pcli = pcli1))
+ {
+ SetLastError(WSA_INVALID_PARAMETER);
+ return(SOCKET_ERROR);
+ }
+
+#if 0 // old way of doing this
+ //
+ // Found it. Build the property segment
+ //
+
+ memset(PropertyBuffer, 0, 128); // clear out everyting
+
+ pbc->bOffset = bData;
+ pbc->bSizeOfString = sizeof("Sapid");
+
+ pbc->bType = BT_WORD; // just a word, I assure you
+ pbc->bSizeOfType = 2;
+ pbc->wNameSpace = (WORD)NS_SAP; // it's us
+ *(PWORD)pszData = htons(*(PWORD)pcli->lpValue);
+ pszData += sizeof(WORD); // where the string goes
+ strcpy(pszData, "SapId");
+// pbc->bFlags = (BYTE)pcli->dwConnectionFlags;
+
+ err = NwpSetClassInfo(
+ lpServiceClassInfo->lpszServiceClassName,
+ lpServiceClassInfo->lpServiceClassId,
+ PropertyBuffer);
+#else
+ err = NwpRnR2AddServiceType(
+ lpServiceClassInfo->lpszServiceClassName,
+ lpServiceClassInfo->lpServiceClassId,
+ sap,
+ port);
+#endif
+ if(err != NO_ERROR)
+ {
+ SetLastError(err);
+ err = (DWORD)SOCKET_ERROR;
+ }
+
+ return(err);
+}
+
+INT WINAPI
+NSPRemoveServiceClass(
+ IN LPGUID lpProviderId,
+ IN LPGUID lpServiceCallId
+ )
+{
+ return(NO_ERROR);
+}
+
+INT WINAPI
+NSPGetServiceClassInfo(
+ IN LPGUID lpProviderId,
+ IN OUT LPDWORD lpdwBufSize,
+ IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
+ )
+{
+/*++
+Routine Description:
+ Get the ClassInfo for this type. Class info data may be in the
+ registry, or available via SAP or the bindery. We try all three
+ as appropriate
+--*/
+ BOOL fAdvert;
+
+ return(pGetServiceClassInfo(
+ lpProviderId,
+ lpdwBufSize,
+ lpServiceClassInfo,
+ &fAdvert));
+}
+
+INT WINAPI
+pGetServiceClassInfo(
+ IN LPGUID lpProviderId,
+ IN OUT LPDWORD lpdwBufSize,
+ IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo,
+ IN PBOOL pfAdvert
+ )
+{
+/*++
+Routine Description:
+ Get the ClassInfo for this type. Class info data may be in the
+ registry, or available via SAP or the bindery. We try all three
+ as appropriate
+--*/
+ DWORD err;
+ LONG lInSize;
+ LONG lSizeNeeded;
+ PBYTE pbBuffer;
+ GUID gdDummy;
+ PWCHAR pwszUuid;
+ LPGUID pType;
+ WORD wSapId;
+ WORD wPort;
+ SOCKADDR_IPX sock;
+ PWCHAR pwszSaveName = lpServiceClassInfo->lpszServiceClassName;
+
+#define SIZENEEDED (sizeof(WSASERVICECLASSINFO) + \
+ sizeof(WSANSCLASSINFO) + \
+ sizeof(WSANSCLASSINFO) + \
+ 10 + 2 + \
+ sizeof(GUID) + 12 + 2)
+
+ *pfAdvert = FALSE;
+
+ lInSize = (LONG)*lpdwBufSize - SIZENEEDED;
+
+ pType = (LPGUID)(lpServiceClassInfo + 1);
+
+ pbBuffer = (PBYTE)(pType + 1);
+
+ if(lInSize < 0)
+ {
+ //
+ // it is too small already
+ //
+
+ pType = &gdDummy;
+ }
+
+ UuidToString(lpServiceClassInfo->lpServiceClassId, &pwszUuid);
+
+ //
+ // First, try the bindery
+ //
+
+ err = NwpGetAddressByName(0,
+ RNRCLASSSAPTYPE,
+ pwszUuid,
+ &sock);
+
+ if(err == NO_ERROR)
+ {
+ wSapId = ntohs(*(PWORD)&sock.sa_netnum);
+ wPort = ntohs(*(PWORD)&sock.sa_socket);
+ }
+ else
+ {
+ UCHAR Buffer[400];
+ DWORD dwLen = 400;
+ DWORD dwNum;
+ //
+ // try SAP
+ //
+
+ err = NwpGetAddressViaSap(RNRCLASSSAPTYPE,
+ pwszUuid,
+ IPX_BIT,
+ (PVOID)Buffer,
+ &dwLen,
+ 0,
+ &dwNum);
+ if((err == NO_ERROR)
+ &&
+ (dwNum > 0) )
+ {
+ PCSADDR_INFO psca = (PCSADDR_INFO)Buffer;
+ PSOCKADDR_IPX psock = (PSOCKADDR_IPX)psca->RemoteAddr.lpSockaddr;
+
+ wSapId = ntohs(*(PWORD)&psock->sa_netnum);
+ wPort = ntohs(*(PWORD)&sock.sa_socket);
+ }
+ else
+ {
+ //
+ // try the local bindery
+
+
+ if(!NwpLookupSapInRegistry(
+ lpServiceClassInfo->lpServiceClassId,
+ &wSapId,
+ &wPort,
+ NULL))
+ {
+ err = WSASERVICE_NOT_FOUND;
+ }
+ else
+ {
+ *pfAdvert = TRUE;
+ err = NO_ERROR;
+ }
+ }
+ }
+
+ RpcStringFree(&pwszUuid);
+
+ if(err != NO_ERROR)
+ {
+ SetLastError(err);
+ err = (DWORD)SOCKET_ERROR;
+ }
+ else
+ {
+ //
+ // we return the input structure and the found type. That's it.
+ // The space needed is a constant since we don't return the name
+ //
+
+ if(lInSize < 0)
+ {
+ SetLastError(WSAEFAULT);
+ *lpdwBufSize += (DWORD)(-lInSize);
+ err = (DWORD)SOCKET_ERROR;
+ }
+ else
+ {
+ LPWSANSCLASSINFOW pci = (LPWSANSCLASSINFOW)pbBuffer;
+ PUCHAR Buff;
+ //
+ // it will fit. SO let's go
+ //
+
+ if(wPort)
+ {
+ Buff = (PCHAR)(pci + 2);
+ }
+ else
+ {
+ Buff = (PCHAR)(pci + 1);
+ }
+
+ *pType = *lpServiceClassInfo->lpServiceClassId;
+ lpServiceClassInfo->lpServiceClassId = pType;
+ lpServiceClassInfo->lpszServiceClassName = 0; // not a
+ lpServiceClassInfo->dwCount = 1;
+ lpServiceClassInfo->lpClassInfos = pci;
+ pci->dwNameSpace = NS_SAP;
+ pci->dwValueType = REG_DWORD;
+ pci->dwValueSize = 2;
+ pci->lpszName = (LPWSTR)Buff;
+ wcscpy((PWCHAR)Buff, L"SapId");
+ Buff += 6 * sizeof(WCHAR);
+ pci->lpValue = (LPVOID)Buff;
+ *(PWORD)Buff = wSapId;
+ Buff += sizeof(WORD);
+ if(wPort)
+ {
+ lpServiceClassInfo->dwCount++;
+ pci++;
+ pci->dwNameSpace = NS_SAP;
+ pci->dwValueType = REG_DWORD;
+ pci->dwValueSize = 2;
+ pci->lpszName = (LPWSTR)Buff;
+ wcscpy((PWCHAR)Buff, L"Port");
+ Buff += 5 * sizeof(WCHAR);
+ pci->lpValue = (LPVOID)Buff;
+ *(PWORD)Buff = wPort;
+ }
+ }
+ }
+ return(err);
+}
+
+INT WINAPI
+NSPStartup(
+ IN LPGUID lpProviderId,
+ IN OUT LPNSP_ROUTINE lpsnpRoutines)
+{
+// DWORD dwSize = min(sizeof(nsrVector), lpsnpRoutines->cbSize);
+ DWORD dwSize = sizeof(nsrVector);
+ RtlCopyMemory(lpsnpRoutines,
+ &nsrVector,
+ dwSize);
+ return(NO_ERROR);
+}
+
+DWORD
+DoASap(
+ IN PSAP_RNR_CONTEXT psrc,
+ IN WORD QueryType,
+ IN PBYTE * ppData,
+ IN LPWSAQUERYSETW lpqsResults,
+ IN PLONG plSpare,
+ IN PDWORD lpdwBufferLength
+ )
+/*++
+ Small routine to construcst a SAP_BROADCAST pakcet and issue the SAP
+--*/
+{
+ DWORD err;
+
+ if(!psrc->u_type.sbc.s)
+ {
+ //
+ // this is the first time. We must init the
+ // structure
+ //
+ err = SapGetSapSocket(&psrc->u_type.sbc.s);
+ if(err)
+ {
+ psrc->u_type.sbc.s = 0; // make sure
+ return(err);
+ }
+ psrc->u_type.sbc.Func = NSPpGotSap;
+ psrc->u_type.sbc.fCheckCancel = NSPpCheckCancel;
+ psrc->u_type.sbc.dwIndex = 0; // just in case.
+ psrc->u_type.sbc.pvArg = (PVOID)lpqsResults;
+ psrc->u_type.sbc.psrc = psrc;
+ psrc->u_type.sbc.fFlags = 0;
+
+ }
+
+ psrc->u_type.sbc.wQueryType = QueryType;
+
+ if(!psrc->u_type.sbc.psdNext1
+ &&
+ !(psrc->u_type.sbc.fFlags & SBC_FLAG_NOMORE))
+ {
+ err = SapGetSapForType(&psrc->u_type.sbc, psrc->wSapId);
+ }
+
+ EnterCriticalSection(&psrc->u_type.sbc.csMonitor);
+ if(psrc->u_type.sbc.psdNext1)
+ {
+ //
+ // Got something to return. Let's do it
+ //
+
+
+ //
+ // Assume we have to return the name
+ //
+
+
+ //
+ // We have to convert the name to UNICODE so
+ // we can return it to the caller.
+ //
+ //
+
+ OEM_STRING Oem;
+ NTSTATUS status;
+ UNICODE_STRING UString;
+
+ RtlInitAnsiString(&Oem,
+ psrc->u_type.sbc.psdNext1->sapname);
+ status = RtlOemStringToUnicodeString(
+ &UString,
+ &Oem,
+ TRUE);
+ if(NT_SUCCESS(status))
+ {
+ if(psrc->wSapId == OT_DIRSERVER)
+ {
+ PWCHAR pwszTemp = &UString.Buffer[31];
+
+ while(*pwszTemp == L'_')
+ {
+ *pwszTemp-- = 0;
+ }
+ }
+ err = pRnRReturnResults(
+ UString.Buffer,
+ &psrc->gdType,
+ 0, // never a version
+ ppData,
+ plSpare,
+ psrc->u_type.sbc.psdNext1->socketAddr,
+ psrc->nProt,
+ psrc->dwControlFlags,
+ lpqsResults);
+ RtlFreeUnicodeString(&UString);
+ if(err == WSAEFAULT)
+ {
+ //
+ // no room. Return buffer size required
+ //
+
+ *lpdwBufferLength =
+ (DWORD)((LONG)*lpdwBufferLength - *plSpare);
+ }
+ }
+ else
+ {
+ err = (DWORD)status;
+ }
+ if(err == NO_ERROR)
+ {
+ //
+ // if we got it, step the item
+ //
+ psrc->u_type.sbc.psdNext1 =
+ psrc->u_type.sbc.psdNext1->sapNext;
+ }
+
+
+ }
+ else
+ {
+ err = (DWORD)WSA_E_NO_MORE;
+ }
+ LeaveCriticalSection(&psrc->u_type.sbc.csMonitor);
+ return(err);
+}
+
+
+DWORD
+PrepareForSap(
+ IN PSAP_RNR_CONTEXT psrc
+ )
+/*++
+Called when there is no bindery or the bindery does not have the
+entry. This initializes the values needed for a SAP search
+--*/
+{
+
+
+ OEM_STRING OemServiceName;
+ UNICODE_STRING UString;
+ NTSTATUS status;
+
+ //
+ // the bindery didn't work. Use SAP.
+ //
+
+
+ psrc->u_type.sbc.dwIndex =
+ psrc->u_type.sbc.dwTickCount = 0;
+ if(psrc->wszContext[0])
+ {
+ return(WSASERVICE_NOT_FOUND); // no contexts in SAP
+ }
+ RtlInitUnicodeString(&UString,
+ psrc->chwName);
+ status = RtlUnicodeStringToOemString(&OemServiceName,
+ &UString,
+ TRUE);
+ if(!NT_SUCCESS(status))
+ {
+ return( (DWORD)status);
+ }
+ strcpy((PCHAR)&psrc->chName,
+ OemServiceName.Buffer);
+ RtlFreeOemString(&OemServiceName);
+ psrc->dwUnionType = LOOKUP_TYPE_SAP;
+ psrc->u_type.sbc.s = 0;
+ return(NO_ERROR);
+}
+