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.

272 lines
7.1 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. // Winsock's function IN6ADDR_SETANY uses the external constant in6addr_any.
  55. // Since we do not statically link to obtain this constatnt, we need to define
  56. // one ourselves.
  57. const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
  58. void TryUsingAfdProc(void) {
  59. // Figure out if we can call AFD directly for datagram.
  60. // This is a performance optimization - if any thing fails
  61. // or does match exactly to MSAFD the we'll just use the
  62. // ws2_32 exported functions.
  63. static const UUID aDefaultProviders[] = {
  64. { 0xe70f1aa0, 0xab8b, 0x11cf, 0x8c, 0xa3, 0x0, 0x80, 0x5f, 0x48, 0xa1, 0x92 }, // AFD UDP
  65. { 0x9d60a9e0, 0x337a, 0x11d0, 0xbd, 0x88, 0x0, 0x00, 0xc0, 0x82, 0xe6, 0x9a }, // RSVP UDP
  66. { 0x11058240, 0xbe47, 0x11cf, 0x95, 0xc8, 0x0, 0x80, 0x5f, 0x48, 0xa1, 0x92 } // AFD IPX
  67. };
  68. INT aProtocols[] = { IPPROTO_UDP, NSPROTO_IPX, 0 };
  69. WSAPROTOCOL_INFO *info;
  70. DWORD dwSize;
  71. INT cProtocols;
  72. BOOL fUseAfd = TRUE;
  73. info = new WSAPROTOCOL_INFO[8];
  74. if (info == NULL)
  75. {
  76. cProtocols = 0;
  77. fUseAfd = FALSE;
  78. }
  79. else
  80. {
  81. dwSize = sizeof(WSAPROTOCOL_INFO) * 8;
  82. }
  83. if (fUseAfd)
  84. {
  85. cProtocols = WSAEnumProtocolsT(aProtocols,
  86. info,
  87. &dwSize);
  88. if (cProtocols <= 0)
  89. {
  90. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  91. DPFLTR_WARNING_LEVEL,
  92. RPCTRANS "Failed to enum protocols, using winsock. %d\n",
  93. GetLastError()));
  94. cProtocols = 0;
  95. fUseAfd = FALSE;
  96. }
  97. for (int i = 0; i < cProtocols; i++)
  98. {
  99. BOOL fFoundIt = FALSE;
  100. for (int j = 0; j < sizeof(aDefaultProviders)/sizeof(UUID); j++)
  101. {
  102. if (memcmp(&aDefaultProviders[j], &info[i].ProviderId, sizeof(UUID)) == 0)
  103. {
  104. fFoundIt = TRUE;
  105. }
  106. }
  107. if (!fFoundIt)
  108. {
  109. fUseAfd = FALSE;
  110. }
  111. }
  112. }
  113. if (fUseAfd)
  114. {
  115. WFT.pWSASendTo = AFD_SendTo;
  116. WFT.pWSARecvFrom = AFD_RecvFrom;
  117. }
  118. else
  119. {
  120. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  121. DPFLTR_WARNING_LEVEL,
  122. RPCTRANS "Non-default winsock providers loaded\n"));
  123. }
  124. if (info)
  125. delete [] info;
  126. }
  127. C_ASSERT((sizeof(WinsockProcData) / sizeof(ProcAddressData)) <= (sizeof(WINSOCK_FUNCTION_TABLE) / sizeof(FARPROC)));
  128. BOOL RPC_WSAStartup(void)
  129. {
  130. // Transport load can only be called by a single thread at a time.
  131. WSADATA data;
  132. PWSASTARTUP pStartup;
  133. FARPROC *ppProc;
  134. BOOL status;
  135. BOOL b;
  136. HMODULE ws2;
  137. HMODULE ws;
  138. HMODULE hDlls[2];
  139. if (hWinsock == 0)
  140. {
  141. ws = LoadLibrary(RPC_CONST_SSTRING("mswsock.dll"));
  142. ws2 = LoadLibrary(RPC_CONST_SSTRING("ws2_32.dll"));
  143. if (ws == 0 || ws2 == 0)
  144. {
  145. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  146. DPFLTR_WARNING_LEVEL,
  147. RPCTRANS "Unable to load windows sockets dlls, bad config? %d\n",
  148. GetLastError()));
  149. return FALSE;
  150. }
  151. }
  152. else
  153. {
  154. // loading already performed - just return true
  155. ASSERT(hWinsock2);
  156. return TRUE;
  157. }
  158. status = FALSE;
  159. pStartup = (PWSASTARTUP)GetProcAddress(ws2, "WSAStartup");
  160. if (pStartup)
  161. {
  162. if ( (*pStartup)(2, &data) == NO_ERROR)
  163. {
  164. status = TRUE;
  165. }
  166. }
  167. if (!status)
  168. {
  169. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  170. DPFLTR_WARNING_LEVEL,
  171. RPCTRANS "GetProcAddr or WSAStartup failed %d\n",
  172. GetLastError()));
  173. b = FreeLibrary(ws);
  174. if (b)
  175. b = FreeLibrary(ws2);
  176. if (!b)
  177. {
  178. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  179. DPFLTR_WARNING_LEVEL,
  180. RPCTRANS "FreeLibrary failed %d\n",
  181. GetLastError()));
  182. ASSERT(0);
  183. }
  184. return(FALSE);
  185. }
  186. ppProc = (FARPROC *)&WFT;
  187. hDlls[0] = ws2;
  188. hDlls[1] = ws;
  189. // WinsockProcData is smaller than WINSOCK_FUNCTION_TABLE. Make sure the loop
  190. // is driven by WinsockProcData
  191. for (int i = 0; i < sizeof(WinsockProcData) / sizeof(ProcAddressData); i++)
  192. {
  193. *ppProc = GetProcAddress(hDlls[WinsockProcData[i].nDllIndex], WinsockProcData[i].pProcName);
  194. if (*ppProc == 0)
  195. {
  196. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  197. DPFLTR_WARNING_LEVEL,
  198. RPCTRANS "Failed to load winsock procedure %s correctly\n",
  199. WinsockProcData[i].pProcName));
  200. b = FreeLibrary(ws);
  201. if (b)
  202. b = FreeLibrary(ws2);
  203. if (!b)
  204. {
  205. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  206. DPFLTR_WARNING_LEVEL,
  207. RPCTRANS "FreeLibrary failed %d\n",
  208. GetLastError()));
  209. ASSERT(0);
  210. }
  211. return(FALSE);
  212. }
  213. ppProc ++;
  214. }
  215. hWinsock = ws;
  216. hWinsock2 = ws2;
  217. return TRUE;
  218. }