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.

1312 lines
32 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. socket.c
  5. Abstract:
  6. This file contains socket initialization functions, as well as open,
  7. close, bind, enumeration types of functions using WinSock.
  8. Author:
  9. Shaun Pierce (shaunp) 15-Jun-1995
  10. Environment:
  11. User Mode -Win32 (Win95 flavor)
  12. Revision History:
  13. --*/
  14. #include <windows.h>
  15. #include <winerror.h>
  16. #include <winsock.h>
  17. #include <wsipx.h>
  18. #include "wsnetbs.h"
  19. #include <nspapi.h>
  20. // #include "dpwssp.h"
  21. #include "socket.h"
  22. #define PORT_DONT_CARE 0
  23. //
  24. // Global Variables:
  25. //
  26. BOOL bNetIsUp;
  27. /*=============================================================================
  28. CountBits - Counts the number of bits in a number
  29. Description:
  30. Counts the number of bits in a DWORD value passed to the function
  31. Arguments:
  32. x - DWORD value to count the number of bits within
  33. Return Value:
  34. Returns the number of bits within the argument x
  35. -----------------------------------------------------------------------------*/
  36. UINT CountBits(
  37. IN DWORD x
  38. )
  39. {
  40. UINT i;
  41. //
  42. // Go until we've rotated everything off the right side.
  43. //
  44. for (i=0; x != 0; x >>= 1) {
  45. if (x & 01) {
  46. //
  47. // The bit in position 0 is ON! Count it!!!
  48. //
  49. i++;
  50. }
  51. }
  52. //
  53. // i now contains how many bits we counted while rotating
  54. //
  55. return (i);
  56. }
  57. /*=============================================================================
  58. InitializeWinSock - Locate, bind, and initialize to the WinSock library
  59. Description:
  60. This function attemps to load the WinSock library (wsock32.dll),
  61. extract function pointers, and then initialize to a 1.1 version
  62. of WinSock.
  63. Arguments:
  64. None.
  65. Return Value:
  66. Returns NO_ERROR if everything goes ok, else if anything occurred
  67. that prevents initialization, it returns an appropriate Win32 error.
  68. -----------------------------------------------------------------------------*/
  69. UINT InitializeWinSock()
  70. {
  71. UINT err;
  72. WSADATA wsaData;
  73. //
  74. // Preset global bNetIsUp variable to false
  75. //
  76. bNetIsUp = FALSE;
  77. //
  78. // Attempt to load the wsock32.dll library. We do this rather than
  79. // statically binding to wsock32.dll because the game may not have
  80. // any WinSock components present. If we statically bind and there
  81. // are no WinSock components around, the user wont be able to fire up
  82. // their game without the damned dialog boxed coming up. This would
  83. // force them to have WinSock stuff on their machine even if they want
  84. // to play the game by themselves.
  85. //
  86. // BUGBUG: Nice idea, might come back to it. C++ is stricter on checking
  87. // types, though. [johnhall]
  88. //
  89. //
  90. // Get addresses of all the WinSock functions we'll be using. All
  91. // of these variables are globals and shouldn't be modified after
  92. // initially getting these values out of this function.
  93. //
  94. //
  95. // Fire up Winsock
  96. //
  97. err = WSAStartup(MAKEWORD(1,1), &wsaData);
  98. if (err) {
  99. //
  100. // Some kind of Error occurred out of WinSock. They can't use the
  101. // WSAGetLastError function yet, so we've gotta report it back to
  102. // the caller
  103. //
  104. return (err);
  105. }
  106. //
  107. // Set global Boolean variable to indicate we've "bound" to the WinSock
  108. // library, and return no error occurred.
  109. //
  110. bNetIsUp = TRUE;
  111. return (NO_ERROR);
  112. }
  113. /*=============================================================================
  114. OpenSocket - Opens a socket in the family and protocol specified.
  115. Description:
  116. This function opens a socket on the family and protocol specified,
  117. but it doesn't bind to the socket in question. Once the open has
  118. completed successfully, the socket must be set to reuse local
  119. addresses and enter broadcast mode in order to return a value
  120. of TRUE which signifies success for the entire operation.
  121. Arguments:
  122. iAddressFamily - The address format specification.
  123. iProtocol - The protocol to use within the address family.
  124. pSocket - Pointer to a variable to receive a socket descriptor.
  125. Return Value:
  126. Returns TRUE if the function was able to open the socket and set
  127. the options needed. Otherwise, return FALSE. Caller can get the
  128. error thru GetLastError().
  129. -----------------------------------------------------------------------------*/
  130. BOOL OpenSocket(
  131. IN INT iAddressFamily,
  132. IN INT iProtocol,
  133. OUT SOCKET *pSocket
  134. )
  135. {
  136. UINT err;
  137. BOOL bTrue = TRUE;
  138. //
  139. // Make sure we've at least initialized with the WinSock library
  140. //
  141. if (!bNetIsUp) {
  142. SetLastError(WSANOTINITIALISED);
  143. return (FALSE);
  144. }
  145. //
  146. // If the socket provided is already open, fail.
  147. //
  148. if (*pSocket != INVALID_SOCKET) {
  149. SetLastError(WSAEADDRINUSE);
  150. return (FALSE);
  151. }
  152. //
  153. // Attempt to create the socket based on what the caller wants. No
  154. // validation here on type or family. It is assumed that an enumeration
  155. // was done prior to this
  156. //
  157. *pSocket = socket(iAddressFamily, SOCK_DGRAM, iProtocol);
  158. if (*pSocket == INVALID_SOCKET) {
  159. return (FALSE);
  160. }
  161. //
  162. // Enable socket for broadcast and allow reuse of local addresses
  163. //
  164. err = setsockopt(*pSocket, SOL_SOCKET, SO_BROADCAST, (LPSTR) &bTrue, sizeof(bTrue));
  165. if (err == SOCKET_ERROR) {
  166. //
  167. // For some reason, WinSock wouldn't let us set the socket
  168. // to allow transmission of broadcast messages. Got no choice
  169. // but to return failure. We'll trap here on debug builds to try
  170. // and see what is going on.
  171. //
  172. err = GetLastError();
  173. CloseSocket(*pSocket, 0);
  174. return (FALSE);
  175. }
  176. //
  177. // Both socket options worked, return TRUE to caller to inform them
  178. // of the success of the entire operation
  179. //
  180. return (TRUE);
  181. }
  182. /*=============================================================================
  183. BindSocket - Binds an already existing socket to a family address
  184. Description:
  185. This function binds an already existing socket to an address via
  186. the port, and family specified. Currently, only IP and IPX are
  187. supported. So support binding to new types of families, simply
  188. add to the switch statement below and fill in the necessary
  189. address specific details.
  190. The last two parameters, (pSockAddr and pSockAddrLen), are
  191. optional. If these two parameters are NULL, this function binds
  192. to the family and port specified. If these two parameters are
  193. NON NULL, then these two parameters are taken as gospel and
  194. the socket will be bound to them.
  195. Arguments:
  196. Socket - socket to be bound
  197. iAddressFamily - The address format specification.
  198. iPort - Requested port wanted on this particular address
  199. pSockAddr - Optional pointer to well known address to bind to
  200. nSockAddrLen - Optional pointer to length of pSockAddr
  201. Return Value:
  202. Returns NO_ERROR if everything goes ok, else if anything occurred
  203. that prevents binding to the address type specified, an appropriate
  204. Win32 error is returned.
  205. -----------------------------------------------------------------------------*/
  206. UINT BindSocket(
  207. IN SOCKET Socket,
  208. IN INT iAddressFamily,
  209. IN INT iPort,
  210. IN PSOCKADDR pSockAddr,
  211. IN LPINT pSockAddrLen
  212. )
  213. {
  214. UINT err;
  215. SOCKADDR SockAddr;
  216. PSOCKADDR_IN pIPAddr;
  217. PSOCKADDR_IPX pIPXAddr;
  218. //
  219. // Lets at least make sure we're binding a real socket here
  220. //
  221. if (Socket == INVALID_SOCKET) {
  222. SetLastError(WSAENOTSOCK);
  223. return (FALSE);
  224. }
  225. //
  226. // Here's where we check to see if pSockAddr and pSockAddrLen
  227. // are NULL. If NON NULL, use address specified and bind to it.
  228. //
  229. if ((pSockAddr) && (pSockAddrLen)) {
  230. //
  231. // Both ponters are NON NULL, so just use what they provided.
  232. //
  233. err = bind(Socket, pSockAddr, *pSockAddrLen);
  234. if (err == SOCKET_ERROR) {
  235. //
  236. // Couldn't bind socket to this address
  237. //
  238. return (GetLastError());
  239. }
  240. return (NO_ERROR);
  241. }
  242. //
  243. // Zero out the socket address structure and dispatch based on the
  244. // address family. If you want this function to handle additional
  245. // types of families, this is the place to add the functionality.
  246. //
  247. memset(&SockAddr, 0, sizeof(SOCKADDR));
  248. switch (iAddressFamily) {
  249. case AF_INET:
  250. //
  251. // Setup IP specific pointer and fill in the appropriate fields
  252. //
  253. pIPAddr = (PSOCKADDR_IN) &SockAddr;
  254. pIPAddr->sin_family = (SHORT)iAddressFamily;
  255. pIPAddr->sin_port = htons((USHORT)iPort);
  256. err = bind(Socket, (SOCKADDR *) pIPAddr, sizeof(SOCKADDR_IN));
  257. if (err == SOCKET_ERROR) {
  258. //
  259. // Couldn't bind socket to this address
  260. //
  261. return (GetLastError());
  262. }
  263. return (NO_ERROR);
  264. case AF_IPX:
  265. //
  266. // Setup IPX specific pointer and fill in the appropriate fields
  267. //
  268. pIPXAddr = (PSOCKADDR_IPX) &SockAddr;
  269. pIPXAddr->sa_family = (SHORT)iAddressFamily;
  270. pIPXAddr->sa_socket = htons((USHORT)iPort);
  271. err = bind((SOCKET) Socket, (SOCKADDR *) pIPXAddr, sizeof(SOCKADDR_IPX));
  272. if (err == SOCKET_ERROR) {
  273. //
  274. // Couldn't bind socket to this address
  275. //
  276. return (GetLastError());
  277. }
  278. return (NO_ERROR);
  279. default:
  280. return (ERROR_NOT_SUPPORTED);
  281. }
  282. }
  283. /*=============================================================================
  284. GetSocketAddr - Gets the address for a particular bound socket
  285. Description:
  286. This function gets the address for a particular socket. Although
  287. this routine just uses WinSock to get the address, I'm attempting
  288. to centralize the WinSock specific calls in one location so we can
  289. do extra validation on parameters, or perhaps use new types of
  290. sockets in the future that don't use WinSock.
  291. Arguments:
  292. Socket - Socket from which to receive address
  293. pAddress - Pointer to buffer to receive address description
  294. pAddressLen - Pointer to address of length of address buffer
  295. Return Value:
  296. Returns NO_ERROR if everything goes ok, else if anything occurred
  297. that prevents getting the address, an appropriate Win32 error
  298. is returned.
  299. -----------------------------------------------------------------------------*/
  300. UINT GetSocketAddr(
  301. IN SOCKET Socket,
  302. OUT PSOCKADDR pAddress,
  303. IN PINT pAddressLen
  304. )
  305. {
  306. UINT err;
  307. //
  308. // Lets at least make sure we're binding a real socket here
  309. //
  310. if (Socket == INVALID_SOCKET) {
  311. SetLastError(WSAENOTSOCK);
  312. return (FALSE);
  313. }
  314. //
  315. // Seems to be a legitimate socket. Call WinSock to get address
  316. //
  317. err = getsockname(Socket, pAddress, pAddressLen);
  318. if (err == SOCKET_ERROR) {
  319. //
  320. // For some reason, WinSock wouldn't let us get the address.
  321. // Return the error. This case is so rare we should trap here on
  322. // debug builds to try and see what is going on.
  323. //
  324. return (GetLastError());
  325. }
  326. return (NO_ERROR);
  327. }
  328. /*=============================================================================
  329. CloseSocket - Closes a socket with the interval specified.
  330. Description:
  331. This function closes the socket with timeout interval specified.
  332. Depending on the interval being zero or non zero, the close of
  333. the socket will be a hard or graceful disconnect.
  334. Interval Type of Close Wait for close?
  335. -------- ------------- ---------------
  336. Zero Hard No
  337. Non-zero Graceful Yes
  338. Arguments:
  339. Socket - socket to be closed
  340. interval - timeout interval (in seconds) which decides the behavior
  341. of the close
  342. Return Value:
  343. Returns TRUE if the function was able to close the socket.
  344. Otherwise, return FALSE. Caller can get the real error thru
  345. GetLastError().
  346. -----------------------------------------------------------------------------*/
  347. BOOL CloseSocket(
  348. IN SOCKET Socket,
  349. IN USHORT interval
  350. )
  351. {
  352. UINT err;
  353. LINGER linger;
  354. //
  355. // Lets at least make sure we're shutting down a real socket here
  356. //
  357. if (Socket == INVALID_SOCKET) {
  358. SetLastError(WSAENOTSOCK);
  359. return (FALSE);
  360. }
  361. //
  362. // Seems to be a legitimate socket. Let's set some socket options
  363. // in order to manage how the socket is closed.
  364. //
  365. linger.l_onoff = TRUE;
  366. linger.l_linger = interval;
  367. //
  368. // We don't care if this fails or not, as we're gonna try to close
  369. // the socket anyway.
  370. //
  371. setsockopt(Socket, SOL_SOCKET, SO_LINGER, (CHAR FAR *) &linger, sizeof(linger));
  372. err = closesocket(Socket);
  373. if (err == SOCKET_ERROR) {
  374. //
  375. // For some reason, WinSock wouldn't let us close the socket.
  376. // Got no choice but to return failure. We'll trap here on
  377. // debug builds to try and see what is going on.
  378. //
  379. err = GetLastError();
  380. return (FALSE);
  381. }
  382. return (TRUE);
  383. }
  384. /*=============================================================================
  385. InitializeSocket - Creates and binds the Socket specified
  386. Description:
  387. This function creates a socket and binds to an address. The
  388. address may be passed in, or if pSockAddr and pSockAddrLen are
  389. NULL, then we let WinSock give us an Address.
  390. Arguments:
  391. iAddressFamily - The address format specification.
  392. pSockAddr - Pointer to address to bind to (Optional)
  393. pSockAddrLen - Pointer to length of address (Optional)
  394. pSocket - Pointer to a variable to receive a socket descriptor.
  395. Return Value:
  396. Returns NO_ERROR if everything goes ok, else if anything occurred
  397. that prevents initializing the socket provided, an appropriate Win32
  398. error is returned.
  399. -----------------------------------------------------------------------------*/
  400. UINT InitializeSocket(
  401. IN INT iAddressFamily,
  402. IN PSOCKADDR pSockAddr,
  403. IN LPINT pSockAddrLen,
  404. OUT SOCKET *pSocket
  405. )
  406. {
  407. UINT err;
  408. PSOCKADDR_IN pSockAddrIn;
  409. PSOCKADDR_IPX pSockAddrIPX;
  410. //
  411. // Let's see if the caller provided an address, or do we need to
  412. // let WinSock pick one for us.
  413. //
  414. if ((pSockAddr) && (pSockAddrLen)) {
  415. //
  416. // Yes, they supplied an address. Use it to open a socket and
  417. // then bind to it.
  418. //
  419. switch (iAddressFamily) {
  420. case AF_INET:
  421. //
  422. // Use the IP information provided in pSockAddr. Assume UDP
  423. //
  424. pSockAddrIn = (PSOCKADDR_IN) pSockAddr;
  425. if (!(OpenSocket(pSockAddrIn->sin_family, IPPROTO_UDP, pSocket))) {
  426. //
  427. // Couldn't open the socket for whatever reason.
  428. // Return the real error to the caller.
  429. //
  430. return (GetLastError());
  431. }
  432. err = BindSocket(*pSocket, 0, 0, (PSOCKADDR) pSockAddrIn, pSockAddrLen);
  433. if (err) {
  434. //
  435. // Couldn't bind to that address for whatever reason
  436. // Return the error to the caller.
  437. //
  438. return (err);
  439. }
  440. break;
  441. case AF_IPX:
  442. //
  443. // Use the IPX information provided in pSockAddr. Assume IPX
  444. //
  445. pSockAddrIPX = (PSOCKADDR_IPX) pSockAddr;
  446. if (!(OpenSocket(pSockAddrIPX->sa_family, NSPROTO_IPX, pSocket))) {
  447. //
  448. // Couldn't open the socket for whatever reason.
  449. // Return the real error to the caller.
  450. //
  451. return (GetLastError());
  452. }
  453. err = BindSocket(*pSocket, 0, 0, (PSOCKADDR) pSockAddrIPX, pSockAddrLen);
  454. if (err) {
  455. //
  456. // Couldn't bind to that address for whatever reason
  457. // Return the error to the caller.
  458. //
  459. return (err);
  460. }
  461. break;
  462. default:
  463. //
  464. // Don't know about this Address Family
  465. //
  466. return (ERROR_NOT_SUPPORTED);
  467. }
  468. //
  469. // If we've made it to here, everything must have worked ok.
  470. // Return without error.
  471. //
  472. return (NO_ERROR);
  473. }
  474. //
  475. // No address and address length specified. This means we'll let
  476. // WinSock figure it out for us.
  477. //
  478. switch (iAddressFamily) {
  479. case AF_INET:
  480. //
  481. // Use AddressFamily provided, and assume UDP
  482. //
  483. if (!(OpenSocket(iAddressFamily, IPPROTO_UDP, pSocket))) {
  484. //
  485. // Couldn't open the socket for whatever reason.
  486. // Return the real error to the caller.
  487. //
  488. return (GetLastError());
  489. }
  490. err = BindSocket(*pSocket, iAddressFamily, PORT_DONT_CARE, NULL, NULL);
  491. if (err) {
  492. //
  493. // Couldn't bind to that address for whatever reason
  494. // Return the error to the caller.
  495. //
  496. return (err);
  497. }
  498. break;
  499. case AF_IPX:
  500. //
  501. // Use AddressFamily provided, and assume IPX
  502. //
  503. if (!(OpenSocket(iAddressFamily, NSPROTO_IPX, pSocket))) {
  504. //
  505. // Couldn't open the socket for whatever reason.
  506. // Return the real error to the caller.
  507. //
  508. return (GetLastError());
  509. }
  510. err = BindSocket(*pSocket, iAddressFamily, PORT_DONT_CARE, NULL, NULL);
  511. if (err) {
  512. //
  513. // Couldn't bind to that address for whatever reason
  514. // Return the error to the caller.
  515. //
  516. return (err);
  517. }
  518. break;
  519. default:
  520. //
  521. // Don't know about this Address Family
  522. //
  523. return (ERROR_NOT_SUPPORTED);
  524. }
  525. //
  526. // If we've made it to here, everything must have worked ok. Return
  527. // without error.
  528. //
  529. return (NO_ERROR);
  530. }
  531. /*=============================================================================
  532. GetProtocolInfo - Get information about the protocols beneath WinSock
  533. Description:
  534. This function enumerates all the protocols residing under WinSock
  535. into the prot_info global structure array. It also returns the
  536. total number of protocols available underneath WinSock, detailing
  537. how many of these are connnectionless type of protocols, as well as
  538. a bitmask of the connectionless protocols in the prot_info array.
  539. For performance reasons, we're most interested in the connectionless,
  540. (i.e. datagram driven) protocols. If it turns out that we find
  541. two connectionless protocols in the same address family, we'll
  542. pick the one with more capabilities.
  543. Arguments:
  544. pTotalProtocols - Pointer to variable to receive total number of
  545. installed protocols under WinSock.
  546. pConnectionlessCount - Pointer to variable to receive the number of
  547. installed connectionless protocols under WinSock.
  548. pConnectionlessMask - Pointer to a variable to receive bitmask of
  549. where the connectionless protocols fall in the global prot_info array.
  550. pInfoBuffer - Pointer to buffer to receive the PROTOCOL_INFO structs
  551. pBufferLength - Pointer to variable holding the length of pInfoBuffer
  552. Return Value:
  553. Returns NO_ERROR if everything goes ok, else if anything occurred
  554. that prevents returning the specified data, it returns an appropriate
  555. Win32 error.
  556. -----------------------------------------------------------------------------*/
  557. UINT GetProtocolInfo(
  558. OUT PUSHORT pTotalProtocols,
  559. OUT PUSHORT pConnectionlessCount,
  560. OUT PUSHORT pConnectionlessMask,
  561. IN OUT PPROTOCOL_INFO pInfoBuffer,
  562. IN OUT LPDWORD pBufferLength
  563. )
  564. {
  565. INT TempFamily;
  566. UINT i;
  567. UINT j;
  568. UINT err;
  569. UINT TempBits;
  570. DWORD TempCaps;
  571. USHORT TempMask;
  572. PPROTOCOL_INFO pTempBuffer;
  573. //
  574. // All of the known protocols we want to enumerate are defined here
  575. //
  576. INT KnownProts[] = { IPPROTO_ICMP, IPPROTO_GGP, IPPROTO_TCP, IPPROTO_PUP,
  577. IPPROTO_UDP, IPPROTO_IDP, IPPROTO_ND, IPPROTO_RAW,
  578. IPPROTO_MAX, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII,
  579. NBPROTO_NETBEUI, 0 };
  580. //
  581. // Preset arguments to be zero, in case we hit an error along the way
  582. //
  583. *pTotalProtocols = 0;
  584. *pConnectionlessCount = 0;
  585. *pConnectionlessMask = 0;
  586. //
  587. // Make sure we've at least initialized with the WinSock library
  588. //
  589. if (!bNetIsUp) {
  590. SetLastError(WSANOTINITIALISED);
  591. return (FALSE);
  592. }
  593. //
  594. // We need a big enough buffer to handle however many protocols are
  595. // installed underneath WinSock. If it's not big enough, WinSock
  596. // doesn't even try to tell you how many protocols are there, it
  597. // just bitches and says buffer not big enough.
  598. //
  599. pTempBuffer = pInfoBuffer;
  600. memset(pInfoBuffer, 0, *pBufferLength);
  601. err = EnumProtocols(KnownProts, pInfoBuffer, pBufferLength);
  602. //
  603. // If EnumProtocols really came back with an error, the error will be
  604. // SOCKET_ERROR. From there, you've gotta call GetLastError to figure
  605. // out what happened. Otherwise, the return value is actually the
  606. // number of installed transports underneath WinSock.
  607. //
  608. if (err == SOCKET_ERROR) {
  609. //
  610. // If the error is buffer was not big enough, the size needed
  611. // will already be in the users buffer length variable.
  612. //
  613. return (GetLastError());
  614. }
  615. //
  616. // No error, fill in callers total count field.
  617. //
  618. *pTotalProtocols = (USHORT)err;
  619. //
  620. // Start enumerating the number of connectionless protocols underneath
  621. // WinSock. We're only interested in connectionless protocols from
  622. // different address families.
  623. //
  624. for (i=0; i < err; i++, pInfoBuffer++) {
  625. if (pInfoBuffer->dwServiceFlags & XP_CONNECTIONLESS) {
  626. //
  627. // Found one! We'll go ahead and increment up the number
  628. // of connectionless transports we've found, and turn on
  629. // this position in the bitmask. However, before we accept
  630. // this as gospel, let's take a look and see if we've
  631. // ever seen anything better from this family before.
  632. //
  633. (*pConnectionlessCount)++;
  634. TempMask = *pConnectionlessMask;
  635. *pConnectionlessMask |= 1 << i;
  636. //
  637. // Chew backwards thru the bitmask looking for relatives
  638. //
  639. j = i-1;
  640. TempCaps = pInfoBuffer->dwServiceFlags;
  641. TempBits = CountBits(pInfoBuffer->dwServiceFlags);
  642. TempFamily = pInfoBuffer->iAddressFamily;
  643. //
  644. // As long as there's somebody turned on in the bitmask,
  645. // we gotta check it out.
  646. //
  647. while (TempMask) {
  648. //
  649. // Must have seen some kindof connectionless protocol before
  650. //
  651. if (TempMask & (1 << j)) {
  652. //
  653. // Found a representative of the best connectionless
  654. // protocol within its particular family. If his
  655. // family and mine are the same, then I've gotta
  656. // check to see if I'm better than him.
  657. //
  658. if (TempFamily == pTempBuffer[j].iAddressFamily) {
  659. //
  660. // We are from the same family. So who's better?
  661. // Since there's two of us from the same family,
  662. // we've gotta decrement the count no matter what.
  663. //
  664. UINT PreviousBits;
  665. DWORD PreviousCaps;
  666. (*pConnectionlessCount)--;
  667. PreviousCaps = pTempBuffer[j].dwServiceFlags;
  668. PreviousBits = CountBits(pTempBuffer[j].dwServiceFlags);
  669. if (TempBits > PreviousBits) {
  670. //
  671. // We got more bits than previous one. Turn him
  672. // off (Previous), then break out of this loop.
  673. //
  674. *pConnectionlessMask &= ~(1 << j);
  675. break;
  676. }
  677. else if (TempBits < PreviousBits) {
  678. //
  679. // Previous one is better than me. Turn myself
  680. // off (Temp), and break out of this loop.
  681. //
  682. *pConnectionlessMask &= ~(1 << i);
  683. break;
  684. }
  685. //
  686. // TempBits must be equal to PreviousBits. So we've
  687. // got equal bits, lets see whos got the newer
  688. // capabilities (if any).
  689. //
  690. else if (TempCaps >= PreviousCaps) {
  691. //
  692. // We'll say that the latter one in the
  693. // Enumeration chain is better (Temp).
  694. // Turn off Previous, and break out of this loop.
  695. //
  696. *pConnectionlessMask &= ~(1 << j);
  697. break;
  698. }
  699. else {
  700. //
  701. // Previous one is better than me. Turn myself
  702. // off (Temp), and break out of this loop.
  703. //
  704. *pConnectionlessMask &= ~(1 << i);
  705. break;
  706. }
  707. }
  708. }
  709. //
  710. // Clear the jth bit in the TempMask, and then decrement
  711. // j in order to goto the previous bit position.
  712. //
  713. TempMask &= ~(1 << j);
  714. j--;
  715. }
  716. }
  717. }
  718. return (NO_ERROR);
  719. }
  720. /*=============================================================================
  721. ReceiveAny - Do a blocking receive from anyone.
  722. Description:
  723. This function does a blocking recvfrom() to WinSock.
  724. On input, pBufferLen says how big pBuffer is, but on
  725. output this function will fill in the amount of data
  726. that was received.
  727. Arguments:
  728. Socket - socket to be receive from
  729. pSockAddr - Pointer to buffer where the senders address will be put
  730. pSockAddrLen - Pointer to variable containing length of pSockAddr
  731. pBuffer - Pointer to buffer where receive data will be placed
  732. pBufferLen - On input, points to length of pBuffer. On output,
  733. the length of the received data will be filled in.
  734. Return Value:
  735. Returns NO_ERROR if everything goes ok, else if anything occurred
  736. that prevents receving the specified data, it returns an appropriate
  737. Win32 error.
  738. -----------------------------------------------------------------------------*/
  739. UINT ReceiveAny(
  740. IN SOCKET Socket,
  741. IN OUT PSOCKADDR pSockAddr,
  742. IN LPINT pSockAddrLen,
  743. IN OUT PCHAR pBuffer,
  744. IN OUT LPUINT pBufferLen
  745. )
  746. {
  747. UINT err;
  748. //
  749. // We'll do a recvfrom() using the parameters provided to us
  750. //
  751. err = recvfrom(Socket, pBuffer, *pBufferLen, 0, pSockAddr, pSockAddrLen);
  752. //
  753. // We've come back from the receive, lets check to see if we really
  754. // received something, or is this just an error.
  755. //
  756. if (err == SOCKET_ERROR) {
  757. //
  758. // This is some kind of error. Get the real error and return it
  759. // to the caller.
  760. //
  761. return (GetLastError());
  762. }
  763. //
  764. // Nope, this is a legitimate receive. Now let's fill in how much
  765. // we received and return with No Error.
  766. //
  767. *pBufferLen = err;
  768. return (NO_ERROR);
  769. }
  770. /*=============================================================================
  771. SendTo - Do a blocking send to someone
  772. Description:
  773. This function does a blocking sendto() to WinSock.
  774. On input, pBufferLen says how big pBuffer is, but on
  775. output this function will fill in the amount of data
  776. that was sent.
  777. Arguments:
  778. Socket - socket to send from
  779. pSockAddr - Pointer to destination address structure
  780. SockAddrLen - Length of destination address structure
  781. pBuffer - Pointer to buffer where receive data will be placed
  782. pBufferLen - On input, points to length of pBuffer.
  783. On output, how much data was sent will be filled in
  784. Return Value:
  785. Returns NO_ERROR if everything goes ok, else if anything occurred
  786. that prevents sending the specified data, it returns an appropriate
  787. Win32 error.
  788. -----------------------------------------------------------------------------*/
  789. UINT SendTo(
  790. IN SOCKET Socket,
  791. IN OUT PSOCKADDR pSockAddr,
  792. IN UINT SockAddrLen,
  793. IN OUT PCHAR pBuffer,
  794. IN OUT LPUINT pBufferLen
  795. )
  796. {
  797. UINT err;
  798. //
  799. // We'll do a sendto() using the parameters provided to us
  800. //
  801. err = sendto(Socket, pBuffer, *pBufferLen, 0, pSockAddr, SockAddrLen);
  802. //
  803. // We've come back from the send, lets check to see if we really
  804. // sent something, or is this just an error.
  805. //
  806. if (err == SOCKET_ERROR) {
  807. //
  808. // This is some kind of error. Get the real error and return it
  809. // to the caller.
  810. //
  811. return (GetLastError());
  812. }
  813. //
  814. // Nope, it sent the data. Now let's fill in how much we actually
  815. // sent so the caller knows and return with No Error.
  816. //
  817. *pBufferLen = err;
  818. return (NO_ERROR);
  819. }
  820. /*=============================================================================
  821. ShutdownWinSock - Terminate use of WinSock library
  822. Description:
  823. This function cleans up the use of WinSock library (wsock32.dll)
  824. Arguments:
  825. None.
  826. Return Value:
  827. Returns NO_ERROR if everything goes ok, else if anything occurred
  828. that prevents cleaning up, it returns an appropriate Win32 error.
  829. -----------------------------------------------------------------------------*/
  830. extern "C" UINT ShutdownWinSock()
  831. {
  832. UINT err;
  833. //
  834. // Make sure we've at least initialized with the WinSock library
  835. //
  836. if (!bNetIsUp) {
  837. SetLastError(WSANOTINITIALISED);
  838. return (FALSE);
  839. }
  840. err = WSACleanup();
  841. if (err == SOCKET_ERROR) {
  842. //
  843. // Some kind of Error occurred out of WinSock. Return the
  844. // real error back to the caller.
  845. //
  846. return (GetLastError());
  847. }
  848. //
  849. // Set global Boolean variable to indicate we've shutdown now.
  850. //
  851. bNetIsUp = FALSE;
  852. return (NO_ERROR);
  853. }