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.

267 lines
6.6 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. wsload.cxx
  5. Abstract:
  6. Implements the wrapper used to avoid loading the winsock
  7. DLLs into more processes than necessary.
  8. Author:
  9. Mario Goertzel [MarioGo]
  10. Revision History:
  11. MarioGo 3/21/1996 Bits 'n pieces
  12. --*/
  13. #include <precomp.hxx>
  14. #include <wswrap.hxx>
  15. struct WINSOCK_FUNCTION_TABLE WFT;
  16. HMODULE hWinsock = 0;
  17. HMODULE hWinsock2 = 0;
  18. typedef int (PASCAL FAR *PWSASTARTUP)(WORD wVersionRequired, LPWSADATA lpWSAData);
  19. typedef struct tagProcAddressData
  20. {
  21. int nDllIndex; // 0 is ws2_32.dll, 1 is mswsock.dll
  22. char *pProcName;
  23. } ProcAddressData;
  24. const ProcAddressData WinsockProcData[] = {
  25. { 0, "socket" },
  26. { 0, "bind" },
  27. { 0, "closesocket" },
  28. { 0, "getsockname" },
  29. { 0, "connect" },
  30. { 0, "listen" },
  31. { 0, "send" },
  32. { 0, "recv" },
  33. { 0, "sendto" },
  34. { 0, "recvfrom" },
  35. { 0, "setsockopt" },
  36. { 0, "getsockopt" },
  37. { 0, "inet_ntoa" },
  38. { 0, "gethostbyname" },
  39. { 1, "GetAddressByNameA" },
  40. { 0, "WSASocketW" },
  41. { 0, "WSARecv" },
  42. { 0, "WSARecvFrom" },
  43. { 0, "WSASend" },
  44. { 0, "WSASendTo" },
  45. { 0, "WSAProviderConfigChange" },
  46. { 0, "WSAEnumProtocolsW" },
  47. { 0, "WSAIoctl" },
  48. { 0, "getaddrinfo"},
  49. { 0, "freeaddrinfo"},
  50. { 0, "getnameinfo" },
  51. { 0, "WSAGetOverlappedResult" }
  52. };
  53. LONG TriedUsingAfd = 0;
  54. void TryUsingAfdProc(void) {
  55. // Figure out if we can call AFD directly for datagram.
  56. // This is a performance optimization - if any thing fails
  57. // or does match exactly to MSAFD the we'll just use the
  58. // ws2_32 exported functions.
  59. static const UUID aDefaultProviders[] = {
  60. { 0xe70f1aa0, 0xab8b, 0x11cf, 0x8c, 0xa3, 0x0, 0x80, 0x5f, 0x48, 0xa1, 0x92 }, // AFD UDP
  61. { 0x9d60a9e0, 0x337a, 0x11d0, 0xbd, 0x88, 0x0, 0x00, 0xc0, 0x82, 0xe6, 0x9a }, // RSVP UDP
  62. { 0x11058240, 0xbe47, 0x11cf, 0x95, 0xc8, 0x0, 0x80, 0x5f, 0x48, 0xa1, 0x92 } // AFD IPX
  63. };
  64. INT aProtocols[] = { IPPROTO_UDP, NSPROTO_IPX, 0 };
  65. WSAPROTOCOL_INFO *info;
  66. DWORD dwSize;
  67. INT cProtocols;
  68. BOOL fUseAfd = TRUE;
  69. info = new WSAPROTOCOL_INFO[8];
  70. if (info == NULL)
  71. {
  72. cProtocols = 0;
  73. fUseAfd = FALSE;
  74. }
  75. else
  76. {
  77. dwSize = sizeof(WSAPROTOCOL_INFO) * 8;
  78. }
  79. if (fUseAfd)
  80. {
  81. cProtocols = WSAEnumProtocolsT(aProtocols,
  82. info,
  83. &dwSize);
  84. if (cProtocols <= 0)
  85. {
  86. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  87. DPFLTR_WARNING_LEVEL,
  88. RPCTRANS "Failed to enum protocols, using winsock. %d\n",
  89. GetLastError()));
  90. cProtocols = 0;
  91. fUseAfd = FALSE;
  92. }
  93. for (int i = 0; i < cProtocols; i++)
  94. {
  95. BOOL fFoundIt = FALSE;
  96. for (int j = 0; j < sizeof(aDefaultProviders)/sizeof(UUID); j++)
  97. {
  98. if (memcmp(&aDefaultProviders[j], &info[i].ProviderId, sizeof(UUID)) == 0)
  99. {
  100. fFoundIt = TRUE;
  101. }
  102. }
  103. if (!fFoundIt)
  104. {
  105. fUseAfd = FALSE;
  106. }
  107. }
  108. }
  109. if (fUseAfd)
  110. {
  111. WFT.pWSASendTo = AFD_SendTo;
  112. WFT.pWSARecvFrom = AFD_RecvFrom;
  113. }
  114. else
  115. {
  116. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  117. DPFLTR_WARNING_LEVEL,
  118. RPCTRANS "Non-default winsock providers loaded\n"));
  119. }
  120. if (info)
  121. delete info;
  122. }
  123. C_ASSERT((sizeof(WinsockProcData) / sizeof(ProcAddressData)) <= (sizeof(WINSOCK_FUNCTION_TABLE) / sizeof(FARPROC)));
  124. BOOL RPC_WSAStartup(void)
  125. {
  126. // Transport load can only be called by a single thread at a time.
  127. WSADATA data;
  128. PWSASTARTUP pStartup;
  129. FARPROC *ppProc;
  130. BOOL status;
  131. BOOL b;
  132. HMODULE ws2;
  133. HMODULE ws;
  134. HMODULE hDlls[2];
  135. if (hWinsock == 0)
  136. {
  137. ws = LoadLibrary(RPC_CONST_SSTRING("mswsock.dll"));
  138. ws2 = LoadLibrary(RPC_CONST_SSTRING("ws2_32.dll"));
  139. if (ws == 0 || ws2 == 0)
  140. {
  141. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  142. DPFLTR_WARNING_LEVEL,
  143. RPCTRANS "Unable to load windows sockets dlls, bad config? %d\n",
  144. GetLastError()));
  145. return FALSE;
  146. }
  147. }
  148. else
  149. {
  150. // loading already performed - just return true
  151. ASSERT(hWinsock2);
  152. return TRUE;
  153. }
  154. status = FALSE;
  155. pStartup = (PWSASTARTUP)GetProcAddress(ws2, "WSAStartup");
  156. if (pStartup)
  157. {
  158. if ( (*pStartup)(2, &data) == NO_ERROR)
  159. {
  160. status = TRUE;
  161. }
  162. }
  163. if (!status)
  164. {
  165. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  166. DPFLTR_WARNING_LEVEL,
  167. RPCTRANS "GetProcAddr or WSAStartup failed %d\n",
  168. GetLastError()));
  169. b = FreeLibrary(ws);
  170. if (b)
  171. b = FreeLibrary(ws2);
  172. if (!b)
  173. {
  174. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  175. DPFLTR_WARNING_LEVEL,
  176. RPCTRANS "FreeLibrary failed %d\n",
  177. GetLastError()));
  178. ASSERT(0);
  179. }
  180. return(FALSE);
  181. }
  182. ppProc = (FARPROC *)&WFT;
  183. hDlls[0] = ws2;
  184. hDlls[1] = ws;
  185. // WinsockProcData is smaller than WINSOCK_FUNCTION_TABLE. Make sure the loop
  186. // is driven by WinsockProcData
  187. for (int i = 0; i < sizeof(WinsockProcData) / sizeof(ProcAddressData); i++)
  188. {
  189. *ppProc = GetProcAddress(hDlls[WinsockProcData[i].nDllIndex], WinsockProcData[i].pProcName);
  190. if (*ppProc == 0)
  191. {
  192. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  193. DPFLTR_WARNING_LEVEL,
  194. RPCTRANS "Failed to load winsock procedure %s correctly\n",
  195. WinsockProcData[i].pProcName));
  196. b = FreeLibrary(ws);
  197. if (b)
  198. b = FreeLibrary(ws2);
  199. if (!b)
  200. {
  201. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  202. DPFLTR_WARNING_LEVEL,
  203. RPCTRANS "FreeLibrary failed %d\n",
  204. GetLastError()));
  205. ASSERT(0);
  206. }
  207. return(FALSE);
  208. }
  209. *ppProc ++;
  210. }
  211. hWinsock = ws;
  212. hWinsock2 = ws2;
  213. return TRUE;
  214. }