Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2073 lines
51 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. gtsadrnr.c
  5. Abstract:
  6. This module contains the code to support the new RnR APIs. Some
  7. support code is in getaddr.c, but the interface routines and
  8. routines specific to RnR2 are herein.
  9. Author:
  10. ArnoldM 4-Dec-1995
  11. Revision History:
  12. ArnoldM Created
  13. --*/
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <windows.h>
  18. #include "ncp.h"
  19. #include <rpc.h>
  20. #include <winsock2.h>
  21. #include <ws2spi.h>
  22. #include <wsipx.h>
  23. #include <rnrdefs.h>
  24. #include <svcguid.h>
  25. #include <rnraddrs.h>
  26. //-------------------------------------------------------------------//
  27. // //
  28. // Globals in getaddr.c and provider .c //
  29. // //
  30. //-------------------------------------------------------------------//
  31. GUID HostAddrByInetStringGuid = SVCID_INET_HOSTADDRBYINETSTRING;
  32. GUID ServiceByNameGuid = SVCID_INET_SERVICEBYNAME;
  33. GUID HostAddrByNameGuid = SVCID_INET_HOSTADDRBYNAME;
  34. GUID HostNameGuid = SVCID_HOSTNAME;
  35. DWORD
  36. NwpGetAddressByName(
  37. IN LPWSTR Reserved,
  38. IN WORD nServiceType,
  39. IN LPWSTR lpServiceName,
  40. IN OUT LPSOCKADDR_IPX lpsockaddr
  41. );
  42. DWORD
  43. NwpGetAddressViaSap(
  44. IN WORD nServiceType,
  45. IN LPWSTR lpServiceName,
  46. IN DWORD nProt,
  47. IN OUT LPVOID lpCsAddrBuffer,
  48. IN OUT LPDWORD lpdwBufferLength,
  49. IN HANDLE hCancellationEvent,
  50. OUT LPDWORD lpcAddress
  51. );
  52. DWORD
  53. NwpRnR2AddServiceType(
  54. IN LPWSTR lpServiceTypeName,
  55. IN LPGUID lpClassType,
  56. IN WORD wSapId,
  57. IN WORD wPort
  58. );
  59. BOOL
  60. NwpRnR2RemoveServiceType(
  61. IN LPGUID lpServiceType
  62. );
  63. DWORD
  64. SapFreeSapSocket(
  65. SOCKET s
  66. );
  67. PSAP_RNR_CONTEXT
  68. SapMakeContext
  69. (
  70. IN HANDLE Handle,
  71. DWORD dwExcess
  72. );
  73. BOOL
  74. NwpLookupSapInRegistry(
  75. IN LPGUID lpServiceType,
  76. OUT PWORD pnSapType,
  77. OUT PWORD pwPort,
  78. IN OUT PDWORD pfConnectionOriented
  79. );
  80. PSAP_RNR_CONTEXT
  81. SapGetContext(
  82. HANDLE h
  83. );
  84. DWORD
  85. DoASap(
  86. IN PSAP_RNR_CONTEXT psrcContext,
  87. IN WORD QueryType,
  88. IN PBYTE * ppData,
  89. IN LPWSAQUERYSETW lpqsResults,
  90. IN PLONG pl,
  91. IN PDWORD pdw
  92. );
  93. VOID
  94. SapReleaseContext(
  95. IN PSAP_RNR_CONTEXT psrcContext
  96. );
  97. DWORD
  98. SapGetSapSocket(
  99. SOCKET * ps
  100. );
  101. DWORD
  102. PrepareForSap(
  103. IN PSAP_RNR_CONTEXT psrc
  104. );
  105. DWORD
  106. SapGetSapForType(
  107. PSAP_BCAST_CONTROL psbc,
  108. WORD nServiceType
  109. );
  110. DWORD
  111. FillBufferWithCsAddr(
  112. IN LPBYTE pAddress,
  113. IN DWORD nProt,
  114. IN OUT LPVOID lpCsAddrBuffer,
  115. IN OUT LPDWORD lpdwBufferLength,
  116. OUT LPDWORD pcAddress
  117. );
  118. DWORD
  119. pSapSetService2(
  120. IN DWORD dwOperation,
  121. IN LPWSTR lpszServiceInstanceName,
  122. IN PBYTE pbAddress,
  123. IN LPGUID pServiceType,
  124. IN WORD nServiceType
  125. );
  126. DWORD
  127. NwpGetRnRAddress(
  128. PHANDLE phServer,
  129. PWCHAR pwszContext,
  130. PLONG plIndex,
  131. LPWSTR lpServiceName,
  132. WORD nServiceType,
  133. PDWORD pdwVersion,
  134. DWORD dwInSize,
  135. LPWSTR OutName,
  136. SOCKADDR_IPX * pSockAddr
  137. );
  138. DWORD
  139. NwpSetClassInfo(
  140. IN LPWSTR lpwszClassName,
  141. IN LPGUID lpClassId,
  142. IN PCHAR lpbProp
  143. );
  144. VOID
  145. pFreeAllContexts();
  146. extern DWORD oldRnRServiceRegister, oldRnRServiceDeRegister;
  147. //-------------------------------------------------------------------//
  148. // //
  149. // Local Function Prototypes //
  150. // //
  151. //-------------------------------------------------------------------//
  152. INT WINAPI
  153. pGetServiceClassInfo(
  154. IN LPGUID lpProviderId,
  155. IN OUT LPDWORD lpdwBufSize,
  156. IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo,
  157. IN PBOOL pfAdvert
  158. );
  159. DWORD
  160. NwpSetClassInfoAdvertise(
  161. IN LPGUID lpClassType,
  162. IN WORD wSapId
  163. );
  164. BOOL
  165. NSPpCheckCancel(
  166. PVOID pvArg
  167. );
  168. DWORD
  169. NSPpGotSap(
  170. PSAP_BCAST_CONTROL psbc,
  171. PSAP_IDENT_HEADER pSap,
  172. PDWORD pdwErr
  173. );
  174. INT WINAPI
  175. NSPLookupServiceBegin(
  176. IN LPGUID lpProviderId,
  177. IN LPWSAQUERYSETW lpqsRestrictions,
  178. IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
  179. IN DWORD dwControlFlags,
  180. OUT LPHANDLE lphLookup
  181. );
  182. INT WINAPI
  183. NSPLookupServiceNext(
  184. IN HANDLE hLookup,
  185. IN DWORD dwControlFlags,
  186. IN OUT LPDWORD lpdwBufferLength,
  187. OUT LPWSAQUERYSETW lpqsResults
  188. );
  189. INT WINAPI
  190. NSPUnInstallNameSpace(
  191. IN LPGUID lpProviderId
  192. );
  193. INT WINAPI
  194. NSPCleanup(
  195. IN LPGUID lpProviderId
  196. );
  197. INT WINAPI
  198. NSPLookupServiceEnd(
  199. IN HANDLE hLookup
  200. );
  201. INT WINAPI
  202. NSPSetService(
  203. IN LPGUID lpProviderId,
  204. IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
  205. IN LPWSAQUERYSETW lpqsRegInfo,
  206. IN WSAESETSERVICEOP essOperation,
  207. IN DWORD dwControlFlags
  208. );
  209. INT WINAPI
  210. NSPInstallServiceClass(
  211. IN LPGUID lpProviderId,
  212. IN LPWSASERVICECLASSINFOW lpServiceClassInfo
  213. );
  214. INT WINAPI
  215. NSPRemoveServiceClass(
  216. IN LPGUID lpProviderId,
  217. IN LPGUID lpServiceCallId
  218. );
  219. INT WINAPI
  220. NSPGetServiceClassInfo(
  221. IN LPGUID lpProviderId,
  222. IN OUT LPDWORD lpdwBufSize,
  223. IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
  224. );
  225. //-------------------------------------------------------------------//
  226. // //
  227. // Data definitions //
  228. // //
  229. //-------------------------------------------------------------------//
  230. NSP_ROUTINE nsrVector = {
  231. FIELD_OFFSET(NSP_ROUTINE, NSPIoctl),
  232. 1, // major version
  233. 1, // minor version
  234. NSPCleanup,
  235. NSPLookupServiceBegin,
  236. NSPLookupServiceNext,
  237. NSPLookupServiceEnd,
  238. NSPSetService,
  239. NSPInstallServiceClass,
  240. NSPRemoveServiceClass,
  241. NSPGetServiceClassInfo
  242. };
  243. static
  244. GUID HostnameGuid = SVCID_HOSTNAME;
  245. static
  246. GUID InetHostname = SVCID_INET_HOSTADDRBYNAME;
  247. static
  248. GUID AddressGuid = SVCID_INET_HOSTADDRBYINETSTRING;
  249. static
  250. GUID IANAGuid = SVCID_INET_SERVICEBYNAME;
  251. #define GuidEqual(x,y) RtlEqualMemory(x, y, sizeof(GUID))
  252. //------------------------------------------------------------------//
  253. // //
  254. // Function Bodies //
  255. // //
  256. //------------------------------------------------------------------//
  257. DWORD
  258. NwpSetClassInfoAdvertise(
  259. IN LPGUID lpClassType,
  260. IN WORD wSapId
  261. )
  262. {
  263. /*++
  264. Routine Description:
  265. Start a class info advertise. Called upon a SetService call
  266. --*/
  267. PWCHAR pwszUuid;
  268. SOCKADDR_IPX sock;
  269. if (UuidToString(lpClassType, &pwszUuid) != RPC_S_OK) {
  270. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  271. return SOCKET_ERROR;
  272. }
  273. memset(&sock, 0, sizeof(sock));
  274. *(PWORD)&sock.sa_netnum = htons(wSapId); // encode the ID here
  275. return(pSapSetService2( oldRnRServiceRegister,
  276. pwszUuid,
  277. (PBYTE)&sock,
  278. lpClassType,
  279. RNRCLASSSAPTYPE));
  280. }
  281. DWORD
  282. pRnRReturnString(
  283. IN PWCHAR pwszSrc,
  284. IN OUT PBYTE *ppData,
  285. IN OUT PLONG plBytes
  286. )
  287. {
  288. /*++
  289. Routine Description:
  290. Utility routine to pack a string into the spare buffer space,
  291. update pointers and counts. If the string fits, it is copied. If
  292. not, the pointer and count are still updated so the caller can
  293. compute the additional space needed
  294. --*/
  295. PBYTE pSave = *ppData;
  296. LONG lLen = (wcslen(pwszSrc) + 1) * sizeof(WCHAR);
  297. *ppData = pSave + lLen; // update the buffer pointer
  298. *plBytes = *plBytes - lLen; // and the count
  299. if(*plBytes >= 0)
  300. {
  301. //
  302. // it fits.
  303. //
  304. RtlMoveMemory(pSave,
  305. pwszSrc,
  306. lLen);
  307. return(NO_ERROR);
  308. }
  309. return(WSAEFAULT);
  310. }
  311. DWORD
  312. pLocateSapIdAndProtocls(
  313. IN LPGUID lpClassInfoType,
  314. IN DWORD dwNumClassInfo,
  315. IN LPWSANSCLASSINFOW lpClassInfoBuf,
  316. OUT PWORD pwSapId,
  317. OUT PDWORD pdwnProt
  318. )
  319. /*++
  320. Routine Description:
  321. Locate the SAP ID entry and return it. Also return
  322. the protocols support.
  323. --*/
  324. {
  325. DWORD err = NO_ERROR;
  326. if(GuidEqual(lpClassInfoType, &HostnameGuid)
  327. ||
  328. GuidEqual(lpClassInfoType, &InetHostname) )
  329. {
  330. *pwSapId = 0x4;
  331. }
  332. else if(IS_SVCID_NETWARE(lpClassInfoType))
  333. {
  334. *pwSapId = SAPID_FROM_SVCID_NETWARE(lpClassInfoType);
  335. }
  336. else
  337. {
  338. for(; dwNumClassInfo; dwNumClassInfo--, lpClassInfoBuf++)
  339. {
  340. //
  341. // We have some class info data. Rummage through it
  342. // looking for what we want
  343. //
  344. if(!_wcsicmp(SERVICE_TYPE_VALUE_SAPIDW, lpClassInfoBuf->lpszName)
  345. &&
  346. (lpClassInfoBuf->dwValueType == REG_DWORD)
  347. &&
  348. (lpClassInfoBuf->dwValueSize >= sizeof(WORD)))
  349. {
  350. //
  351. // got it
  352. //
  353. *pwSapId = *(PWORD)lpClassInfoBuf->lpValue;
  354. break;
  355. }
  356. }
  357. if(!dwNumClassInfo)
  358. {
  359. err = WSA_INVALID_PARAMETER;
  360. }
  361. }
  362. *pdwnProt = SPX_BIT | SPXII_BIT | IPX_BIT;
  363. return(err);
  364. }
  365. DWORD
  366. pRnRReturnResults(
  367. IN PWCHAR pwszString,
  368. IN LPGUID pgdServiceClass,
  369. IN DWORD dwVersion,
  370. IN OUT PBYTE *ppData,
  371. IN OUT PLONG plBytes,
  372. IN PBYTE lpSockAddr,
  373. IN DWORD nProt,
  374. IN DWORD dwControlFlags,
  375. OUT LPWSAQUERYSETW lpqsResults
  376. )
  377. {
  378. /*++
  379. Routine Description:
  380. Return the requested results
  381. --*/
  382. DWORD err;
  383. lpqsResults->dwNameSpace = NS_SAP;
  384. if(dwControlFlags & LUP_RETURN_TYPE)
  385. {
  386. lpqsResults->lpServiceClassId = (LPGUID)*ppData;
  387. *ppData += sizeof(GUID);
  388. *plBytes -= sizeof(GUID);
  389. if(*plBytes >= 0)
  390. {
  391. *lpqsResults->lpServiceClassId = *pgdServiceClass;
  392. }
  393. }
  394. if(dwVersion
  395. &&
  396. (dwControlFlags & LUP_RETURN_VERSION) )
  397. {
  398. //
  399. // have a verion, and the caller wants it
  400. //
  401. lpqsResults->lpVersion = (LPWSAVERSION)*ppData;
  402. *ppData += sizeof(WSAVERSION);
  403. *plBytes -= sizeof(WSAVERSION);
  404. if(*plBytes >= 0)
  405. {
  406. //
  407. // and it fits. So return it
  408. //
  409. lpqsResults->lpVersion->dwVersion = dwVersion;
  410. lpqsResults->lpVersion->ecHow = COMP_EQUAL;
  411. }
  412. }
  413. if(dwControlFlags & LUP_RETURN_ADDR)
  414. {
  415. DWORD dwCsAddrLen;
  416. if(*plBytes >= 0)
  417. {
  418. dwCsAddrLen = (DWORD)*plBytes; // all of it for now
  419. }
  420. else
  421. {
  422. dwCsAddrLen = 0;
  423. }
  424. lpqsResults->lpcsaBuffer = (PVOID)*ppData;
  425. err = FillBufferWithCsAddr(
  426. lpSockAddr,
  427. nProt,
  428. (PVOID)lpqsResults->lpcsaBuffer,
  429. &dwCsAddrLen,
  430. &lpqsResults->dwNumberOfCsAddrs);
  431. //
  432. // see if it fit. Whether it did or not, compute the space available,
  433. // align, and do the rest
  434. //
  435. if(err == NO_ERROR)
  436. {
  437. //
  438. // if it worked, we have to compute the space taken
  439. //
  440. dwCsAddrLen = lpqsResults->dwNumberOfCsAddrs * (sizeof(CSADDR_INFO) +
  441. 2*sizeof(SOCKADDR_IPX));
  442. }
  443. else if(err == ERROR_INSUFFICIENT_BUFFER)
  444. {
  445. err = WSAEFAULT;
  446. }
  447. *plBytes = *plBytes - dwCsAddrLen;
  448. *ppData = *ppData + dwCsAddrLen;
  449. }
  450. else
  451. {
  452. err = NO_ERROR;
  453. }
  454. //
  455. // no padding needed.
  456. if((dwControlFlags & LUP_RETURN_NAME))
  457. {
  458. lpqsResults->lpszServiceInstanceName = (LPWSTR)*ppData;
  459. err = pRnRReturnString(
  460. pwszString,
  461. ppData,
  462. plBytes);
  463. }
  464. if(pgdServiceClass)
  465. {
  466. //
  467. // Do we really return this?
  468. //
  469. }
  470. return(err);
  471. }
  472. INT WINAPI
  473. NSPLookupServiceBegin(
  474. IN LPGUID lpProviderId,
  475. IN LPWSAQUERYSETW lpqsRestrictions,
  476. IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
  477. IN DWORD dwControlFlags,
  478. OUT LPHANDLE lphLookup
  479. )
  480. /*++
  481. Routine Description:
  482. This is the RnR routine that begins a lookup.
  483. --*/
  484. {
  485. PSAP_RNR_CONTEXT psrc;
  486. int err;
  487. DWORD nProt, nProt1;
  488. OEM_STRING OemServiceName;
  489. LPWSTR pwszContext;
  490. WORD wSapid;
  491. DWORD dwNumClassInfo;
  492. LPWSANSCLASSINFOW lpClassInfoBuf;
  493. //
  494. // Do parameter checking.
  495. //
  496. if ( lpqsRestrictions == NULL ||
  497. lpProviderId == NULL )
  498. {
  499. SetLastError( WSA_INVALID_PARAMETER );
  500. return( SOCKET_ERROR );
  501. }
  502. if ( lpqsRestrictions->dwNameSpace != NS_ALL &&
  503. lpqsRestrictions->dwNameSpace != NS_SAP )
  504. {
  505. SetLastError( WSAEINVAL );
  506. return( SOCKET_ERROR );
  507. }
  508. if ( lpqsRestrictions->lpServiceClassId == NULL )
  509. {
  510. SetLastError( WSA_INVALID_PARAMETER );
  511. return( SOCKET_ERROR );
  512. }
  513. //
  514. // Test to see if the ServiceClassId is TCP's, if so
  515. // we don't do the lookup.
  516. if ( lpqsRestrictions->lpServiceClassId &&
  517. ( GuidEqual( lpqsRestrictions->lpServiceClassId,
  518. &HostAddrByInetStringGuid ) ||
  519. GuidEqual( lpqsRestrictions->lpServiceClassId,
  520. &ServiceByNameGuid ) ||
  521. GuidEqual( lpqsRestrictions->lpServiceClassId,
  522. &HostNameGuid ) ||
  523. GuidEqual( lpqsRestrictions->lpServiceClassId,
  524. &HostAddrByNameGuid ) ) )
  525. {
  526. SetLastError( WSASERVICE_NOT_FOUND );
  527. return( SOCKET_ERROR );
  528. }
  529. if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW))
  530. {
  531. SetLastError(WSAEFAULT);
  532. return(SOCKET_ERROR);
  533. }
  534. if(lpqsRestrictions->lpszContext
  535. &&
  536. (lpqsRestrictions->lpszContext[0] != 0)
  537. &&
  538. wcscmp(&lpqsRestrictions->lpszContext[0], L"\\") )
  539. {
  540. //
  541. // if not the default context, we must copy it.
  542. //
  543. pwszContext = lpqsRestrictions->lpszContext;
  544. }
  545. else
  546. {
  547. //
  548. // map all default contexts into "no context".
  549. //
  550. pwszContext = 0;
  551. }
  552. //
  553. // Compute protocols to return, or return them all
  554. //
  555. if(lpqsRestrictions->lpafpProtocols)
  556. {
  557. //
  558. // Make certain at least one IPX/SPX protocol is being requested
  559. //
  560. DWORD i;
  561. nProt = 0;
  562. for ( i = 0; i < lpqsRestrictions->dwNumberOfProtocols; i++ )
  563. {
  564. if((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_IPX)
  565. ||
  566. (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC)
  567. )
  568. {
  569. switch(lpqsRestrictions->lpafpProtocols[i].iProtocol)
  570. {
  571. case NSPROTO_IPX:
  572. nProt |= IPX_BIT;
  573. break;
  574. case NSPROTO_SPX:
  575. nProt |= SPX_BIT;
  576. break;
  577. case NSPROTO_SPXII:
  578. nProt |= SPXII_BIT;
  579. break;
  580. default:
  581. break;
  582. }
  583. }
  584. }
  585. if(!nProt)
  586. {
  587. //
  588. // if the caller doesn't want IPX/SPX addresses, why bother?
  589. //
  590. SetLastError(WSANO_DATA);
  591. return(SOCKET_ERROR);
  592. }
  593. }
  594. else
  595. {
  596. nProt = IPX_BIT | SPX_BIT | SPXII_BIT;
  597. }
  598. if(dwControlFlags & LUP_CONTAINERS)
  599. {
  600. if(pwszContext)
  601. {
  602. BadGuid:
  603. SetLastError(WSANO_DATA);
  604. return(SOCKET_ERROR); // can't handle containers in containers
  605. }
  606. wSapid = 0x4;
  607. nProt1 = IPX_BIT;
  608. err = NO_ERROR;
  609. }
  610. else
  611. {
  612. LPGUID pgClass = lpqsRestrictions->lpServiceClassId;
  613. if(!pgClass
  614. ||
  615. GuidEqual(pgClass, &AddressGuid)
  616. ||
  617. GuidEqual(pgClass, &IANAGuid) )
  618. {
  619. goto BadGuid;
  620. }
  621. if(!lpqsRestrictions->lpszServiceInstanceName
  622. ||
  623. !*lpqsRestrictions->lpszServiceInstanceName)
  624. {
  625. SetLastError(WSA_INVALID_PARAMETER);
  626. return(SOCKET_ERROR);
  627. }
  628. if(!lpServiceClassInfo)
  629. {
  630. dwNumClassInfo = 0;
  631. }
  632. else
  633. {
  634. dwNumClassInfo = lpServiceClassInfo->dwCount;
  635. lpClassInfoBuf = lpServiceClassInfo->lpClassInfos;
  636. }
  637. err = pLocateSapIdAndProtocls(pgClass,
  638. dwNumClassInfo,
  639. lpClassInfoBuf,
  640. &wSapid,
  641. &nProt1);
  642. if(err)
  643. {
  644. if(dwNumClassInfo)
  645. {
  646. SetLastError(err);
  647. return(SOCKET_ERROR);
  648. }
  649. else
  650. {
  651. nProt1 = nProt;
  652. wSapid = 0;
  653. err = 0;
  654. }
  655. }
  656. }
  657. nProt &= nProt1; // the relevant protocols
  658. if(!nProt)
  659. {
  660. SetLastError(WSANO_DATA);
  661. return(SOCKET_ERROR);
  662. }
  663. //
  664. // Make sure a class ID is given since we copy it
  665. //
  666. if(!lpqsRestrictions->lpServiceClassId)
  667. {
  668. //
  669. // not. So, fail
  670. //
  671. SetLastError(WSA_INVALID_PARAMETER);
  672. return(SOCKET_ERROR);
  673. }
  674. //
  675. // It looks like a query we can handle. Make a context
  676. //
  677. psrc = SapMakeContext(0,
  678. sizeof(WSAVERSION) - sizeof(PVOID));
  679. if(!psrc)
  680. {
  681. SetLastError(WSA_NOT_ENOUGH_MEMORY);
  682. return(SOCKET_ERROR);
  683. }
  684. //
  685. // save things
  686. //
  687. psrc->gdType = *lpqsRestrictions->lpServiceClassId;
  688. psrc->dwControlFlags = dwControlFlags; // save for Next processing
  689. psrc->wSapId = wSapid;
  690. if(pwszContext)
  691. {
  692. wcscpy(psrc->wszContext, pwszContext);
  693. }
  694. //
  695. // save the relevant restrictions
  696. // if the name is a wild-card, don't copy it. A NULL name
  697. // serves as a wild-card to NSPLookupServiceNext
  698. //
  699. if(lpqsRestrictions->lpszServiceInstanceName
  700. &&
  701. *lpqsRestrictions->lpszServiceInstanceName
  702. &&
  703. wcscmp(lpqsRestrictions->lpszServiceInstanceName, L"*"))
  704. {
  705. DWORD dwLen = wcslen(lpqsRestrictions->lpszServiceInstanceName);
  706. if(dwLen > 48)
  707. {
  708. err = WSA_INVALID_PARAMETER;
  709. goto Done;
  710. }
  711. else
  712. {
  713. RtlMoveMemory(psrc->chwName,
  714. lpqsRestrictions->lpszServiceInstanceName,
  715. dwLen * sizeof(WCHAR));
  716. _wcsupr(psrc->chwName);
  717. }
  718. }
  719. psrc->fConnectionOriented = (DWORD) -1;
  720. *lphLookup = (HANDLE)psrc;
  721. psrc->nProt = nProt;
  722. psrc->gdProvider = *lpProviderId;
  723. if(lpqsRestrictions->lpVersion)
  724. {
  725. *(LPWSAVERSION)&psrc->pvVersion = *lpqsRestrictions->lpVersion;
  726. }
  727. Done:
  728. SapReleaseContext(psrc);
  729. if(err != NO_ERROR)
  730. {
  731. SapReleaseContext(psrc);
  732. SetLastError(err);
  733. err = SOCKET_ERROR;
  734. }
  735. return(err);
  736. }
  737. INT WINAPI
  738. NSPLookupServiceNext(
  739. IN HANDLE hLookup,
  740. IN DWORD dwControlFlags,
  741. IN OUT LPDWORD lpdwBufferLength,
  742. OUT LPWSAQUERYSETW lpqsResults
  743. )
  744. /*++
  745. Routine Description:
  746. The continuation of the LookupServiceBegin. Called to fetch
  747. a matching item.
  748. Arguments:
  749. See RnR spec
  750. --*/
  751. {
  752. DWORD err = NO_ERROR;
  753. PSAP_RNR_CONTEXT psrc;
  754. SOCKADDR_IPX SockAddr;
  755. WCHAR OutName[48];
  756. PBYTE pData = (PBYTE)(lpqsResults + 1);
  757. LONG lSpare;
  758. LONG lLastIndex;
  759. DWORD dwVersion;
  760. WSAQUERYSETW wsaqDummy;
  761. BOOL fDoStateMachine;
  762. if(*lpdwBufferLength < sizeof(WSAQUERYSETW))
  763. {
  764. lpqsResults = &wsaqDummy;
  765. }
  766. lSpare = (LONG)*lpdwBufferLength - sizeof(WSAQUERYSETW);
  767. memset(lpqsResults, 0, sizeof(WSAQUERYSETW));
  768. lpqsResults->dwNameSpace = NS_SAP;
  769. lpqsResults->dwSize = sizeof(WSAQUERYSETW);
  770. psrc = SapGetContext(hLookup);
  771. if(!psrc)
  772. {
  773. SetLastError(WSA_INVALID_HANDLE);
  774. return(SOCKET_ERROR);
  775. }
  776. //
  777. // This is a valid context. Determine whether this is the first
  778. // call to this. If so, we need to determine whether to
  779. // get the information from the bindery or by using SAP.
  780. //
  781. if ( psrc->u_type.bc.lIndex == 0xffffffff )
  782. {
  783. err = WSA_E_NO_MORE;
  784. goto DoneNext;
  785. }
  786. //
  787. // make sure we have the class info info
  788. //
  789. if(!psrc->wSapId)
  790. {
  791. //
  792. // Need to get it
  793. //
  794. UCHAR Buffer[1000];
  795. LPWSASERVICECLASSINFOW lpcli = (LPWSASERVICECLASSINFOW)Buffer;
  796. DWORD dwBufSize;
  797. DWORD nProt1;
  798. dwBufSize = 1000;
  799. lpcli->lpServiceClassId = &psrc->gdType;
  800. if( (err = NSPGetServiceClassInfo(&psrc->gdProvider,
  801. &dwBufSize,
  802. lpcli)) != NO_ERROR)
  803. {
  804. goto DoneNext;
  805. }
  806. err = pLocateSapIdAndProtocls(&psrc->gdType,
  807. lpcli->dwCount,
  808. lpcli->lpClassInfos,
  809. &psrc->wSapId,
  810. &nProt1);
  811. if(err)
  812. {
  813. SetLastError(err);
  814. goto DoneNext;
  815. }
  816. psrc->nProt &= nProt1;
  817. if(!psrc->nProt)
  818. {
  819. //
  820. // no protocols match
  821. //
  822. err = WSANO_DATA;
  823. goto DoneNext;
  824. }
  825. }
  826. //
  827. // this is the state machine for querying. It selects the bindery or
  828. // SAP as appropriate.
  829. //
  830. fDoStateMachine = TRUE; // enter the machine
  831. do
  832. {
  833. //
  834. // switch on the current machine state.
  835. //
  836. switch(psrc->dwUnionType)
  837. {
  838. case LOOKUP_TYPE_NIL:
  839. psrc->u_type.bc.lIndex = -1;
  840. psrc->dwUnionType = LOOKUP_TYPE_BINDERY;
  841. break; // reenter state machine
  842. case LOOKUP_TYPE_BINDERY:
  843. //
  844. // try the bindery
  845. //
  846. if(psrc->dwControlFlags & LUP_NEAREST)
  847. {
  848. err = NO_DATA; // skip the bindery
  849. }
  850. else
  851. {
  852. //
  853. // otherwise, try the bindery
  854. //
  855. EnterCriticalSection(&psrc->u_type.sbc.csMonitor);
  856. lLastIndex = psrc->u_type.bc.lIndex; // save it
  857. err = NwpGetRnRAddress(
  858. &psrc->hServer,
  859. (psrc->wszContext[0] ?
  860. &psrc->wszContext[0] :
  861. 0),
  862. &psrc->u_type.bc.lIndex,
  863. (psrc->chwName[0] ?
  864. psrc->chwName :
  865. 0),
  866. psrc->wSapId,
  867. &dwVersion,
  868. 48 * sizeof(WCHAR),
  869. OutName,
  870. &SockAddr);
  871. LeaveCriticalSection(&psrc->u_type.sbc.csMonitor);
  872. }
  873. if(err != NO_ERROR)
  874. {
  875. if((psrc->u_type.bc.lIndex == -1))
  876. {
  877. err = PrepareForSap(psrc);
  878. if(err)
  879. {
  880. //
  881. // if we can't, exit the state machine
  882. //
  883. fDoStateMachine = FALSE;
  884. }
  885. }
  886. else
  887. {
  888. //
  889. // no more bindery entries. We will leave the state machine
  890. //
  891. if(err == ERROR_NO_MORE_ITEMS)
  892. {
  893. err = WSA_E_NO_MORE;
  894. }
  895. fDoStateMachine = FALSE;
  896. }
  897. break;
  898. }
  899. else
  900. {
  901. LPWSAVERSION lpVersion = (LPWSAVERSION)&psrc->pvVersion;
  902. if(lpVersion->dwVersion && dwVersion)
  903. {
  904. //
  905. // need to checkout for version matching
  906. //
  907. switch(lpVersion->ecHow)
  908. {
  909. case COMP_EQUAL:
  910. if(lpVersion->dwVersion != dwVersion)
  911. {
  912. continue; //reenter machine
  913. }
  914. break;
  915. case COMP_NOTLESS:
  916. if(lpVersion->dwVersion > dwVersion)
  917. {
  918. continue;
  919. }
  920. break;
  921. default:
  922. continue; // error. If we don't
  923. // know how to compare, we
  924. // must reject it.
  925. }
  926. }
  927. //
  928. // have a suitable item.
  929. // return the name and type and all
  930. // that
  931. err = pRnRReturnResults(
  932. OutName,
  933. &psrc->gdType,
  934. dwVersion,
  935. &pData,
  936. &lSpare,
  937. (PBYTE)SockAddr.sa_netnum,
  938. psrc->nProt,
  939. psrc->dwControlFlags,
  940. lpqsResults);
  941. if(err == WSAEFAULT)
  942. {
  943. //
  944. // no room. Return buffer size required and
  945. // restore the index
  946. //
  947. *lpdwBufferLength =
  948. (DWORD)((LONG)*lpdwBufferLength - lSpare);
  949. psrc->u_type.bc.lIndex = lLastIndex;
  950. }
  951. fDoStateMachine = FALSE;
  952. }
  953. break;
  954. case LOOKUP_TYPE_SAP:
  955. //
  956. // Use SAP.
  957. //
  958. {
  959. WORD QueryType;
  960. if(psrc->dwControlFlags & LUP_NEAREST)
  961. {
  962. QueryType = QT_NEAREST_QUERY;
  963. }
  964. else
  965. {
  966. QueryType = QT_GENERAL_QUERY;
  967. }
  968. err = DoASap(psrc,
  969. QueryType,
  970. &pData,
  971. lpqsResults,
  972. &lSpare,
  973. lpdwBufferLength);
  974. if((err == WSA_E_NO_MORE)
  975. &&
  976. !(psrc->fFlags & SAP_F_END_CALLED)
  977. &&
  978. (QueryType == QT_NEAREST_QUERY)
  979. &&
  980. (psrc->dwControlFlags & LUP_DEEP)
  981. &&
  982. !psrc->u_type.sbc.psdHead)
  983. {
  984. //
  985. // didn't find it locally. Turn off LUP_NEAREST
  986. // and do this as a general query. This might bring
  987. // it back to a SAP query, but this time
  988. // without LUP_NEAREST. But starting anew
  989. // allows the use of the bindery and that
  990. // might find things quickly.
  991. //
  992. psrc->dwControlFlags &= ~LUP_NEAREST;
  993. psrc->dwUnionType = LOOKUP_TYPE_NIL;
  994. if(psrc->u_type.sbc.s)
  995. {
  996. SapFreeSapSocket(psrc->u_type.sbc.s);
  997. psrc->u_type.sbc.s = 0;
  998. }
  999. }
  1000. else
  1001. {
  1002. fDoStateMachine = FALSE;
  1003. }
  1004. break;
  1005. }
  1006. } // switch
  1007. } while(fDoStateMachine);
  1008. DoneNext:
  1009. SapReleaseContext(psrc);
  1010. if((err != NO_ERROR)
  1011. &&
  1012. (err != (DWORD)SOCKET_ERROR))
  1013. {
  1014. SetLastError(err);
  1015. err = (DWORD)SOCKET_ERROR;
  1016. }
  1017. return((INT)err);
  1018. }
  1019. BOOL
  1020. NSPpCheckCancel(
  1021. PVOID pvArg
  1022. )
  1023. /*++
  1024. Routine Description:
  1025. Coroutine called to check if the SAP lookup has been cancelled.
  1026. For now, this always returns FALSE as we use the flags word in
  1027. the control block instead
  1028. --*/
  1029. {
  1030. return(FALSE);
  1031. }
  1032. DWORD
  1033. NSPpGotSap(
  1034. PSAP_BCAST_CONTROL psbc,
  1035. PSAP_IDENT_HEADER pSap,
  1036. PDWORD pdwErr
  1037. )
  1038. /*++
  1039. Routine Description:
  1040. Coroutine called for each SAP reply received. This decides
  1041. whether to keep the data or not and returns a code telling
  1042. the SAP engine whether to proceed
  1043. Arguments:
  1044. psbc -- the SAP_BCAST_CONTROL
  1045. pSap -- the SAP reply
  1046. pdwErr -- where to put an error code
  1047. --*/
  1048. {
  1049. PSAP_DATA psdData;
  1050. LPWSAQUERYSETW Results = (LPWSAQUERYSETW)psbc->pvArg;
  1051. PSAP_RNR_CONTEXT psrc = psbc->psrc;
  1052. DWORD dwRet = dwrcNil;
  1053. PCHAR pServiceName = (PCHAR)psrc->chName;
  1054. EnterCriticalSection(&psbc->csMonitor);
  1055. //
  1056. // First, check if this is a lookup for a particular name. If so,
  1057. // accept only the name.
  1058. //
  1059. if(*pServiceName)
  1060. {
  1061. if(strcmp(pServiceName, pSap->ServerName))
  1062. {
  1063. goto nota;
  1064. }
  1065. if(!(psrc->dwControlFlags & LUP_NEAREST))
  1066. {
  1067. dwRet = dwrcDone;
  1068. psbc->fFlags |= SBC_FLAG_NOMORE;
  1069. }
  1070. }
  1071. //
  1072. // see if we want to keep this guy
  1073. // We keep it if we don't already have it in the list
  1074. //
  1075. for(psdData = psbc->psdHead;
  1076. psdData;
  1077. psdData = psdData->sapNext)
  1078. {
  1079. if(RtlEqualMemory( psdData->socketAddr,
  1080. &pSap->Address,
  1081. IPX_ADDRESS_LENGTH))
  1082. {
  1083. goto nota; // we have it already
  1084. }
  1085. }
  1086. psdData = (PSAP_DATA)LocalAlloc(LPTR, sizeof(SAP_DATA));
  1087. if(!psdData)
  1088. {
  1089. goto nota; // can't save it
  1090. }
  1091. psdData->sapid = pSap->ServerType;
  1092. RtlMoveMemory(psdData->sapname,
  1093. pSap->ServerName,
  1094. 48);
  1095. RtlMoveMemory(psdData->socketAddr,
  1096. &pSap->Address,
  1097. IPX_ADDRESS_LENGTH);
  1098. if(psbc->psdTail)
  1099. {
  1100. psbc->psdTail->sapNext = psdData;
  1101. }
  1102. else
  1103. {
  1104. psbc->psdHead = psdData;
  1105. }
  1106. psbc->psdTail = psdData;
  1107. if(!psbc->psdNext1)
  1108. {
  1109. psbc->psdNext1 = psdData;
  1110. }
  1111. nota:
  1112. LeaveCriticalSection(&psbc->csMonitor);
  1113. if((dwRet == dwrcNil)
  1114. &&
  1115. psbc->psdNext1)
  1116. {
  1117. dwRet = dwrcNoWait;
  1118. }
  1119. return(dwRet);
  1120. }
  1121. INT WINAPI
  1122. NSPUnInstallNameSpace(
  1123. IN LPGUID lpProviderId
  1124. )
  1125. {
  1126. return(NO_ERROR);
  1127. }
  1128. INT WINAPI
  1129. NSPCleanup(
  1130. IN LPGUID lpProviderId
  1131. )
  1132. {
  1133. //
  1134. // Make sure all contexts are released
  1135. //
  1136. // pFreeAllContexts(); // done in Dll Process detach
  1137. return(NO_ERROR);
  1138. }
  1139. INT WINAPI
  1140. NSPLookupServiceEnd(
  1141. IN HANDLE hLookup
  1142. )
  1143. {
  1144. PSAP_RNR_CONTEXT psrc;
  1145. psrc = SapGetContext(hLookup);
  1146. if(!psrc)
  1147. {
  1148. SetLastError(WSA_INVALID_HANDLE);
  1149. return(SOCKET_ERROR);
  1150. }
  1151. psrc->fFlags |= SAP_F_END_CALLED;
  1152. SapReleaseContext(psrc); // get rid of it
  1153. SapReleaseContext(psrc); // and close it. Context cleanup is
  1154. // done on the last derefernce.
  1155. return(NO_ERROR);
  1156. }
  1157. INT WINAPI
  1158. NSPSetService(
  1159. IN LPGUID lpProviderId,
  1160. IN LPWSASERVICECLASSINFOW lpServiceClassInfo,
  1161. IN LPWSAQUERYSETW lpqsRegInfo,
  1162. IN WSAESETSERVICEOP essOperation,
  1163. IN DWORD dwControlFlags
  1164. )
  1165. {
  1166. /*++
  1167. Routine Description:
  1168. The routine that implements the RnR SetService routine. Note that
  1169. context is ignored. There is no way to direct the registration to
  1170. a particular server.
  1171. --*/
  1172. PBYTE pbAddress;
  1173. DWORD dwOperation;
  1174. PBYTE pbSocket;
  1175. DWORD dwAddrs;
  1176. DWORD err = NO_ERROR;
  1177. WORD wSapId;
  1178. DWORD nProt, dwAddress;
  1179. BOOL fAdvert = FALSE;
  1180. DWORD dwNumClassInfo;
  1181. LPWSANSCLASSINFOW lpClassInfoBuf;
  1182. //
  1183. // Verify all args present
  1184. //
  1185. if(!lpqsRegInfo->lpszServiceInstanceName
  1186. ||
  1187. !lpqsRegInfo->lpServiceClassId)
  1188. {
  1189. SetLastError(WSA_INVALID_PARAMETER);
  1190. return(SOCKET_ERROR);
  1191. }
  1192. if(!lpServiceClassInfo && !IS_SVCID_NETWARE(lpqsRegInfo->lpServiceClassId))
  1193. {
  1194. UCHAR Buffer[1000];
  1195. LPWSASERVICECLASSINFOW lpcli = (LPWSASERVICECLASSINFOW)Buffer;
  1196. DWORD dwBufSize;
  1197. dwBufSize = 1000;
  1198. lpcli->lpServiceClassId = lpqsRegInfo->lpServiceClassId;
  1199. if(pGetServiceClassInfo(lpProviderId,
  1200. &dwBufSize,
  1201. lpcli,
  1202. &fAdvert) != NO_ERROR)
  1203. {
  1204. return(SOCKET_ERROR);
  1205. }
  1206. dwNumClassInfo = lpcli->dwCount;
  1207. lpClassInfoBuf = lpcli->lpClassInfos;
  1208. }
  1209. else if (lpServiceClassInfo)
  1210. {
  1211. dwNumClassInfo = lpServiceClassInfo->dwCount;
  1212. lpClassInfoBuf = lpServiceClassInfo->lpClassInfos;
  1213. }
  1214. else
  1215. {
  1216. // lpServiceClassId is a GUID which defines the SapId. This means
  1217. // that pLocateSapIdAndProtocls doesn't need the lpClassInfoBuf.
  1218. dwNumClassInfo = 0;
  1219. lpClassInfoBuf = 0;
  1220. }
  1221. //
  1222. // Find the IPX address in the input args
  1223. //
  1224. err = pLocateSapIdAndProtocls(lpqsRegInfo->lpServiceClassId,
  1225. dwNumClassInfo,
  1226. lpClassInfoBuf,
  1227. &wSapId,
  1228. &nProt);
  1229. if(err == NO_ERROR)
  1230. {
  1231. if(essOperation == RNRSERVICE_REGISTER)
  1232. {
  1233. PCSADDR_INFO pcsaAddress;
  1234. pcsaAddress = lpqsRegInfo->lpcsaBuffer;
  1235. try
  1236. {
  1237. for(dwAddrs = lpqsRegInfo->dwNumberOfCsAddrs;
  1238. dwAddrs;
  1239. dwAddrs--, pcsaAddress++)
  1240. {
  1241. if(pcsaAddress->LocalAddr.lpSockaddr->sa_family == AF_IPX)
  1242. {
  1243. pbSocket =
  1244. (PBYTE)pcsaAddress->LocalAddr.lpSockaddr;
  1245. break;
  1246. }
  1247. }
  1248. }
  1249. except(EXCEPTION_EXECUTE_HANDLER)
  1250. {
  1251. err = GetExceptionCode();
  1252. }
  1253. if(err || !dwAddrs)
  1254. {
  1255. err = ERROR_INCORRECT_ADDRESS;
  1256. }
  1257. else if(fAdvert)
  1258. {
  1259. NwpSetClassInfoAdvertise(lpqsRegInfo->lpServiceClassId,
  1260. wSapId);
  1261. }
  1262. }
  1263. else
  1264. {
  1265. pbSocket = 0;
  1266. }
  1267. if(err == NO_ERROR)
  1268. {
  1269. //
  1270. // map the operation, and call the common worker
  1271. //
  1272. switch(essOperation)
  1273. {
  1274. case RNRSERVICE_REGISTER:
  1275. dwOperation = oldRnRServiceRegister;
  1276. break;
  1277. case RNRSERVICE_DEREGISTER:
  1278. case RNRSERVICE_DELETE:
  1279. dwOperation = oldRnRServiceDeRegister;
  1280. break;
  1281. default:
  1282. err = WSA_INVALID_PARAMETER;
  1283. break;
  1284. }
  1285. if(err == NO_ERROR)
  1286. {
  1287. err = pSapSetService2(
  1288. dwOperation,
  1289. lpqsRegInfo->lpszServiceInstanceName,
  1290. pbSocket,
  1291. lpqsRegInfo->lpServiceClassId,
  1292. wSapId);
  1293. }
  1294. }
  1295. }
  1296. if(err != NO_ERROR)
  1297. {
  1298. SetLastError(err);
  1299. err = (DWORD)SOCKET_ERROR;
  1300. }
  1301. return(err);
  1302. }
  1303. INT WINAPI
  1304. NSPInstallServiceClass(
  1305. IN LPGUID lpProviderId,
  1306. IN LPWSASERVICECLASSINFOW lpServiceClassInfo
  1307. )
  1308. {
  1309. LPWSANSCLASSINFOW pcli, pcli1 = 0;
  1310. DWORD dwIndex = lpServiceClassInfo->dwCount;
  1311. CHAR PropertyBuffer[128];
  1312. PBINDERYCLASSES pbc = (PBINDERYCLASSES)PropertyBuffer;
  1313. BYTE bData = (BYTE)&((PBINDERYCLASSES)0)->cDataArea[0];
  1314. PCHAR pszData = &pbc->cDataArea[0];
  1315. DWORD err;
  1316. DWORD iter;
  1317. WORD port = 0, sap = 0;
  1318. BOOL fIsSAP = FALSE;
  1319. //
  1320. // Check a few parameters . . .
  1321. //
  1322. if ( lpServiceClassInfo == NULL )
  1323. {
  1324. SetLastError(WSA_INVALID_PARAMETER);
  1325. return(SOCKET_ERROR);
  1326. }
  1327. if ( !lpServiceClassInfo->lpServiceClassId ||
  1328. !lpServiceClassInfo->lpszServiceClassName ||
  1329. ( lpServiceClassInfo->dwCount &&
  1330. !lpServiceClassInfo->lpClassInfos ) )
  1331. {
  1332. SetLastError(WSA_INVALID_PARAMETER);
  1333. return(SOCKET_ERROR);
  1334. }
  1335. //
  1336. // Test to see if the ServiceClassId is TCP's, if so we don't allow
  1337. // the service class installation since these are already present.
  1338. //
  1339. if ( GuidEqual( lpServiceClassInfo->lpServiceClassId,
  1340. &HostAddrByInetStringGuid ) ||
  1341. GuidEqual( lpServiceClassInfo->lpServiceClassId,
  1342. &ServiceByNameGuid ) ||
  1343. GuidEqual( lpServiceClassInfo->lpServiceClassId,
  1344. &HostNameGuid ) ||
  1345. GuidEqual( lpServiceClassInfo->lpServiceClassId,
  1346. &HostAddrByNameGuid ) )
  1347. {
  1348. SetLastError(WSA_INVALID_PARAMETER);
  1349. return(SOCKET_ERROR);
  1350. }
  1351. for( iter = 0; iter < lpServiceClassInfo->dwCount; iter++ )
  1352. {
  1353. if ( lpServiceClassInfo->lpClassInfos[iter].dwNameSpace == NS_SAP ||
  1354. lpServiceClassInfo->lpClassInfos[iter].dwNameSpace == NS_ALL )
  1355. fIsSAP = TRUE;
  1356. }
  1357. if ( !fIsSAP )
  1358. {
  1359. SetLastError(WSA_INVALID_PARAMETER);
  1360. return(SOCKET_ERROR);
  1361. }
  1362. //
  1363. // Find the SapId entry
  1364. //
  1365. for(pcli = lpServiceClassInfo->lpClassInfos;
  1366. dwIndex;
  1367. pcli++, dwIndex--)
  1368. {
  1369. WORD wTemp;
  1370. if ( pcli->dwNameSpace == NS_SAP ||
  1371. pcli->dwNameSpace == NS_ALL )
  1372. {
  1373. if(!_wcsicmp(pcli->lpszName, SERVICE_TYPE_VALUE_IPXPORTW)
  1374. &&
  1375. (pcli->dwValueSize == sizeof(WORD)))
  1376. {
  1377. //
  1378. // the value may not be aligned
  1379. //
  1380. ((PBYTE)&wTemp)[0] = ((PBYTE)pcli->lpValue)[0];
  1381. ((PBYTE)&wTemp)[1] = ((PBYTE)pcli->lpValue)[1];
  1382. port = wTemp;
  1383. } else if(!_wcsicmp(pcli->lpszName, SERVICE_TYPE_VALUE_SAPIDW)
  1384. &&
  1385. (pcli->dwValueSize >= sizeof(WORD)))
  1386. {
  1387. ((PBYTE)&wTemp)[0] = ((PBYTE)pcli->lpValue)[0];
  1388. ((PBYTE)&wTemp)[1] = ((PBYTE)pcli->lpValue)[1];
  1389. sap = wTemp;
  1390. pcli1 = pcli;
  1391. }
  1392. }
  1393. }
  1394. if(!(pcli = pcli1))
  1395. {
  1396. SetLastError(WSA_INVALID_PARAMETER);
  1397. return(SOCKET_ERROR);
  1398. }
  1399. #if 0 // old way of doing this
  1400. //
  1401. // Found it. Build the property segment
  1402. //
  1403. memset(PropertyBuffer, 0, 128); // clear out everyting
  1404. pbc->bOffset = bData;
  1405. pbc->bSizeOfString = sizeof("Sapid");
  1406. pbc->bType = BT_WORD; // just a word, I assure you
  1407. pbc->bSizeOfType = 2;
  1408. pbc->wNameSpace = (WORD)NS_SAP; // it's us
  1409. *(PWORD)pszData = htons(*(PWORD)pcli->lpValue);
  1410. pszData += sizeof(WORD); // where the string goes
  1411. strcpy(pszData, "SapId");
  1412. // pbc->bFlags = (BYTE)pcli->dwConnectionFlags;
  1413. err = NwpSetClassInfo(
  1414. lpServiceClassInfo->lpszServiceClassName,
  1415. lpServiceClassInfo->lpServiceClassId,
  1416. PropertyBuffer);
  1417. #else
  1418. err = NwpRnR2AddServiceType(
  1419. lpServiceClassInfo->lpszServiceClassName,
  1420. lpServiceClassInfo->lpServiceClassId,
  1421. sap,
  1422. port);
  1423. #endif
  1424. if(err != NO_ERROR)
  1425. {
  1426. SetLastError(err);
  1427. err = (DWORD)SOCKET_ERROR;
  1428. }
  1429. return(err);
  1430. }
  1431. INT WINAPI
  1432. NSPRemoveServiceClass(
  1433. IN LPGUID lpProviderId,
  1434. IN LPGUID lpServiceCallId
  1435. )
  1436. {
  1437. BOOL success;
  1438. //
  1439. // Do parameter checking
  1440. //
  1441. if ( lpServiceCallId == NULL )
  1442. {
  1443. SetLastError( WSA_INVALID_PARAMETER );
  1444. return SOCKET_ERROR;
  1445. }
  1446. success = NwpRnR2RemoveServiceType( lpServiceCallId );
  1447. if ( success )
  1448. return( NO_ERROR );
  1449. else
  1450. SetLastError(WSATYPE_NOT_FOUND);
  1451. return (DWORD)SOCKET_ERROR;
  1452. }
  1453. INT WINAPI
  1454. NSPGetServiceClassInfo(
  1455. IN LPGUID lpProviderId,
  1456. IN OUT LPDWORD lpdwBufSize,
  1457. IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
  1458. )
  1459. {
  1460. /*++
  1461. Routine Description:
  1462. Get the ClassInfo for this type. Class info data may be in the
  1463. registry, or available via SAP or the bindery. We try all three
  1464. as appropriate
  1465. --*/
  1466. BOOL fAdvert;
  1467. return(pGetServiceClassInfo(
  1468. lpProviderId,
  1469. lpdwBufSize,
  1470. lpServiceClassInfo,
  1471. &fAdvert));
  1472. }
  1473. INT WINAPI
  1474. pGetServiceClassInfo(
  1475. IN LPGUID lpProviderId,
  1476. IN OUT LPDWORD lpdwBufSize,
  1477. IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo,
  1478. IN PBOOL pfAdvert
  1479. )
  1480. {
  1481. /*++
  1482. Routine Description:
  1483. Get the ClassInfo for this type. Class info data may be in the
  1484. registry, or available via SAP or the bindery. We try all three
  1485. as appropriate
  1486. --*/
  1487. DWORD err;
  1488. LONG lInSize;
  1489. LONG lSizeNeeded;
  1490. PBYTE pbBuffer;
  1491. GUID gdDummy;
  1492. PWCHAR pwszUuid;
  1493. LPGUID pType;
  1494. WORD wSapId;
  1495. WORD wPort;
  1496. SOCKADDR_IPX sock;
  1497. PWCHAR pwszSaveName = lpServiceClassInfo->lpszServiceClassName;
  1498. #define SIZENEEDED (sizeof(WSASERVICECLASSINFO) + \
  1499. sizeof(WSANSCLASSINFO) + \
  1500. sizeof(WSANSCLASSINFO) + \
  1501. 10 + 2 + \
  1502. sizeof(GUID) + 12 + 2)
  1503. *pfAdvert = FALSE;
  1504. lInSize = (LONG)*lpdwBufSize - SIZENEEDED;
  1505. pType = (LPGUID)(lpServiceClassInfo + 1);
  1506. pbBuffer = (PBYTE)(pType + 1);
  1507. if(lInSize < 0)
  1508. {
  1509. //
  1510. // it is too small already
  1511. //
  1512. pType = &gdDummy;
  1513. }
  1514. if (UuidToString(lpServiceClassInfo->lpServiceClassId, &pwszUuid) != RPC_S_OK) {
  1515. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1516. return SOCKET_ERROR;
  1517. }
  1518. //
  1519. // First, try the bindery
  1520. //
  1521. err = NwpGetAddressByName(0,
  1522. RNRCLASSSAPTYPE,
  1523. pwszUuid,
  1524. &sock);
  1525. if(err == NO_ERROR)
  1526. {
  1527. wSapId = ntohs(*(PWORD)&sock.sa_netnum);
  1528. wPort = ntohs(*(PWORD)&sock.sa_socket);
  1529. }
  1530. else
  1531. {
  1532. UCHAR Buffer[400];
  1533. DWORD dwLen = 400;
  1534. DWORD dwNum;
  1535. //
  1536. // try SAP
  1537. //
  1538. err = NwpGetAddressViaSap(RNRCLASSSAPTYPE,
  1539. pwszUuid,
  1540. IPX_BIT,
  1541. (PVOID)Buffer,
  1542. &dwLen,
  1543. 0,
  1544. &dwNum);
  1545. if((err == NO_ERROR)
  1546. &&
  1547. (dwNum > 0) )
  1548. {
  1549. PCSADDR_INFO psca = (PCSADDR_INFO)Buffer;
  1550. PSOCKADDR_IPX psock = (PSOCKADDR_IPX)psca->RemoteAddr.lpSockaddr;
  1551. wSapId = ntohs(*(PWORD)&psock->sa_netnum);
  1552. wPort = ntohs(*(PWORD)&sock.sa_socket);
  1553. }
  1554. else
  1555. {
  1556. //
  1557. // try the local bindery
  1558. if(!NwpLookupSapInRegistry(
  1559. lpServiceClassInfo->lpServiceClassId,
  1560. &wSapId,
  1561. &wPort,
  1562. NULL))
  1563. {
  1564. err = WSASERVICE_NOT_FOUND;
  1565. }
  1566. else
  1567. {
  1568. *pfAdvert = TRUE;
  1569. err = NO_ERROR;
  1570. }
  1571. }
  1572. }
  1573. RpcStringFree(&pwszUuid);
  1574. if(err != NO_ERROR)
  1575. {
  1576. SetLastError(err);
  1577. err = (DWORD)SOCKET_ERROR;
  1578. }
  1579. else
  1580. {
  1581. //
  1582. // we return the input structure and the found type. That's it.
  1583. // The space needed is a constant since we don't return the name
  1584. //
  1585. if(lInSize < 0)
  1586. {
  1587. SetLastError(WSAEFAULT);
  1588. *lpdwBufSize += (DWORD)(-lInSize);
  1589. err = (DWORD)SOCKET_ERROR;
  1590. }
  1591. else
  1592. {
  1593. LPWSANSCLASSINFOW pci = (LPWSANSCLASSINFOW)pbBuffer;
  1594. PUCHAR Buff;
  1595. //
  1596. // it will fit. SO let's go
  1597. //
  1598. if(wPort)
  1599. {
  1600. Buff = (PCHAR)(pci + 2);
  1601. }
  1602. else
  1603. {
  1604. Buff = (PCHAR)(pci + 1);
  1605. }
  1606. *pType = *lpServiceClassInfo->lpServiceClassId;
  1607. lpServiceClassInfo->lpServiceClassId = pType;
  1608. lpServiceClassInfo->lpszServiceClassName = 0; // not a
  1609. lpServiceClassInfo->dwCount = 1;
  1610. lpServiceClassInfo->lpClassInfos = pci;
  1611. pci->dwNameSpace = NS_SAP;
  1612. pci->dwValueType = REG_DWORD;
  1613. pci->dwValueSize = 2;
  1614. pci->lpszName = (LPWSTR)Buff;
  1615. wcscpy((PWCHAR)Buff, L"SapId");
  1616. Buff += 6 * sizeof(WCHAR);
  1617. pci->lpValue = (LPVOID)Buff;
  1618. *(PWORD)Buff = wSapId;
  1619. Buff += sizeof(WORD);
  1620. if(wPort)
  1621. {
  1622. lpServiceClassInfo->dwCount++;
  1623. pci++;
  1624. pci->dwNameSpace = NS_SAP;
  1625. pci->dwValueType = REG_DWORD;
  1626. pci->dwValueSize = 2;
  1627. pci->lpszName = (LPWSTR)Buff;
  1628. wcscpy((PWCHAR)Buff, L"Port");
  1629. Buff += 5 * sizeof(WCHAR);
  1630. pci->lpValue = (LPVOID)Buff;
  1631. *(PWORD)Buff = wPort;
  1632. }
  1633. }
  1634. }
  1635. return(err);
  1636. }
  1637. INT WINAPI
  1638. NSPStartup(
  1639. IN LPGUID lpProviderId,
  1640. IN OUT LPNSP_ROUTINE lpsnpRoutines)
  1641. {
  1642. // DWORD dwSize = min(sizeof(nsrVector), lpsnpRoutines->cbSize);
  1643. DWORD dwSize = sizeof(nsrVector);
  1644. RtlCopyMemory(lpsnpRoutines,
  1645. &nsrVector,
  1646. dwSize);
  1647. return(NO_ERROR);
  1648. }
  1649. DWORD
  1650. DoASap(
  1651. IN PSAP_RNR_CONTEXT psrc,
  1652. IN WORD QueryType,
  1653. IN PBYTE * ppData,
  1654. IN LPWSAQUERYSETW lpqsResults,
  1655. IN PLONG plSpare,
  1656. IN PDWORD lpdwBufferLength
  1657. )
  1658. /*++
  1659. Small routine to construcst a SAP_BROADCAST pakcet and issue the SAP
  1660. --*/
  1661. {
  1662. DWORD err;
  1663. if(!psrc->u_type.sbc.s)
  1664. {
  1665. //
  1666. // this is the first time. We must init the
  1667. // structure
  1668. //
  1669. err = SapGetSapSocket(&psrc->u_type.sbc.s);
  1670. if(err)
  1671. {
  1672. psrc->u_type.sbc.s = 0; // make sure
  1673. return(err);
  1674. }
  1675. psrc->u_type.sbc.Func = NSPpGotSap;
  1676. psrc->u_type.sbc.fCheckCancel = NSPpCheckCancel;
  1677. psrc->u_type.sbc.dwIndex = 0; // just in case.
  1678. psrc->u_type.sbc.pvArg = (PVOID)lpqsResults;
  1679. psrc->u_type.sbc.psrc = psrc;
  1680. psrc->u_type.sbc.fFlags = 0;
  1681. }
  1682. psrc->u_type.sbc.wQueryType = QueryType;
  1683. if(!psrc->u_type.sbc.psdNext1
  1684. &&
  1685. !(psrc->u_type.sbc.fFlags & SBC_FLAG_NOMORE))
  1686. {
  1687. err = SapGetSapForType(&psrc->u_type.sbc, psrc->wSapId);
  1688. }
  1689. EnterCriticalSection(&psrc->u_type.sbc.csMonitor);
  1690. if(psrc->u_type.sbc.psdNext1)
  1691. {
  1692. //
  1693. // Got something to return. Let's do it
  1694. //
  1695. //
  1696. // Assume we have to return the name
  1697. //
  1698. //
  1699. // We have to convert the name to UNICODE so
  1700. // we can return it to the caller.
  1701. //
  1702. //
  1703. OEM_STRING Oem;
  1704. NTSTATUS status;
  1705. UNICODE_STRING UString;
  1706. RtlInitAnsiString(&Oem,
  1707. psrc->u_type.sbc.psdNext1->sapname);
  1708. status = RtlOemStringToUnicodeString(
  1709. &UString,
  1710. &Oem,
  1711. TRUE);
  1712. if(NT_SUCCESS(status))
  1713. {
  1714. if(psrc->wSapId == OT_DIRSERVER)
  1715. {
  1716. PWCHAR pwszTemp = &UString.Buffer[31];
  1717. while(*pwszTemp == L'_')
  1718. {
  1719. *pwszTemp-- = 0;
  1720. }
  1721. }
  1722. err = pRnRReturnResults(
  1723. UString.Buffer,
  1724. &psrc->gdType,
  1725. 0, // never a version
  1726. ppData,
  1727. plSpare,
  1728. psrc->u_type.sbc.psdNext1->socketAddr,
  1729. psrc->nProt,
  1730. psrc->dwControlFlags,
  1731. lpqsResults);
  1732. RtlFreeUnicodeString(&UString);
  1733. if(err == WSAEFAULT)
  1734. {
  1735. //
  1736. // no room. Return buffer size required
  1737. //
  1738. *lpdwBufferLength =
  1739. (DWORD)((LONG)*lpdwBufferLength - *plSpare);
  1740. }
  1741. }
  1742. else
  1743. {
  1744. err = (DWORD)status;
  1745. }
  1746. if(err == NO_ERROR)
  1747. {
  1748. //
  1749. // if we got it, step the item
  1750. //
  1751. psrc->u_type.sbc.psdNext1 =
  1752. psrc->u_type.sbc.psdNext1->sapNext;
  1753. }
  1754. }
  1755. else
  1756. {
  1757. err = (DWORD)WSA_E_NO_MORE;
  1758. }
  1759. LeaveCriticalSection(&psrc->u_type.sbc.csMonitor);
  1760. return(err);
  1761. }
  1762. DWORD
  1763. PrepareForSap(
  1764. IN PSAP_RNR_CONTEXT psrc
  1765. )
  1766. /*++
  1767. Called when there is no bindery or the bindery does not have the
  1768. entry. This initializes the values needed for a SAP search
  1769. --*/
  1770. {
  1771. OEM_STRING OemServiceName;
  1772. UNICODE_STRING UString;
  1773. NTSTATUS status;
  1774. //
  1775. // the bindery didn't work. Use SAP.
  1776. //
  1777. psrc->u_type.sbc.dwIndex =
  1778. psrc->u_type.sbc.dwTickCount = 0;
  1779. if(psrc->wszContext[0])
  1780. {
  1781. return(WSASERVICE_NOT_FOUND); // no contexts in SAP
  1782. }
  1783. RtlInitUnicodeString(&UString,
  1784. psrc->chwName);
  1785. status = RtlUnicodeStringToOemString(&OemServiceName,
  1786. &UString,
  1787. TRUE);
  1788. if(!NT_SUCCESS(status))
  1789. {
  1790. return( (DWORD)status);
  1791. }
  1792. strcpy((PCHAR)&psrc->chName,
  1793. OemServiceName.Buffer);
  1794. RtlFreeOemString(&OemServiceName);
  1795. psrc->dwUnionType = LOOKUP_TYPE_SAP;
  1796. psrc->u_type.sbc.s = 0;
  1797. return(NO_ERROR);
  1798. }