Leaked source code of windows server 2003
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.

1834 lines
46 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. iwinsock.cxx
  5. Abstract:
  6. Contains functions to load sockets DLL and entry points. Functions and data
  7. in this module take care of indirecting sockets calls, hence _I_ in front
  8. of the function name
  9. Contents:
  10. IwinsockInitialize
  11. IwinsockTerminate
  12. LoadWinsock
  13. UnloadWinsock
  14. SafeCloseSocket
  15. Author:
  16. Richard L Firth (rfirth) 12-Apr-1995
  17. Environment:
  18. Win32(s) user-mode DLL
  19. Revision History:
  20. 12-Apr-1995 rfirth
  21. Created
  22. 08-May-1996 arthurbi
  23. Added support for Socks Firewalls.
  24. 05-Mar-1998 rfirth
  25. Moved SOCKS support into ICSocket class. Removed SOCKS library
  26. loading/unloading from this module (revert to pre-SOCKS)
  27. --*/
  28. #include <wininetp.h>
  29. #if defined(__cplusplus)
  30. extern "C" {
  31. #endif
  32. #if INET_DEBUG
  33. #if defined(RETAIL_LOGGING)
  34. #define DPRINTF (void)
  35. #else
  36. #define DPRINTF dprintf
  37. #endif
  38. VOID
  39. InitDebugSock(
  40. VOID
  41. );
  42. VOID
  43. TerminateDebugSock(
  44. VOID
  45. );
  46. #else
  47. #define DPRINTF (void)
  48. #endif
  49. //
  50. // private types
  51. //
  52. typedef struct {
  53. #if defined(unix)
  54. LPSTR FunctionOrdinal;
  55. #else
  56. DWORD FunctionOrdinal;
  57. #endif /* unix */
  58. FARPROC * FunctionAddress;
  59. } SOCKETS_FUNCTION;
  60. //
  61. // global data
  62. //
  63. GLOBAL
  64. SOCKET
  65. (PASCAL FAR * _I_accept)(
  66. SOCKET s,
  67. struct sockaddr FAR *addr,
  68. int FAR *addrlen
  69. ) = NULL;
  70. GLOBAL
  71. int
  72. (PASCAL FAR * _I_bind)(
  73. SOCKET s,
  74. const struct sockaddr FAR *addr,
  75. int namelen
  76. ) = NULL;
  77. GLOBAL
  78. int
  79. (PASCAL FAR * _I_closesocket)(
  80. SOCKET s
  81. ) = NULL;
  82. GLOBAL
  83. int
  84. (PASCAL FAR * _I_connect)(
  85. SOCKET s,
  86. const struct sockaddr FAR *name,
  87. int namelen
  88. ) = NULL;
  89. GLOBAL
  90. int
  91. (PASCAL FAR * _I_gethostname)(
  92. char FAR * name,
  93. int namelen
  94. ) = NULL;
  95. GLOBAL
  96. LPHOSTENT
  97. (PASCAL FAR * _I_gethostbyname)(
  98. const char FAR * lpHostName
  99. ) = NULL;
  100. GLOBAL
  101. int
  102. (PASCAL FAR * _I_getsockname)(
  103. SOCKET s,
  104. struct sockaddr FAR *name,
  105. int FAR * namelen
  106. ) = NULL;
  107. GLOBAL
  108. int
  109. (PASCAL FAR * _I_getpeername)(
  110. SOCKET s,
  111. struct sockaddr FAR *name,
  112. int FAR * namelen
  113. ) = NULL;
  114. GLOBAL
  115. int
  116. (PASCAL FAR * _I_getsockopt)(
  117. SOCKET s,
  118. int level,
  119. int optname,
  120. char FAR * optval,
  121. int FAR *optlen
  122. );
  123. GLOBAL
  124. u_long
  125. (PASCAL FAR * _I_htonl)(
  126. u_long hostlong
  127. ) = NULL;
  128. GLOBAL
  129. u_short
  130. (PASCAL FAR * _I_htons)(
  131. u_short hostshort
  132. ) = NULL;
  133. GLOBAL
  134. unsigned long
  135. (PASCAL FAR * _I_inet_addr)(
  136. const char FAR * cp
  137. ) = NULL;
  138. GLOBAL
  139. char FAR *
  140. (PASCAL FAR * _I_inet_ntoa)(
  141. struct in_addr in
  142. ) = NULL;
  143. GLOBAL
  144. int
  145. (PASCAL FAR * _I_ioctlsocket)(
  146. SOCKET s,
  147. long cmd,
  148. u_long FAR *argp
  149. ) = NULL;
  150. GLOBAL
  151. int
  152. (PASCAL FAR * _I_listen)(
  153. SOCKET s,
  154. int backlog
  155. ) = NULL;
  156. GLOBAL
  157. u_short
  158. (PASCAL FAR * _I_ntohs)(
  159. u_short netshort
  160. ) = NULL;
  161. GLOBAL
  162. int
  163. (PASCAL FAR * _I_recv)(
  164. SOCKET s,
  165. char FAR * buf,
  166. int len,
  167. int flags
  168. ) = NULL;
  169. GLOBAL
  170. int
  171. (PASCAL FAR * _I_recvfrom)(
  172. SOCKET s,
  173. char FAR * buf,
  174. int len,
  175. int flags,
  176. struct sockaddr FAR *from,
  177. int FAR * fromlen
  178. ) = NULL;
  179. GLOBAL
  180. int
  181. (PASCAL FAR * _I_select)(
  182. int nfds,
  183. fd_set FAR *readfds,
  184. fd_set FAR *writefds,
  185. fd_set FAR *exceptfds,
  186. const struct timeval FAR *timeout
  187. ) = NULL;
  188. GLOBAL
  189. int
  190. (PASCAL FAR * _I_send)(
  191. SOCKET s,
  192. const char FAR * buf,
  193. int len,
  194. int flags
  195. ) = NULL;
  196. GLOBAL
  197. int
  198. (PASCAL FAR * _I_sendto)(
  199. SOCKET s,
  200. const char FAR * buf,
  201. int len,
  202. int flags,
  203. const struct sockaddr FAR *to,
  204. int tolen
  205. ) = NULL;
  206. GLOBAL
  207. int
  208. (PASCAL FAR * _I_setsockopt)(
  209. SOCKET s,
  210. int level,
  211. int optname,
  212. const char FAR * optval,
  213. int optlen
  214. ) = NULL;
  215. GLOBAL
  216. int
  217. (PASCAL FAR * _I_shutdown)(
  218. SOCKET s,
  219. int how
  220. ) = NULL;
  221. GLOBAL
  222. SOCKET
  223. (PASCAL FAR * _I_socket)(
  224. int af,
  225. int type,
  226. int protocol
  227. ) = NULL;
  228. GLOBAL
  229. int
  230. (PASCAL FAR * _I_WSAStartup)(
  231. WORD wVersionRequired,
  232. LPWSADATA lpWSAData
  233. ) = NULL;
  234. GLOBAL
  235. int
  236. (PASCAL FAR * _I_WSACleanup)(
  237. void
  238. ) = NULL;
  239. GLOBAL
  240. int
  241. (PASCAL FAR * _I_WSAGetLastError)(
  242. void
  243. ) = NULL;
  244. GLOBAL
  245. void
  246. (PASCAL FAR * _I_WSASetLastError)(
  247. int iError
  248. ) = NULL;
  249. GLOBAL
  250. int
  251. (PASCAL FAR * _I___WSAFDIsSet)(
  252. SOCKET,
  253. fd_set FAR *
  254. ) = NULL;
  255. GLOBAL
  256. int
  257. (PASCAL FAR * _I_getaddrinfo)(
  258. IN const char FAR * nodename,
  259. IN const char FAR * servname,
  260. IN const struct addrinfo FAR * hints,
  261. OUT struct addrinfo FAR * FAR * res
  262. ) = NULL;
  263. GLOBAL
  264. void
  265. (PASCAL FAR * _I_freeaddrinfo)(
  266. IN struct addrinfo *ai
  267. ) = NULL;
  268. GLOBAL
  269. int
  270. (PASCAL FAR * _I_getnameinfo)(
  271. IN const struct sockaddr FAR * sa,
  272. IN socklen_t salen,
  273. OUT char FAR * host,
  274. IN size_t hostlen,
  275. OUT char FAR * serv,
  276. IN size_t servlen,
  277. IN int flags
  278. ) = NULL;
  279. GLOBAL
  280. int
  281. (PASCAL FAR * _I_WSALookupServiceBeginW)(
  282. IN LPWSAQUERYSETW lpqsRestrictions,
  283. IN DWORD dwControlFlags,
  284. OUT LPHANDLE lphLookup
  285. ) = NULL;
  286. GLOBAL
  287. int
  288. (PASCAL FAR * _I_WSALookupServiceNextW)(
  289. IN HANDLE hLookup,
  290. IN DWORD dwControlFlags,
  291. IN OUT LPDWORD lpdwBufferLength,
  292. OUT LPWSAQUERYSETW lpqsResults
  293. ) = NULL;
  294. GLOBAL
  295. int
  296. (PASCAL FAR * _I_WSALookupServiceEnd)(
  297. IN HANDLE hLookup
  298. ) = NULL;
  299. GLOBAL
  300. int
  301. (PASCAL FAR * _I_WSANSPIoctl)(
  302. IN HANDLE hLookup,
  303. IN DWORD dwControlCode,
  304. IN LPVOID lpvInBuffer,
  305. IN DWORD cbInBuffer,
  306. OUT LPVOID lpvOutBuffer,
  307. IN DWORD cbOutBuffer,
  308. OUT LPDWORD lpcbBytesReturned,
  309. IN LPWSACOMPLETION lpCompletion
  310. ) = NULL;
  311. #if INET_DEBUG
  312. void SetupSocketsTracing(void);
  313. #endif
  314. //
  315. // private data
  316. //
  317. //
  318. // InitializationLock - protects against multiple threads loading WSOCK32.DLL
  319. // and entry points
  320. //
  321. PRIVATE CRITICAL_SECTION InitializationLock = {0};
  322. //
  323. // hWinsock - NULL when WSOCK32.DLL is not loaded
  324. // hWs2_32 - NULL when WS2_32.DLL is not loaded.
  325. // hAddrResLib - NULL when WS2_32.DLL/WSHIPV6.DLL is not loaded
  326. // If WS2_32.DLL is loaded in the process and it has IPv6 entry points,
  327. // hAddrResLib==hWs2_32, otherwise it is handle to WSHIPV6.DLL if
  328. // the latter is present and usable (IPv6 is present).
  329. //
  330. PRIVATE HINSTANCE hWinsock = NULL;
  331. PRIVATE HINSTANCE hWs2_32 = NULL;
  332. PRIVATE HINSTANCE hAddrResLib = NULL;
  333. //
  334. // WinsockLoadCount - the number of times we have made calls to LoadWinsock()
  335. // and UnloadWinsock(). When this reaches 0 (again), we can unload the Winsock
  336. // DLL for real
  337. //
  338. PRIVATE DWORD WinsockLoadCount = 0;
  339. //
  340. // SocketsFunctions - this is the list of entry points in WSOCK32.DLL that we
  341. // need to load for WININET.DLL
  342. //
  343. #if !defined(unix)
  344. PRIVATE
  345. SOCKETS_FUNCTION
  346. SocketsFunctions[] = {
  347. 1, (FARPROC*)&_I_accept,
  348. 2, (FARPROC*)&_I_bind,
  349. 3, (FARPROC*)&_I_closesocket,
  350. 4, (FARPROC*)&_I_connect,
  351. 5, (FARPROC*)&_I_getpeername,
  352. 6, (FARPROC*)&_I_getsockname,
  353. 7, (FARPROC*)&_I_getsockopt,
  354. 8, (FARPROC*)&_I_htonl,
  355. 9, (FARPROC*)&_I_htons,
  356. 10, (FARPROC*)&_I_inet_addr,
  357. 11, (FARPROC*)&_I_inet_ntoa,
  358. 12, (FARPROC*)&_I_ioctlsocket,
  359. 13, (FARPROC*)&_I_listen,
  360. 15, (FARPROC*)&_I_ntohs,
  361. 16, (FARPROC*)&_I_recv,
  362. 17, (FARPROC*)&_I_recvfrom,
  363. 18, (FARPROC*)&_I_select,
  364. 19, (FARPROC*)&_I_send,
  365. 20, (FARPROC*)&_I_sendto,
  366. 21, (FARPROC*)&_I_setsockopt,
  367. 22, (FARPROC*)&_I_shutdown,
  368. 23, (FARPROC*)&_I_socket,
  369. 52, (FARPROC*)&_I_gethostbyname,
  370. 57, (FARPROC*)&_I_gethostname,
  371. 111, (FARPROC*)&_I_WSAGetLastError,
  372. 112, (FARPROC*)&_I_WSASetLastError,
  373. 115, (FARPROC*)&_I_WSAStartup,
  374. 116, (FARPROC*)&_I_WSACleanup,
  375. 151, (FARPROC*)&_I___WSAFDIsSet
  376. };
  377. #else
  378. PRIVATE
  379. SOCKETS_FUNCTION
  380. SocketsFunctions[] = {
  381. "MwAccept", (FARPROC*)&_I_accept,
  382. "MwBind", (FARPROC*)&_I_bind,
  383. "closesocket", (FARPROC*)&_I_closesocket,
  384. "MwConnect", (FARPROC*)&_I_connect,
  385. "MwGetpeername", (FARPROC*)&_I_getpeername,
  386. "MwGetsockname", (FARPROC*)&_I_getsockname,
  387. "MwGetsockopt", (FARPROC*)&_I_getsockopt,
  388. "MwHtonl", (FARPROC*)&_I_htonl,
  389. "MwHtons", (FARPROC*)&_I_htons,
  390. "MwInet_addr", (FARPROC*)&_I_inet_addr,
  391. "MwInet_ntoa", (FARPROC*)&_I_inet_ntoa,
  392. "ioctlsocket", (FARPROC*)&_I_ioctlsocket,
  393. "MwListen", (FARPROC*)&_I_listen,
  394. "MwNtohs", (FARPROC*)&_I_ntohs,
  395. "MwRecv", (FARPROC*)&_I_recv,
  396. "MwRecvfrom", (FARPROC*)&_I_recvfrom,
  397. "MwSelect", (FARPROC*)&_I_select,
  398. "MwSend", (FARPROC*)&_I_send,
  399. "MwSendto", (FARPROC*)&_I_sendto,
  400. "MwSetsockopt", (FARPROC*)&_I_setsockopt,
  401. "MwShutdown", (FARPROC*)&_I_shutdown,
  402. "MwSocket", (FARPROC*)&_I_socket,
  403. "MwGethostbyname", (FARPROC*)&_I_gethostbyname,
  404. "MwGethostname", (FARPROC*)&_I_gethostname,
  405. "WSAGetLastError", (FARPROC*)&_I_WSAGetLastError,
  406. "WSASetLastError", (FARPROC*)&_I_WSASetLastError,
  407. "WSAStartup", (FARPROC*)&_I_WSAStartup,
  408. "WSACleanup", (FARPROC*)&_I_WSACleanup,
  409. #if 0
  410. "", (FARPROC*)&_I___WSAFDIsSet
  411. #endif
  412. };
  413. #endif /* unix */
  414. //
  415. // private prototypes
  416. //
  417. #if INET_DEBUG
  418. void SetupSocketsTracing(void);
  419. #endif
  420. int
  421. PASCAL FAR
  422. LimitedGetAddrInfo(
  423. IN const char FAR * nodename,
  424. IN const char FAR * servname,
  425. IN const struct addrinfo FAR * hints,
  426. OUT struct addrinfo FAR * FAR * res
  427. );
  428. void
  429. PASCAL FAR
  430. LimitedFreeAddrInfo(
  431. IN struct addrinfo *ai
  432. );
  433. int
  434. PASCAL FAR
  435. LimitedGetNameInfo(
  436. IN const struct sockaddr FAR * sa,
  437. IN socklen_t salen,
  438. OUT char FAR * host,
  439. IN size_t hostlen,
  440. OUT char FAR * serv,
  441. IN size_t servlen,
  442. IN int flags
  443. );
  444. //
  445. // functions
  446. //
  447. VOID
  448. IwinsockInitialize(
  449. VOID
  450. )
  451. /*++
  452. Routine Description:
  453. Performs initialization/resource allocation for this module
  454. Arguments:
  455. None.
  456. Return Value:
  457. None.
  458. --*/
  459. {
  460. //
  461. // initialize the critical section that protects against multiple threads
  462. // trying to initialize Winsock
  463. //
  464. InitializeCriticalSection(&InitializationLock);
  465. #if INET_DEBUG
  466. InitDebugSock();
  467. #endif
  468. }
  469. VOID
  470. IwinsockTerminate(
  471. VOID
  472. )
  473. /*++
  474. Routine Description:
  475. Performs termination & resource cleanup for this module
  476. Arguments:
  477. None.
  478. Return Value:
  479. None.
  480. --*/
  481. {
  482. DeleteCriticalSection(&InitializationLock);
  483. #if INET_DEBUG
  484. TerminateDebugSock();
  485. #endif
  486. }
  487. DWORD
  488. LoadWinsock(
  489. VOID
  490. )
  491. /*++
  492. Routine Description:
  493. Dynamically loads Windows sockets library
  494. Arguments:
  495. None.
  496. Return Value:
  497. DWORD
  498. Success - ERROR_SUCCESS
  499. Failure - Win32 error
  500. e.g. LoadLibrary() failure
  501. WSA error
  502. e.g. WSAStartup() failure
  503. --*/
  504. {
  505. DEBUG_ENTER((DBG_SOCKETS,
  506. Dword,
  507. "LoadWinsock",
  508. NULL
  509. ));
  510. DWORD error = ERROR_SUCCESS;
  511. //
  512. // ensure no 2 threads are trying to modify the loaded state of winsock at
  513. // the same time
  514. //
  515. EnterCriticalSection(&InitializationLock);
  516. if (hWinsock == NULL) {
  517. BOOL failed = FALSE;
  518. DPRINTF("Attempting to load winsock\n");
  519. //
  520. // Even though we attempt to load WinSock 2 (ws2_32.dll) below,
  521. // we still load WinSock 1 (wsock32.dll) here because some of the
  522. // supposedly identical ordinal numbers were changed between
  523. // versions, thus breaking pure binary compatibility.
  524. //
  525. hWinsock = LoadLibrary("wsock32");
  526. if (hWinsock != NULL) {
  527. //
  528. // Load function entry points from the WinSock library.
  529. //
  530. FARPROC farProc;
  531. for (int i = 0; i < ARRAY_ELEMENTS(SocketsFunctions); ++i) {
  532. farProc = GetProcAddress(
  533. hWinsock,
  534. (LPCSTR)(DWORD_PTR)SocketsFunctions[i].FunctionOrdinal
  535. );
  536. if (farProc == NULL) {
  537. failed = TRUE;
  538. DPRINTF("Can't find entry %d in function array\n", i);
  539. break;
  540. }
  541. *SocketsFunctions[i].FunctionAddress = farProc;
  542. }
  543. if (!failed) {
  544. //
  545. // although we need a WSADATA for WSAStartup(), it is an
  546. // expendible structure (not required for any other sockets
  547. // calls)
  548. //
  549. WSADATA wsaData;
  550. error = _I_WSAStartup(0x0101, &wsaData);
  551. if (error == ERROR_SUCCESS) {
  552. DEBUG_PRINT(SOCKETS,
  553. INFO,
  554. ("winsock description: %q\n",
  555. wsaData.szDescription
  556. ));
  557. int stringLen;
  558. stringLen = lstrlen(wsaData.szDescription);
  559. if (strnistr(wsaData.szDescription, "novell", stringLen)
  560. && strnistr(wsaData.szDescription, "wsock32", stringLen)) {
  561. DEBUG_PRINT(SOCKETS,
  562. INFO,
  563. ("running on Novell Client32 stack\n"
  564. ));
  565. GlobalRunningNovellClient32 = TRUE;
  566. }
  567. #if INET_DEBUG
  568. SetupSocketsTracing();
  569. #endif
  570. //
  571. // We may need to load ws2_32 for several purposes.
  572. // If the functionality is actually not available,
  573. // we do not want to keep around unnecessarily.
  574. // This refcount will help us decide.
  575. //
  576. INT ws2_32RefCount = 0;
  577. //
  578. // Attempt load ws2_32.dll.
  579. //
  580. DPRINTF("Checking for presence of ws2_32\n");
  581. hWs2_32 = LoadLibrary ("ws2_32");
  582. if (hWs2_32!=NULL) {
  583. //
  584. // Try to locate name resolution API
  585. // necessary to access Network Location Awareness
  586. // service (available on Whistler).
  587. //
  588. if (GlobalPlatformWhistler) {
  589. farProc = GetProcAddress (hWs2_32,
  590. "WSALookupServiceBeginW");
  591. if (farProc!=NULL) {
  592. *(FARPROC *)&_I_WSALookupServiceBeginW = farProc;
  593. farProc = GetProcAddress (hWs2_32,
  594. "WSALookupServiceEnd");
  595. if (farProc!=NULL) {
  596. *(FARPROC *)&_I_WSALookupServiceEnd = farProc;
  597. farProc = GetProcAddress (hWs2_32,
  598. "WSALookupServiceNextW");
  599. if (farProc!=NULL) {
  600. *(FARPROC *)&_I_WSALookupServiceNextW = farProc;
  601. farProc = GetProcAddress (hWs2_32,
  602. "WSANSPIoctl");
  603. if (farProc!=NULL) {
  604. *(FARPROC *)&_I_WSANSPIoctl = farProc;
  605. }
  606. }
  607. }
  608. }
  609. if (farProc!=NULL) {
  610. //
  611. // Increment ws2_32 ref count for
  612. // the purpose of NLA
  613. //
  614. ws2_32RefCount += 1;
  615. }
  616. else {
  617. _I_WSALookupServiceBeginW = NULL;
  618. _I_WSALookupServiceEnd = NULL;
  619. _I_WSALookupServiceNextW = NULL;
  620. _I_WSANSPIoctl = NULL;
  621. }
  622. }
  623. //
  624. // Try to locate the address family independent name
  625. // resolution routines (i.e. getaddrinfo, getnameinfo).
  626. // In Whistler and beyond, these will be present in
  627. // the WinSock 2 library (ws2_32.dll).
  628. //
  629. // Restricting to Whistler only.
  630. if (GlobalPlatformWhistler)
  631. {
  632. DPRINTF("Looking in ws2_32 for getaddrinfo\n");
  633. farProc = GetProcAddress(hWs2_32, "getaddrinfo");
  634. if (farProc != NULL) {
  635. //
  636. // Increment ws2_32 ref count for
  637. // the purpose of IPv6 address resolution.
  638. //
  639. ws2_32RefCount += 1;
  640. hAddrResLib = hWs2_32;
  641. }
  642. }
  643. }
  644. // Restricting to Whistler only.
  645. if ((hAddrResLib == NULL)
  646. && GlobalPlatformWhistler)
  647. {
  648. //
  649. // In the IPv6 Technology Preview, the address family
  650. // independent name resolution calls are snuck in via
  651. // the IPv6 WinSock helper library (wship6.dll).
  652. // So look there next.
  653. //
  654. DPRINTF("Looking in wship6 for getaddrinfo\n");
  655. hAddrResLib = LoadLibrary("wship6");
  656. if (hAddrResLib != NULL) {
  657. farProc = GetProcAddress(hAddrResLib,
  658. "getaddrinfo");
  659. if (farProc == NULL) {
  660. FreeLibrary(hAddrResLib);
  661. hAddrResLib = NULL;
  662. } else {
  663. //
  664. // The Tech Preview version of the address
  665. // family independent APIs doesn't check that
  666. // an IPv6 stack is present before returning
  667. // IPv6 addresses. So we need to check for it.
  668. //
  669. SOCKET Test;
  670. struct sockaddr_in6 TestSA;
  671. DPRINTF("Checking for active IPv6 stack\n");
  672. error = SOCKET_ERROR;
  673. Test = _I_socket(PF_INET6, 0, 0);
  674. if (Test != INVALID_SOCKET) {
  675. memset(&TestSA, 0, sizeof(TestSA));
  676. TestSA.sin6_family = AF_INET6;
  677. TestSA.sin6_addr.s6_addr[15] = 1;
  678. error = _I_bind(Test, (LPSOCKADDR)&TestSA,
  679. sizeof(TestSA));
  680. _I_closesocket(Test);
  681. }
  682. if (error != 0) {
  683. DPRINTF("IPv6 stack is not active\n");
  684. FreeLibrary(hAddrResLib);
  685. hAddrResLib = NULL;
  686. error = 0;
  687. }
  688. }
  689. }
  690. }
  691. if (hAddrResLib != NULL) {
  692. //
  693. // Use routines from this library. Since getaddrinfo
  694. // is here, we expect the others to be also, but will
  695. // fall back to IPv4-only if any of them is missing.
  696. //
  697. *(FARPROC *)&_I_getaddrinfo = farProc;
  698. farProc = GetProcAddress(hAddrResLib, "freeaddrinfo");
  699. if (farProc != NULL) {
  700. *(FARPROC *)&_I_freeaddrinfo = farProc;
  701. farProc = GetProcAddress(hAddrResLib,
  702. "getnameinfo");
  703. if (farProc != NULL)
  704. *(FARPROC *)&_I_getnameinfo = farProc;
  705. }
  706. if (farProc == NULL) {
  707. if (hAddrResLib!=hWs2_32) {
  708. FreeLibrary(hAddrResLib);
  709. }
  710. else {
  711. ws2_32RefCount -= 1;
  712. }
  713. hAddrResLib = NULL;
  714. }
  715. }
  716. if (hAddrResLib == NULL) {
  717. //
  718. // If we can't find getaddrinfo lying around on the
  719. // system somewhere, assume we're still in the
  720. // IPv4-only dark ages.
  721. //
  722. DPRINTF("Using IPv4-only name res functions\n");
  723. _I_getaddrinfo = LimitedGetAddrInfo;
  724. _I_freeaddrinfo = LimitedFreeAddrInfo;
  725. _I_getnameinfo = LimitedGetNameInfo;
  726. }
  727. //
  728. // Check if we actually used ws2_32 for anything
  729. // and unload it if not.
  730. //
  731. if (ws2_32RefCount==0 && hWs2_32!=NULL) {
  732. FreeLibrary (hWs2_32);
  733. hWs2_32 = NULL;
  734. }
  735. } else {
  736. DPRINTF("Winsock failed to start\n");
  737. failed = TRUE;
  738. }
  739. }
  740. } else {
  741. DPRINTF("Couldn't load the winsock library\n");
  742. failed = TRUE;
  743. }
  744. //
  745. // if we failed to find an entry point or WSAStartup() returned an error
  746. // then unload the library
  747. //
  748. if (failed) {
  749. //
  750. // important: there should be no API calls between determining the
  751. // failure and coming here to get the error code
  752. //
  753. // if error == ERROR_SUCCESS then we have to get the last error, else
  754. // it is the error returned by WSAStartup()
  755. //
  756. if (error == ERROR_SUCCESS) {
  757. error = GetLastError();
  758. INET_ASSERT(error != ERROR_SUCCESS);
  759. }
  760. DPRINTF("Unloading winsock due to error 0x%x\n", error);
  761. UnloadWinsock();
  762. }
  763. } else {
  764. //
  765. // just increment the number of times we have called LoadWinsock()
  766. // without a corresponding call to UnloadWinsock();
  767. //
  768. ++WinsockLoadCount;
  769. }
  770. LeaveCriticalSection(&InitializationLock);
  771. //
  772. // if we failed for any reason, need to report that TCP/IP not available
  773. //
  774. if (error != ERROR_SUCCESS) {
  775. error = ERROR_INTERNET_TCPIP_NOT_INSTALLED;
  776. }
  777. DEBUG_LEAVE(error);
  778. return error;
  779. }
  780. VOID
  781. UnloadWinsock(
  782. VOID
  783. )
  784. /*++
  785. Routine Description:
  786. Unloads winsock DLL and prepares hWinsock and SocketsFunctions[] for reload
  787. Arguments:
  788. None.
  789. Return Value:
  790. None.
  791. --*/
  792. {
  793. DEBUG_ENTER((DBG_SOCKETS,
  794. None,
  795. "UnloadWinsock",
  796. NULL
  797. ));
  798. //
  799. // ensure no 2 threads are trying to modify the loaded state of winsock at
  800. // the same time
  801. //
  802. EnterCriticalSection(&InitializationLock);
  803. //
  804. // only unload the DLL if it has been mapped into process memory
  805. //
  806. if (hWinsock != NULL) {
  807. //
  808. // and only if this is the last load instance
  809. //
  810. if (WinsockLoadCount == 0) {
  811. INET_ASSERT(_I_WSACleanup != NULL);
  812. if (_I_WSACleanup != NULL) {
  813. //
  814. // need to terminate async support too - it is reliant on
  815. // Winsock
  816. //
  817. TerminateAsyncSupport();
  818. int serr = _I_WSACleanup();
  819. if (serr != 0) {
  820. DEBUG_PRINT(SOCKETS,
  821. ERROR,
  822. ("WSACleanup() returns %d; WSA error = %d\n",
  823. serr,
  824. (_I_WSAGetLastError != NULL)
  825. ? _I_WSAGetLastError()
  826. : -1
  827. ));
  828. }
  829. }
  830. if (hAddrResLib != NULL) {
  831. *(FARPROC *)&_I_getaddrinfo = (FARPROC)NULL;
  832. *(FARPROC *)&_I_freeaddrinfo = (FARPROC)NULL;
  833. *(FARPROC *)&_I_getnameinfo = (FARPROC)NULL;
  834. if (hAddrResLib!=hWs2_32) {
  835. FreeLibrary(hAddrResLib);
  836. }
  837. hAddrResLib = NULL;
  838. }
  839. if (hWs2_32!=NULL) {
  840. *(FARPROC *)&_I_WSALookupServiceBeginW = (FARPROC)NULL;
  841. *(FARPROC *)&_I_WSALookupServiceEnd = (FARPROC)NULL;
  842. *(FARPROC *)&_I_WSALookupServiceNextW = (FARPROC)NULL;
  843. *(FARPROC *)&_I_WSANSPIoctl = (FARPROC)NULL;
  844. FreeLibrary (hWs2_32);
  845. hWs2_32 = NULL;
  846. }
  847. for (int i = 0; i < ARRAY_ELEMENTS(SocketsFunctions); ++i) {
  848. *SocketsFunctions[i].FunctionAddress = (FARPROC)NULL;
  849. }
  850. FreeLibrary(hWinsock);
  851. hWinsock = NULL;
  852. } else {
  853. //
  854. // if there have been multiple virtual loads, then just reduce the
  855. // load count
  856. //
  857. --WinsockLoadCount;
  858. }
  859. }
  860. LeaveCriticalSection(&InitializationLock);
  861. DEBUG_LEAVE(0);
  862. }
  863. //
  864. // Following is v4-only version of getaddrinfo and friends.
  865. //
  866. // Note that we use LocalAlloc/LocalFree instead of malloc/free
  867. // to avoid introducing a dependency on msvcrt.dll.
  868. //
  869. //* LimitedFreeAddrInfo - Free an addrinfo structure (or chain of structures).
  870. //
  871. // As specified in RFC 2553, Section 6.4.
  872. //
  873. void WSAAPI
  874. LimitedFreeAddrInfo(
  875. struct addrinfo *Free) // Structure (chain) to free.
  876. {
  877. struct addrinfo *Next;
  878. for (Next = Free; Next != NULL; Free = Next) {
  879. if (Free->ai_canonname != NULL)
  880. LocalFree(Free->ai_canonname);
  881. if (Free->ai_addr != NULL)
  882. LocalFree(Free->ai_addr);
  883. Next = Free->ai_next;
  884. LocalFree(Free);
  885. }
  886. }
  887. //* NewAddrInfo - Allocate an addrinfo structure and populate some fields.
  888. //
  889. // Internal function, not exported. Expects to be called with valid
  890. // arguments, does no checking.
  891. //
  892. // Returns a partially filled-in addrinfo struct, or NULL if out of memory.
  893. //
  894. static struct addrinfo *
  895. NewAddrInfo(
  896. int SocketType, // SOCK_*. Can be wildcarded (zero).
  897. int Protocol, // IPPROTO_*. Can be wildcarded (zero).
  898. struct addrinfo ***Prev) // In/out param for accessing previous ai_next.
  899. {
  900. struct addrinfo *New;
  901. //
  902. // Allocate a new addrinfo structure.
  903. //
  904. New = (struct addrinfo *)LocalAlloc(0, sizeof(struct addrinfo));
  905. if (New == NULL)
  906. return NULL;
  907. //
  908. // Fill in the easy stuff.
  909. //
  910. New->ai_flags = 0;
  911. New->ai_family = PF_INET;
  912. New->ai_socktype = SocketType;
  913. New->ai_protocol = Protocol;
  914. New->ai_addrlen = sizeof(struct sockaddr_in);
  915. New->ai_canonname = NULL;
  916. New->ai_addr = (LPSOCKADDR)LocalAlloc(0, New->ai_addrlen);
  917. if (New->ai_addr == NULL) {
  918. LocalFree(New);
  919. return NULL;
  920. }
  921. New->ai_next = NULL;
  922. //
  923. // Link this one onto the end of the chain.
  924. //
  925. **Prev = New;
  926. *Prev = &New->ai_next;
  927. return New;
  928. }
  929. //* LookupNode - Resolve a nodename and add any addresses found to the list.
  930. //
  931. // Internal function, not exported. Expects to be called with valid
  932. // arguments, does no checking.
  933. //
  934. // Returns 0 on success, an EAI_* style error value otherwise.
  935. //
  936. static int
  937. LookupNode(
  938. const char *NodeName, // Name of node to resolve.
  939. int SocketType, // SOCK_*. Can be wildcarded (zero).
  940. int Protocol, // IPPROTO_*. Can be wildcarded (zero).
  941. int Flags, // Flags.
  942. struct addrinfo ***Prev) // In/out param for accessing previous ai_next.
  943. {
  944. struct addrinfo *CurrentInfo;
  945. struct sockaddr_in *sin;
  946. struct hostent *hA;
  947. char **addrs;
  948. int Error = 0;
  949. hA = _I_gethostbyname(NodeName);
  950. if (hA != NULL) {
  951. if ((hA->h_addrtype == AF_INET) &&
  952. (hA->h_length == sizeof(struct in_addr))) {
  953. //
  954. // Loop through all the addresses returned by gethostbyname,
  955. // allocating an addrinfo structure and filling in the address
  956. // field for each.
  957. //
  958. for (addrs = hA->h_addr_list; *addrs != NULL; addrs++) {
  959. CurrentInfo = NewAddrInfo(SocketType, Protocol, Prev);
  960. if (CurrentInfo == NULL) {
  961. Error = EAI_MEMORY;
  962. break;
  963. }
  964. //
  965. // We fill in the ai_canonname field in the first addrinfo
  966. // structure that we return if we've been asked to do so.
  967. //
  968. if (Flags & AI_CANONNAME) {
  969. if (hA->h_name != NULL) {
  970. int NameLength;
  971. NameLength = strlen(hA->h_name) + 1;
  972. CurrentInfo->ai_canonname = (char *)LocalAlloc(0, NameLength);
  973. if (CurrentInfo->ai_canonname == NULL) {
  974. Error = EAI_MEMORY;
  975. break;
  976. }
  977. memcpy(CurrentInfo->ai_canonname, hA->h_name, NameLength);
  978. }
  979. // Turn off flag so we only do this once.
  980. Flags &= ~AI_CANONNAME;
  981. }
  982. //
  983. // We're returning IPv4 addresses.
  984. //
  985. sin = (struct sockaddr_in *)CurrentInfo->ai_addr;
  986. sin->sin_family = AF_INET;
  987. sin->sin_port = 0;
  988. memcpy(&sin->sin_addr, (struct in_addr *)*addrs, sizeof sin->sin_addr);
  989. memset(sin->sin_zero, 0, sizeof sin->sin_zero);
  990. }
  991. }
  992. } else {
  993. Error = _I_WSAGetLastError();
  994. if (Error == WSANO_DATA) {
  995. Error = EAI_NODATA;
  996. } else if (Error == WSAHOST_NOT_FOUND) {
  997. Error = EAI_NONAME;
  998. } else {
  999. Error = EAI_FAIL;
  1000. }
  1001. }
  1002. return Error;
  1003. }
  1004. //* ParseV4Address
  1005. //
  1006. // Helper function for parsing a literal v4 address, because
  1007. // WSAStringToAddress is too liberal in what it accepts.
  1008. // Returns FALSE if there is an error, TRUE for success.
  1009. //
  1010. // The syntax is a.b.c.d, where each number is between 0 - 255.
  1011. //
  1012. static int
  1013. ParseV4Address(const char *String, struct in_addr *Addr)
  1014. {
  1015. u_int Number;
  1016. int NumChars;
  1017. char Char;
  1018. int i;
  1019. for (i = 0; i < 4; i++) {
  1020. Number = 0;
  1021. NumChars = 0;
  1022. for (;;) {
  1023. Char = *String++;
  1024. if (Char == '\0') {
  1025. if ((NumChars > 0) && (i == 3))
  1026. break;
  1027. else
  1028. return FALSE;
  1029. }
  1030. else if (Char == '.') {
  1031. if ((NumChars > 0) && (i < 3))
  1032. break;
  1033. else
  1034. return FALSE;
  1035. }
  1036. else if (('0' <= Char) && (Char <= '9')) {
  1037. if ((NumChars != 0) && (Number == 0))
  1038. return FALSE;
  1039. else if (++NumChars <= 3)
  1040. Number = 10 * Number + (Char - '0');
  1041. else
  1042. return FALSE;
  1043. } else
  1044. return FALSE;
  1045. }
  1046. if (Number > 255)
  1047. return FALSE;
  1048. ((u_char *)Addr)[i] = (u_char)Number;
  1049. }
  1050. return TRUE;
  1051. }
  1052. //* LimitedGetAddrInfo - Protocol-independent name-to-address translation.
  1053. //
  1054. // As specified in RFC 2553, Section 6.4.
  1055. //
  1056. // This is the hacked version that only supports IPv4.
  1057. //
  1058. // Returns zero if successful, an EAI_* error code if not.
  1059. //
  1060. int WSAAPI
  1061. LimitedGetAddrInfo(
  1062. const char *NodeName, // Node name to lookup.
  1063. const char *ServiceName, // Service name to lookup.
  1064. const struct addrinfo *Hints, // Hints about how to process request.
  1065. struct addrinfo **Result) // Where to return result.
  1066. {
  1067. struct addrinfo *CurrentInfo, **Next;
  1068. int ProtocolId = 0;
  1069. u_short ProtocolFamily = PF_UNSPEC;
  1070. int SocketType = 0;
  1071. int Flags = 0;
  1072. int Error;
  1073. struct sockaddr_in *sin;
  1074. struct in_addr TempAddr;
  1075. //
  1076. // This special cut-down version for wininet doesn't do service lookup.
  1077. // So the request must be for nodename lookup.
  1078. //
  1079. INET_ASSERT(ServiceName == NULL);
  1080. INET_ASSERT(NodeName != NULL);
  1081. //
  1082. // In case we have to bail early, make it clear to our caller
  1083. // that we haven't allocated an addrinfo structure.
  1084. //
  1085. *Result = NULL;
  1086. Next = Result;
  1087. //
  1088. // Validate hints argument.
  1089. //
  1090. if (Hints != NULL) {
  1091. //
  1092. // Wininet can be trusted to call us correctly.
  1093. //
  1094. INET_ASSERT((Hints->ai_addrlen == 0) &&
  1095. (Hints->ai_canonname == NULL) &&
  1096. (Hints->ai_addr == NULL) &&
  1097. (Hints->ai_next == NULL));
  1098. Flags = Hints->ai_flags;
  1099. INET_ASSERT(!((Flags & AI_CANONNAME) && (Flags & AI_NUMERICHOST)));
  1100. ProtocolFamily = (u_short)Hints->ai_family;
  1101. INET_ASSERT((ProtocolFamily == PF_UNSPEC) ||
  1102. (ProtocolFamily == PF_INET));
  1103. SocketType = Hints->ai_socktype;
  1104. INET_ASSERT((SocketType == 0) ||
  1105. (SocketType == SOCK_STREAM) ||
  1106. (SocketType == SOCK_DGRAM));
  1107. ProtocolId = Hints->ai_protocol;
  1108. }
  1109. //
  1110. // We have a node name (either alpha or numeric) we need to look up.
  1111. //
  1112. //
  1113. // First, see if this is a numeric string address that we can
  1114. // just convert to a binary address.
  1115. //
  1116. if (ParseV4Address(NodeName, &TempAddr)) {
  1117. //
  1118. // Conversion from IPv4 numeric string to binary address
  1119. // was sucessfull. Create an addrinfo structure to hold it,
  1120. // and return it to the user.
  1121. //
  1122. CurrentInfo = NewAddrInfo(SocketType, ProtocolId, &Next);
  1123. if (CurrentInfo == NULL) {
  1124. Error = EAI_MEMORY;
  1125. goto Bail;
  1126. }
  1127. sin = (struct sockaddr_in *)CurrentInfo->ai_addr;
  1128. sin->sin_family = AF_INET;
  1129. sin->sin_port = 0;
  1130. sin->sin_addr = TempAddr;
  1131. memset(sin->sin_zero, 0, sizeof sin->sin_zero);
  1132. return 0; // Success!
  1133. }
  1134. //
  1135. // It's not a numeric string address. If our caller only wants us
  1136. // to convert numeric addresses, give up now.
  1137. //
  1138. if (Flags & AI_NUMERICHOST) {
  1139. Error = EAI_NONAME;
  1140. goto Bail;
  1141. }
  1142. //
  1143. // Since it's non-numeric, we have to do a regular node name lookup.
  1144. //
  1145. Error = LookupNode(NodeName, SocketType, ProtocolId, Flags, &Next);
  1146. if (Error != 0)
  1147. goto Bail;
  1148. return 0; // Success!
  1149. Bail:
  1150. if (*Result != NULL) {
  1151. LimitedFreeAddrInfo(*Result);
  1152. *Result = NULL;
  1153. }
  1154. return Error;
  1155. }
  1156. //* LimitedGetNameInfo - Protocol-independent address-to-name translation.
  1157. //
  1158. // As specified in RFC 2553, Section 6.5.
  1159. //
  1160. // This is a special version for wininet that only supports IPv4.
  1161. // All extraneous checks have been removed, only the specific calls
  1162. // that wininet makes are supported.
  1163. //
  1164. // Note that unless the IE team decides to attempt the FTP EPRT command
  1165. // for IPv4 as well as IPv6 (see comments in ftp\protocol.cxx), this
  1166. // routine will never be called.
  1167. //
  1168. int WSAAPI
  1169. LimitedGetNameInfo(
  1170. const struct sockaddr *SocketAddress, // Socket address to translate.
  1171. socklen_t SocketAddressLength, // Length of above socket address.
  1172. char *NodeName, // Where to return the node name.
  1173. size_t NodeBufferSize, // Size of above buffer.
  1174. char *ServiceName, // Where to return the service name.
  1175. size_t ServiceBufferSize, // Size of above buffer.
  1176. int Flags) // Flags of type NI_*.
  1177. {
  1178. //
  1179. // Wininet doesn't do service lookup.
  1180. //
  1181. INET_ASSERT((ServiceName == NULL) && (ServiceBufferSize == 0));
  1182. //
  1183. // Wininet can be trusted to call us correctly.
  1184. //
  1185. INET_ASSERT((NodeName != NULL) && (SocketAddress != NULL) &&
  1186. (SocketAddressLength == sizeof(struct sockaddr_in)));
  1187. //
  1188. // This version is IPv4 only.
  1189. //
  1190. INET_ASSERT(SocketAddress->sa_family == AF_INET);
  1191. //
  1192. // Wininet will only call this routine to translate the given address
  1193. // to an IPv4 address literal.
  1194. //
  1195. INET_ASSERT(Flags & NI_NUMERICHOST);
  1196. INET_ASSERT(NodeBufferSize >= sizeof("255.255.255.255"));
  1197. strcpy(NodeName, _I_inet_ntoa(((struct sockaddr_in *)SocketAddress)->sin_addr));
  1198. return 0;
  1199. }
  1200. DWORD
  1201. SafeCloseSocket(
  1202. IN SOCKET Socket
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. closesocket() call protected by exception handler in case winsock DLL has
  1207. been unloaded by system before Wininet DLL unloaded
  1208. Arguments:
  1209. Socket - socket handle to close
  1210. Return Value:
  1211. DWORD
  1212. Success - ERROR_SUCCESS
  1213. Failure - socket error mapped to ERROR_INTERNET_ error
  1214. --*/
  1215. {
  1216. int serr;
  1217. __try {
  1218. serr = _I_closesocket(Socket);
  1219. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1220. serr = 0;
  1221. }
  1222. ENDEXCEPT
  1223. return (serr == SOCKET_ERROR)
  1224. ? MapInternetError(_I_WSAGetLastError())
  1225. : ERROR_SUCCESS;
  1226. }
  1227. #if INET_DEBUG
  1228. //
  1229. // debug data types
  1230. //
  1231. SOCKET
  1232. PASCAL FAR
  1233. _II_socket(
  1234. int af,
  1235. int type,
  1236. int protocol
  1237. );
  1238. int
  1239. PASCAL FAR
  1240. _II_closesocket(
  1241. SOCKET s
  1242. );
  1243. SOCKET
  1244. PASCAL FAR
  1245. _II_accept(
  1246. SOCKET s,
  1247. struct sockaddr FAR *addr,
  1248. int FAR *addrlen
  1249. );
  1250. GLOBAL
  1251. SOCKET
  1252. (PASCAL FAR * _P_accept)(
  1253. SOCKET s,
  1254. struct sockaddr FAR *addr,
  1255. int FAR *addrlen
  1256. ) = NULL;
  1257. GLOBAL
  1258. int
  1259. (PASCAL FAR * _P_closesocket)(
  1260. SOCKET s
  1261. ) = NULL;
  1262. GLOBAL
  1263. SOCKET
  1264. (PASCAL FAR * _P_socket)(
  1265. int af,
  1266. int type,
  1267. int protocol
  1268. ) = NULL;
  1269. #define MAX_STACK_TRACE 5
  1270. #define MAX_SOCK_ENTRIES 1000
  1271. typedef struct _DEBUG_SOCK_ENTRY {
  1272. SOCKET Socket;
  1273. DWORD StackTraceLength;
  1274. PVOID StackTrace[ MAX_STACK_TRACE ];
  1275. } DEBUG_SOCK_ENTRY, *LPDEBUG_SOCK_ENTRY;
  1276. CRITICAL_SECTION DebugSockLock;
  1277. DEBUG_SOCK_ENTRY GlobalSockEntry[MAX_SOCK_ENTRIES];
  1278. DWORD GlobalSocketsCount = 0;
  1279. #define LOCK_DEBUG_SOCK() EnterCriticalSection( &DebugSockLock )
  1280. #define UNLOCK_DEBUG_SOCK() LeaveCriticalSection( &DebugSockLock )
  1281. HINSTANCE NtDllHandle;
  1282. typedef USHORT (*RTL_CAPTURE_STACK_BACK_TRACE)(
  1283. IN ULONG FramesToSkip,
  1284. IN ULONG FramesToCapture,
  1285. OUT PVOID *BackTrace,
  1286. OUT PULONG BackTraceHash
  1287. );
  1288. RTL_CAPTURE_STACK_BACK_TRACE pRtlCaptureStackBackTrace;
  1289. VOID
  1290. InitDebugSock(
  1291. VOID
  1292. )
  1293. {
  1294. InitializeCriticalSection( &DebugSockLock );
  1295. memset( GlobalSockEntry, 0x0, sizeof(GlobalSockEntry) );
  1296. GlobalSocketsCount = 0;
  1297. return;
  1298. }
  1299. VOID
  1300. TerminateDebugSock(
  1301. VOID
  1302. )
  1303. {
  1304. DeleteCriticalSection(&DebugSockLock);
  1305. }
  1306. VOID
  1307. SetupSocketsTracing(
  1308. VOID
  1309. )
  1310. {
  1311. if (!(InternetDebugCategoryFlags & DBG_TRACE_SOCKETS)) {
  1312. return ;
  1313. }
  1314. if (!IsPlatformWinNT()) {
  1315. return ;
  1316. }
  1317. if ((NtDllHandle = LoadLibrary("ntdll.dll")) == NULL) {
  1318. return ;
  1319. }
  1320. if ((pRtlCaptureStackBackTrace =
  1321. (RTL_CAPTURE_STACK_BACK_TRACE)
  1322. GetProcAddress(NtDllHandle, "RtlCaptureStackBackTrace")) == NULL) {
  1323. FreeLibrary(NtDllHandle);
  1324. return ;
  1325. }
  1326. //#ifdef DONT_DO_FOR_NOW
  1327. _P_accept = _I_accept;
  1328. _I_accept = _II_accept;
  1329. _P_closesocket = _I_closesocket;
  1330. _I_closesocket = _II_closesocket;
  1331. _P_socket = _I_socket;
  1332. _I_socket = _II_socket;
  1333. //#endif
  1334. }
  1335. VOID
  1336. AddSockEntry(
  1337. SOCKET S
  1338. )
  1339. {
  1340. DWORD i;
  1341. DWORD Hash;
  1342. if (!(InternetDebugCategoryFlags & DBG_TRACE_SOCKETS)) {
  1343. return ;
  1344. }
  1345. LOCK_DEBUG_SOCK();
  1346. //
  1347. // search for a free entry.
  1348. //
  1349. for( i = 0; i < MAX_SOCK_ENTRIES; i++ ) {
  1350. if( GlobalSockEntry[i].Socket == 0 ) {
  1351. DWORD Hash;
  1352. //
  1353. // found a free entry.
  1354. //
  1355. GlobalSockEntry[i].Socket = S;
  1356. //
  1357. // get caller stack.
  1358. //
  1359. #if i386
  1360. Hash = 0;
  1361. GlobalSockEntry[i].StackTraceLength =
  1362. pRtlCaptureStackBackTrace(
  1363. 2,
  1364. MAX_STACK_TRACE,
  1365. GlobalSockEntry[i].StackTrace,
  1366. &Hash );
  1367. #else // i386
  1368. GlobalSockEntry[i].StackTraceLength = 0;
  1369. #endif // i386
  1370. GlobalSocketsCount++;
  1371. DEBUG_PRINT(SOCKETS,
  1372. INFO,
  1373. ("socket count = %ld\n",
  1374. GlobalSocketsCount
  1375. ));
  1376. DPRINTF("%d sockets\n", GlobalSocketsCount);
  1377. UNLOCK_DEBUG_SOCK();
  1378. return;
  1379. }
  1380. }
  1381. //
  1382. // we have reached a high handle limit, which is unusal, needs to be
  1383. // debugged.
  1384. //
  1385. INET_ASSERT( FALSE );
  1386. UNLOCK_DEBUG_SOCK();
  1387. return;
  1388. }
  1389. VOID
  1390. RemoveSockEntry(
  1391. SOCKET S
  1392. )
  1393. {
  1394. DWORD i;
  1395. if (!(InternetDebugCategoryFlags & DBG_TRACE_SOCKETS)) {
  1396. return ;
  1397. }
  1398. LOCK_DEBUG_SOCK();
  1399. for( i = 0; i < MAX_SOCK_ENTRIES; i++ ) {
  1400. if( GlobalSockEntry[i].Socket == S ) {
  1401. //
  1402. // found the entry. Free it now.
  1403. //
  1404. memset( &GlobalSockEntry[i], 0x0, sizeof(DEBUG_SOCK_ENTRY) );
  1405. GlobalSocketsCount--;
  1406. #ifdef IWINSOCK_DEBUG_PRINT
  1407. DEBUG_PRINT(SOCKETS,
  1408. INFO,
  1409. ("count(%ld), RemoveSock(%lx)\n",
  1410. GlobalSocketsCount,
  1411. S
  1412. ));
  1413. #endif // IWINSOCK_DEBUG_PRINT
  1414. DPRINTF("%d sockets\n", GlobalSocketsCount);
  1415. UNLOCK_DEBUG_SOCK();
  1416. return;
  1417. }
  1418. }
  1419. #ifdef IWINSOCK_DEBUG_PRINT
  1420. DEBUG_PRINT(SOCKETS,
  1421. INFO,
  1422. ("count(%ld), UnknownSock(%lx)\n",
  1423. GlobalSocketsCount,
  1424. S
  1425. ));
  1426. #endif // IWINSOCK_DEBUG_PRINT
  1427. //
  1428. // socket entry is not found.
  1429. //
  1430. // INET_ASSERT( FALSE );
  1431. UNLOCK_DEBUG_SOCK();
  1432. return;
  1433. }
  1434. SOCKET
  1435. PASCAL FAR
  1436. _II_socket(
  1437. int af,
  1438. int type,
  1439. int protocol
  1440. )
  1441. {
  1442. SOCKET S;
  1443. S = _P_socket( af, type, protocol );
  1444. AddSockEntry( S );
  1445. return( S );
  1446. }
  1447. int
  1448. PASCAL FAR
  1449. _II_closesocket(
  1450. SOCKET s
  1451. )
  1452. {
  1453. int Ret;
  1454. RemoveSockEntry( s );
  1455. Ret = _P_closesocket( s );
  1456. return( Ret );
  1457. }
  1458. SOCKET
  1459. PASCAL FAR
  1460. _II_accept(
  1461. SOCKET s,
  1462. struct sockaddr FAR *addr,
  1463. int FAR *addrlen
  1464. )
  1465. {
  1466. SOCKET S;
  1467. S = _P_accept( s, addr, addrlen );
  1468. AddSockEntry( S );
  1469. return( S );
  1470. }
  1471. VOID
  1472. IWinsockCheckSockets(
  1473. VOID
  1474. )
  1475. {
  1476. DEBUG_PRINT(SOCKETS,
  1477. INFO,
  1478. ("GlobalSocketsCount = %d\n",
  1479. GlobalSocketsCount
  1480. ));
  1481. for (DWORD i = 0; i < MAX_SOCK_ENTRIES; ++i) {
  1482. SOCKET sock;
  1483. if ((sock = GlobalSockEntry[i].Socket) != 0) {
  1484. DEBUG_PRINT(SOCKETS,
  1485. INFO,
  1486. ("Socket %#x\n",
  1487. sock
  1488. ));
  1489. }
  1490. }
  1491. }
  1492. #endif // INET_DEBUG
  1493. #if defined(__cplusplus)
  1494. }
  1495. #endif