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.

1180 lines
22 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. //#define RLF_DEBUG 1
  33. #if INET_DEBUG
  34. #ifdef RLF_DEBUG
  35. #define DPRINTF dprintf
  36. #else
  37. #define DPRINTF (void)
  38. #endif
  39. BOOL
  40. InitDebugSock(
  41. VOID
  42. );
  43. VOID
  44. TerminateDebugSock(
  45. VOID
  46. );
  47. #else
  48. #define DPRINTF (void)
  49. #endif
  50. //
  51. // private types
  52. //
  53. typedef struct {
  54. LPSTR FunctionOrdinal;
  55. FARPROC * FunctionAddress;
  56. } SOCKETS_FUNCTION;
  57. //
  58. // global data
  59. //
  60. GLOBAL
  61. SOCKET
  62. (PASCAL FAR * _I_accept)(
  63. SOCKET s,
  64. struct sockaddr FAR *addr,
  65. int FAR *addrlen
  66. ) = NULL;
  67. GLOBAL
  68. int
  69. (PASCAL FAR * _I_bind)(
  70. SOCKET s,
  71. const struct sockaddr FAR *addr,
  72. int namelen
  73. ) = NULL;
  74. GLOBAL
  75. int
  76. (PASCAL FAR * _I_closesocket)(
  77. SOCKET s
  78. ) = NULL;
  79. GLOBAL
  80. int
  81. (PASCAL FAR * _I_connect)(
  82. SOCKET s,
  83. const struct sockaddr FAR *name,
  84. int namelen
  85. ) = NULL;
  86. GLOBAL
  87. int
  88. (PASCAL FAR * _I_gethostname)(
  89. char FAR * name,
  90. int namelen
  91. ) = NULL;
  92. GLOBAL
  93. LPHOSTENT
  94. (PASCAL FAR * _I_gethostbyname)(
  95. LPSTR lpHostName
  96. ) = NULL;
  97. GLOBAL
  98. int
  99. (PASCAL FAR * _I_getsockname)(
  100. SOCKET s,
  101. struct sockaddr FAR *name,
  102. int FAR * namelen
  103. ) = NULL;
  104. GLOBAL
  105. int
  106. (PASCAL FAR * _I_getsockopt)(
  107. SOCKET s,
  108. int level,
  109. int optname,
  110. char FAR * optval,
  111. int FAR *optlen
  112. );
  113. GLOBAL
  114. u_long
  115. (PASCAL FAR * _I_htonl)(
  116. u_long hostlong
  117. ) = NULL;
  118. GLOBAL
  119. u_short
  120. (PASCAL FAR * _I_htons)(
  121. u_short hostshort
  122. ) = NULL;
  123. GLOBAL
  124. unsigned long
  125. (PASCAL FAR * _I_inet_addr)(
  126. const char FAR * cp
  127. ) = NULL;
  128. GLOBAL
  129. char FAR *
  130. (PASCAL FAR * _I_inet_ntoa)(
  131. struct in_addr in
  132. ) = NULL;
  133. GLOBAL
  134. int
  135. (PASCAL FAR * _I_ioctlsocket)(
  136. SOCKET s,
  137. long cmd,
  138. u_long FAR *argp
  139. ) = NULL;
  140. GLOBAL
  141. int
  142. (PASCAL FAR * _I_listen)(
  143. SOCKET s,
  144. int backlog
  145. ) = NULL;
  146. GLOBAL
  147. u_short
  148. (PASCAL FAR * _I_ntohs)(
  149. u_short netshort
  150. ) = NULL;
  151. GLOBAL
  152. int
  153. (PASCAL FAR * _I_recv)(
  154. SOCKET s,
  155. char FAR * buf,
  156. int len,
  157. int flags
  158. ) = NULL;
  159. GLOBAL
  160. int
  161. (PASCAL FAR * _I_WSARecv)(
  162. SOCKET s,
  163. LPWSABUF lpBuffers,
  164. DWORD dwBufferCount,
  165. LPDWORD lpNumberOfBytesRecvd,
  166. LPDWORD lpFlags,
  167. LPWSAOVERLAPPED lpOverlapped,
  168. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  169. ) = NULL;
  170. GLOBAL
  171. int
  172. (PASCAL FAR * _I_recvfrom)(
  173. SOCKET s,
  174. char FAR * buf,
  175. int len,
  176. int flags,
  177. struct sockaddr FAR *from,
  178. int FAR * fromlen
  179. ) = NULL;
  180. GLOBAL
  181. int
  182. (PASCAL FAR * _I_select)(
  183. int nfds,
  184. fd_set FAR *readfds,
  185. fd_set FAR *writefds,
  186. fd_set FAR *exceptfds,
  187. const struct timeval FAR *timeout
  188. ) = NULL;
  189. GLOBAL
  190. int
  191. (PASCAL FAR * _I_send)(
  192. SOCKET s,
  193. const char FAR * buf,
  194. int len,
  195. int flags
  196. ) = NULL;
  197. GLOBAL
  198. int
  199. (PASCAL FAR * _I_WSASend)(
  200. SOCKET s,
  201. LPWSABUF lpBuffers,
  202. DWORD dwBufferCount,
  203. LPDWORD lpNumberOfBytesSent,
  204. DWORD dwFlags,
  205. LPWSAOVERLAPPED lpOverlapped,
  206. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  207. ) = NULL;
  208. GLOBAL
  209. int
  210. (PASCAL FAR * _I_sendto)(
  211. SOCKET s,
  212. const char FAR * buf,
  213. int len,
  214. int flags,
  215. const struct sockaddr FAR *to,
  216. int tolen
  217. ) = NULL;
  218. GLOBAL
  219. int
  220. (PASCAL FAR * _I_setsockopt)(
  221. SOCKET s,
  222. int level,
  223. int optname,
  224. const char FAR * optval,
  225. int optlen
  226. ) = NULL;
  227. GLOBAL
  228. int
  229. (PASCAL FAR * _I_shutdown)(
  230. SOCKET s,
  231. int how
  232. ) = NULL;
  233. GLOBAL
  234. SOCKET
  235. (PASCAL FAR * _I_socket)(
  236. int af,
  237. int type,
  238. int protocol
  239. ) = NULL;
  240. GLOBAL
  241. int
  242. (PASCAL FAR * _I_WSAStartup)(
  243. WORD wVersionRequired,
  244. LPWSADATA lpWSAData
  245. ) = NULL;
  246. GLOBAL
  247. int
  248. (PASCAL FAR * _I_WSACleanup)(
  249. void
  250. ) = NULL;
  251. //VENKATKBUG-remove later - for now trap any errors
  252. GLOBAL
  253. int
  254. (PASCAL FAR * __I_WSAGetLastError)(
  255. void
  256. ) = NULL;
  257. int
  258. ___I_WSAGetLastError(
  259. VOID
  260. )
  261. {
  262. int nError = __I_WSAGetLastError();
  263. /*
  264. VENKATK_BUG - OK to have WSAENOTSOCK - could happen for timeout situations.
  265. INET_ASSERT (nError != WSAENOTSOCK);
  266. */
  267. return nError;
  268. }
  269. GLOBAL
  270. int
  271. (PASCAL FAR * _I_WSAGetLastError)(
  272. void
  273. ) = ___I_WSAGetLastError;
  274. GLOBAL
  275. void
  276. (PASCAL FAR * _I_WSASetLastError)(
  277. int iError
  278. ) = NULL;
  279. GLOBAL
  280. int
  281. (PASCAL FAR * _I___WSAFDIsSet)(
  282. SOCKET,
  283. fd_set FAR *
  284. ) = NULL;
  285. #if INET_DEBUG
  286. void SetupSocketsTracing(void);
  287. #endif
  288. //
  289. // private data
  290. //
  291. //
  292. // InitializationLock - protects against multiple threads loading WSOCK32.DLL
  293. // and entry points
  294. //
  295. PRIVATE CCritSec InitializationLock;
  296. //
  297. // hWinsock - NULL when WSOCK32.DLL is not loaded
  298. //
  299. PRIVATE HINSTANCE hWinsock = NULL;
  300. //
  301. // WinsockLoadCount - the number of times we have made calls to LoadWinsock()
  302. // and UnloadWinsock(). When this reaches 0 (again), we can unload the Winsock
  303. // DLL for real
  304. //
  305. PRIVATE DWORD WinsockLoadCount = 0;
  306. //
  307. // SocketsFunctions - this is the list of entry points in WSOCK32.DLL that we
  308. // need to load for WININET.DLL
  309. //
  310. PRIVATE
  311. SOCKETS_FUNCTION
  312. SocketsFunctions[] = {
  313. "accept", (FARPROC*)&_I_accept,
  314. "bind", (FARPROC*)&_I_bind,
  315. "closesocket", (FARPROC*)&_I_closesocket,
  316. "connect", (FARPROC*)&_I_connect,
  317. "getsockname", (FARPROC*)&_I_getsockname,
  318. "getsockopt", (FARPROC*)&_I_getsockopt,
  319. "htonl", (FARPROC*)&_I_htonl,
  320. "htons", (FARPROC*)&_I_htons,
  321. "inet_addr", (FARPROC*)&_I_inet_addr,
  322. "inet_ntoa", (FARPROC*)&_I_inet_ntoa,
  323. "ioctlsocket", (FARPROC*)&_I_ioctlsocket,
  324. "listen", (FARPROC*)&_I_listen,
  325. "ntohs", (FARPROC*)&_I_ntohs,
  326. "recv", (FARPROC*)&_I_recv,
  327. "recvfrom", (FARPROC*)&_I_recvfrom,
  328. "select", (FARPROC*)&_I_select,
  329. "send", (FARPROC*)&_I_send,
  330. "sendto", (FARPROC*)&_I_sendto,
  331. "setsockopt", (FARPROC*)&_I_setsockopt,
  332. "shutdown", (FARPROC*)&_I_shutdown,
  333. "socket", (FARPROC*)&_I_socket,
  334. "gethostbyname", (FARPROC*)&_I_gethostbyname,
  335. "gethostname", (FARPROC*)&_I_gethostname,
  336. "WSAGetLastError", (FARPROC*)&__I_WSAGetLastError,
  337. "WSASetLastError", (FARPROC*)&_I_WSASetLastError,
  338. "WSAStartup", (FARPROC*)&_I_WSAStartup,
  339. "WSACleanup", (FARPROC*)&_I_WSACleanup,
  340. "__WSAFDIsSet", (FARPROC*)&_I___WSAFDIsSet,
  341. "WSARecv", (FARPROC*)&_I_WSARecv,
  342. "WSASend", (FARPROC*)&_I_WSASend
  343. };
  344. //
  345. // private prototypes
  346. //
  347. #if INET_DEBUG
  348. void SetupSocketsTracing(void);
  349. #endif
  350. //
  351. // functions
  352. //
  353. BOOL
  354. IwinsockInitialize(
  355. VOID
  356. )
  357. /*++
  358. Routine Description:
  359. Performs initialization/resource allocation for this module
  360. Arguments:
  361. None.
  362. Return Value:
  363. None.
  364. --*/
  365. {
  366. BOOL fResult;
  367. //
  368. // initialize the critical section that protects against multiple threads
  369. // trying to initialize Winsock
  370. //
  371. fResult = InitializationLock.Init();
  372. #if INET_DEBUG
  373. if (fResult)
  374. fResult = InitDebugSock();
  375. #endif
  376. return fResult;
  377. }
  378. VOID
  379. IwinsockTerminate(
  380. VOID
  381. )
  382. /*++
  383. Routine Description:
  384. Performs termination & resource cleanup for this module
  385. Arguments:
  386. None.
  387. Return Value:
  388. None.
  389. --*/
  390. {
  391. InitializationLock.FreeLock();
  392. #if INET_DEBUG
  393. TerminateDebugSock();
  394. #endif
  395. }
  396. DWORD
  397. LoadWinsock(
  398. VOID
  399. )
  400. /*++
  401. Routine Description:
  402. Dynamically loads Windows sockets library
  403. Arguments:
  404. None.
  405. Return Value:
  406. DWORD
  407. Success - ERROR_SUCCESS
  408. Failure - Win32 error
  409. e.g. LoadLibrary() failure
  410. WSA error
  411. e.g. WSAStartup() failure
  412. --*/
  413. {
  414. DEBUG_ENTER((DBG_SOCKETS,
  415. Dword,
  416. "LoadWinsock",
  417. NULL
  418. ));
  419. DWORD error = ERROR_SUCCESS;
  420. //
  421. // ensure no 2 threads are trying to modify the loaded state of winsock at
  422. // the same time
  423. //
  424. if (!InitializationLock.Lock())
  425. {
  426. error = ERROR_NOT_ENOUGH_MEMORY;
  427. goto quit;
  428. }
  429. if (hWinsock == NULL) {
  430. BOOL failed = FALSE;
  431. //
  432. // BUGBUG - read this value from registry
  433. //
  434. hWinsock = LoadLibrary("ws2_32");
  435. if (hWinsock == NULL) {
  436. DEBUG_PRINT(SOCKETS,
  437. INFO,
  438. ("failed to load ws2_32.dll"));
  439. hWinsock = LoadLibrary("wsock32");
  440. }
  441. if (hWinsock != NULL) {
  442. //
  443. // load the entry points
  444. //
  445. for (int i = 0; i < ARRAY_ELEMENTS(SocketsFunctions); ++i) {
  446. FARPROC farProc;
  447. farProc = GetProcAddress(
  448. hWinsock,
  449. (LPCSTR)SocketsFunctions[i].FunctionOrdinal
  450. );
  451. if (farProc == NULL) {
  452. failed = TRUE;
  453. break;
  454. }
  455. *SocketsFunctions[i].FunctionAddress = farProc;
  456. }
  457. if (!failed) {
  458. //
  459. // although we need a WSADATA for WSAStartup(), it is an
  460. // expendible structure (not required for any other sockets
  461. // calls)
  462. //
  463. WSADATA wsaData;
  464. error = _I_WSAStartup(0x0101, &wsaData);
  465. if (error == ERROR_SUCCESS) {
  466. DEBUG_PRINT(SOCKETS,
  467. INFO,
  468. ("winsock description: %q\n",
  469. wsaData.szDescription
  470. ));
  471. int stringLen;
  472. stringLen = lstrlen(wsaData.szDescription);
  473. if (strnistr(wsaData.szDescription, "novell", stringLen)
  474. && strnistr(wsaData.szDescription, "wsock32", stringLen)) {
  475. DEBUG_PRINT(SOCKETS,
  476. INFO,
  477. ("running on Novell Client32 stack\n"
  478. ));
  479. GlobalRunningNovellClient32 = TRUE;
  480. }
  481. #if INET_DEBUG
  482. SetupSocketsTracing();
  483. #endif
  484. } else {
  485. failed = TRUE;
  486. }
  487. }
  488. } else {
  489. failed = TRUE;
  490. }
  491. //
  492. // if we failed to find an entry point or WSAStartup() returned an error
  493. // then unload the library
  494. //
  495. if (failed) {
  496. //
  497. // important: there should be no API calls between determining the
  498. // failure and coming here to get the error code
  499. //
  500. // if error == ERROR_SUCCESS then we have to get the last error, else
  501. // it is the error returned by WSAStartup()
  502. //
  503. if (error == ERROR_SUCCESS) {
  504. error = GetLastError();
  505. INET_ASSERT(error != ERROR_SUCCESS);
  506. }
  507. UnloadWinsock();
  508. }
  509. } else {
  510. //
  511. // just increment the number of times we have called LoadWinsock()
  512. // without a corresponding call to UnloadWinsock();
  513. //
  514. ++WinsockLoadCount;
  515. }
  516. InitializationLock.Unlock();
  517. //
  518. // if we failed for any reason, need to report that TCP/IP not available
  519. //
  520. if (error != ERROR_SUCCESS) {
  521. error = ERROR_NOT_SUPPORTED;
  522. }
  523. quit:
  524. DEBUG_LEAVE(error);
  525. return error;
  526. }
  527. VOID
  528. UnloadWinsock(
  529. VOID
  530. )
  531. /*++
  532. Routine Description:
  533. Unloads winsock DLL and prepares hWinsock and SocketsFunctions[] for reload
  534. Arguments:
  535. None.
  536. Return Value:
  537. None.
  538. --*/
  539. {
  540. DEBUG_ENTER((DBG_SOCKETS,
  541. None,
  542. "UnloadWinsock",
  543. NULL
  544. ));
  545. //
  546. // ensure no 2 threads are trying to modify the loaded state of winsock at
  547. // the same time
  548. //
  549. if (!InitializationLock.Lock())
  550. {
  551. goto quit;
  552. }
  553. //
  554. // only unload the DLL if it has been mapped into process memory
  555. //
  556. if (hWinsock != NULL) {
  557. //
  558. // and only if this is the last load instance
  559. //
  560. if (WinsockLoadCount == 0) {
  561. INET_ASSERT(_I_WSACleanup != NULL);
  562. if (_I_WSACleanup != NULL) {
  563. //
  564. // need to terminate async support too - it is reliant on
  565. // Winsock
  566. //
  567. //called only from LoadWinsock which is called only from INTERNET_HANDLE_OBJECT()
  568. //so not in dynamic unload, so alrite to cleanup.
  569. TerminateAsyncSupport(TRUE);
  570. int serr = _I_WSACleanup();
  571. if (serr != 0) {
  572. DEBUG_PRINT(SOCKETS,
  573. ERROR,
  574. ("WSACleanup() returns %d; WSA error = %d\n",
  575. serr,
  576. (_I_WSAGetLastError != NULL)
  577. ? _I_WSAGetLastError()
  578. : -1
  579. ));
  580. }
  581. }
  582. for (int i = 0; i < ARRAY_ELEMENTS(SocketsFunctions); ++i) {
  583. *SocketsFunctions[i].FunctionAddress = (FARPROC)NULL;
  584. }
  585. FreeLibrary(hWinsock);
  586. hWinsock = NULL;
  587. } else {
  588. //
  589. // if there have been multiple virtual loads, then just reduce the
  590. // load count
  591. //
  592. --WinsockLoadCount;
  593. }
  594. }
  595. InitializationLock.Unlock();
  596. quit:
  597. DEBUG_LEAVE(0);
  598. }
  599. DWORD
  600. SafeCloseSocket(
  601. IN SOCKET Socket
  602. )
  603. /*++
  604. Routine Description:
  605. closesocket() call protected by exception handler in case winsock DLL has
  606. been unloaded by system before Wininet DLL unloaded
  607. Arguments:
  608. Socket - socket handle to close
  609. Return Value:
  610. DWORD
  611. Success - ERROR_SUCCESS
  612. Failure - socket error mapped to ERROR_WINHTTP_ error
  613. --*/
  614. {
  615. int serr;
  616. __try {
  617. serr = _I_closesocket(Socket);
  618. } __except(EXCEPTION_EXECUTE_HANDLER) {
  619. serr = 0;
  620. }
  621. ENDEXCEPT
  622. return (serr == SOCKET_ERROR)
  623. ? MapInternetError(_I_WSAGetLastError())
  624. : ERROR_SUCCESS;
  625. }
  626. CWrapOverlapped* GetWrapOverlappedObject(LPVOID lpAddress)
  627. {
  628. return CONTAINING_RECORD(lpAddress, CWrapOverlapped, m_Overlapped);
  629. }
  630. #if INET_DEBUG
  631. //
  632. // debug data types
  633. //
  634. SOCKET
  635. PASCAL FAR
  636. _II_socket(
  637. int af,
  638. int type,
  639. int protocol
  640. );
  641. int
  642. PASCAL FAR
  643. _II_closesocket(
  644. SOCKET s
  645. );
  646. SOCKET
  647. PASCAL FAR
  648. _II_accept(
  649. SOCKET s,
  650. struct sockaddr FAR *addr,
  651. int FAR *addrlen
  652. );
  653. GLOBAL
  654. SOCKET
  655. (PASCAL FAR * _P_accept)(
  656. SOCKET s,
  657. struct sockaddr FAR *addr,
  658. int FAR *addrlen
  659. ) = NULL;
  660. GLOBAL
  661. int
  662. (PASCAL FAR * _P_closesocket)(
  663. SOCKET s
  664. ) = NULL;
  665. GLOBAL
  666. SOCKET
  667. (PASCAL FAR * _P_socket)(
  668. int af,
  669. int type,
  670. int protocol
  671. ) = NULL;
  672. #define MAX_STACK_TRACE 5
  673. #define MAX_SOCK_ENTRIES 1000
  674. typedef struct _DEBUG_SOCK_ENTRY {
  675. SOCKET Socket;
  676. DWORD StackTraceLength;
  677. PVOID StackTrace[ MAX_STACK_TRACE ];
  678. } DEBUG_SOCK_ENTRY, *LPDEBUG_SOCK_ENTRY;
  679. CCritSec DebugSockLock;
  680. DEBUG_SOCK_ENTRY GlobalSockEntry[MAX_SOCK_ENTRIES];
  681. DWORD GlobalSocketsCount = 0;
  682. #define LOCK_DEBUG_SOCK() (DebugSockLock.Lock())
  683. #define UNLOCK_DEBUG_SOCK() (DebugSockLock.Unlock())
  684. HINSTANCE NtDllHandle;
  685. typedef USHORT (*RTL_CAPTURE_STACK_BACK_TRACE)(
  686. IN ULONG FramesToSkip,
  687. IN ULONG FramesToCapture,
  688. OUT PVOID *BackTrace,
  689. OUT PULONG BackTraceHash
  690. );
  691. RTL_CAPTURE_STACK_BACK_TRACE pRtlCaptureStackBackTrace;
  692. BOOL
  693. InitDebugSock(
  694. VOID
  695. )
  696. {
  697. memset( GlobalSockEntry, 0x0, sizeof(GlobalSockEntry) );
  698. GlobalSocketsCount = 0;
  699. if (!DebugSockLock.Init())
  700. {
  701. INET_ASSERT(FALSE);
  702. return FALSE;
  703. }
  704. else
  705. {
  706. return TRUE;
  707. }
  708. }
  709. VOID
  710. TerminateDebugSock(
  711. VOID
  712. )
  713. {
  714. DebugSockLock.FreeLock();
  715. }
  716. VOID
  717. SetupSocketsTracing(
  718. VOID
  719. )
  720. {
  721. if (!(InternetDebugCategoryFlags & DBG_TRACE_SOCKETS)) {
  722. return ;
  723. }
  724. if (!IsPlatformWinNT()) {
  725. return ;
  726. }
  727. if ((NtDllHandle = LoadLibrary("ntdll.dll")) == NULL) {
  728. return ;
  729. }
  730. if ((pRtlCaptureStackBackTrace =
  731. (RTL_CAPTURE_STACK_BACK_TRACE)
  732. GetProcAddress(NtDllHandle, "RtlCaptureStackBackTrace")) == NULL) {
  733. FreeLibrary(NtDllHandle);
  734. return ;
  735. }
  736. //#ifdef DONT_DO_FOR_NOW
  737. _P_accept = _I_accept;
  738. _I_accept = _II_accept;
  739. _P_closesocket = _I_closesocket;
  740. _I_closesocket = _II_closesocket;
  741. _P_socket = _I_socket;
  742. _I_socket = _II_socket;
  743. //#endif
  744. }
  745. VOID
  746. AddSockEntry(
  747. SOCKET S
  748. )
  749. {
  750. DWORD i;
  751. DWORD Hash;
  752. if (!(InternetDebugCategoryFlags & DBG_TRACE_SOCKETS)) {
  753. return ;
  754. }
  755. LOCK_DEBUG_SOCK();
  756. //
  757. // search for a free entry.
  758. //
  759. for( i = 0; i < MAX_SOCK_ENTRIES; i++ ) {
  760. if( GlobalSockEntry[i].Socket == 0 ) {
  761. DWORD Hash;
  762. //
  763. // found a free entry.
  764. //
  765. GlobalSockEntry[i].Socket = S;
  766. //
  767. // get caller stack.
  768. //
  769. #if i386
  770. Hash = 0;
  771. GlobalSockEntry[i].StackTraceLength =
  772. pRtlCaptureStackBackTrace(
  773. 2,
  774. MAX_STACK_TRACE,
  775. GlobalSockEntry[i].StackTrace,
  776. &Hash );
  777. #else // i386
  778. GlobalSockEntry[i].StackTraceLength = 0;
  779. #endif // i386
  780. GlobalSocketsCount++;
  781. DEBUG_PRINT(SOCKETS,
  782. INFO,
  783. ("socket count = %ld\n",
  784. GlobalSocketsCount
  785. ));
  786. DPRINTF("%d sockets\n", GlobalSocketsCount);
  787. UNLOCK_DEBUG_SOCK();
  788. return;
  789. }
  790. }
  791. //
  792. // we have reached a high handle limit, which is unusal, needs to be
  793. // debugged.
  794. //
  795. INET_ASSERT( FALSE );
  796. UNLOCK_DEBUG_SOCK();
  797. return;
  798. }
  799. VOID
  800. RemoveSockEntry(
  801. SOCKET S
  802. )
  803. {
  804. DWORD i;
  805. if (!(InternetDebugCategoryFlags & DBG_TRACE_SOCKETS)) {
  806. return ;
  807. }
  808. LOCK_DEBUG_SOCK();
  809. for( i = 0; i < MAX_SOCK_ENTRIES; i++ ) {
  810. if( GlobalSockEntry[i].Socket == S ) {
  811. //
  812. // found the entry. Free it now.
  813. //
  814. memset( &GlobalSockEntry[i], 0x0, sizeof(DEBUG_SOCK_ENTRY) );
  815. GlobalSocketsCount--;
  816. #ifdef IWINSOCK_DEBUG_PRINT
  817. DEBUG_PRINT(SOCKETS,
  818. INFO,
  819. ("count(%ld), RemoveSock(%lx)\n",
  820. GlobalSocketsCount,
  821. S
  822. ));
  823. #endif // IWINSOCK_DEBUG_PRINT
  824. DPRINTF("%d sockets\n", GlobalSocketsCount);
  825. UNLOCK_DEBUG_SOCK();
  826. return;
  827. }
  828. }
  829. #ifdef IWINSOCK_DEBUG_PRINT
  830. DEBUG_PRINT(SOCKETS,
  831. INFO,
  832. ("count(%ld), UnknownSock(%lx)\n",
  833. GlobalSocketsCount,
  834. S
  835. ));
  836. #endif // IWINSOCK_DEBUG_PRINT
  837. //
  838. // socket entry is not found.
  839. //
  840. // INET_ASSERT( FALSE );
  841. UNLOCK_DEBUG_SOCK();
  842. return;
  843. }
  844. SOCKET
  845. PASCAL FAR
  846. _II_socket(
  847. int af,
  848. int type,
  849. int protocol
  850. )
  851. {
  852. SOCKET S;
  853. S = _P_socket( af, type, protocol );
  854. AddSockEntry( S );
  855. return( S );
  856. }
  857. int
  858. PASCAL FAR
  859. _II_closesocket(
  860. SOCKET s
  861. )
  862. {
  863. int Ret;
  864. RemoveSockEntry( s );
  865. Ret = _P_closesocket( s );
  866. return( Ret );
  867. }
  868. SOCKET
  869. PASCAL FAR
  870. _II_accept(
  871. SOCKET s,
  872. struct sockaddr FAR *addr,
  873. int FAR *addrlen
  874. )
  875. {
  876. SOCKET S;
  877. S = _P_accept( s, addr, addrlen );
  878. AddSockEntry( S );
  879. return( S );
  880. }
  881. VOID
  882. IWinsockCheckSockets(
  883. VOID
  884. )
  885. {
  886. DEBUG_PRINT(SOCKETS,
  887. INFO,
  888. ("GlobalSocketsCount = %d\n",
  889. GlobalSocketsCount
  890. ));
  891. for (DWORD i = 0; i < MAX_SOCK_ENTRIES; ++i) {
  892. SOCKET sock;
  893. if ((sock = GlobalSockEntry[i].Socket) != 0) {
  894. DEBUG_PRINT(SOCKETS,
  895. INFO,
  896. ("Socket %#x\n",
  897. sock
  898. ));
  899. }
  900. }
  901. }
  902. #endif // INET_DEBUG
  903. #if defined(__cplusplus)
  904. }
  905. #endif