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.

1377 lines
43 KiB

  1. #include "windows.h"
  2. #include "types.h"
  3. #include "winsock.h"
  4. #include "wsasync.h"
  5. #ifdef UNDER_CE
  6. #include <ceconfig.h>
  7. #endif
  8. DWORD CopyHostEnt(PHOSTENT lpWinsockHostEnt, PHOSTENT lpHostEnt,
  9. LPDWORD lpdwHostEntBufferSize);
  10. #define ProxyDbgAssert(x) ASSERT(x)
  11. // If Count is not already aligned, then
  12. // round Count up to an even multiple of "Pow2". "Pow2" must be a power of 2.
  13. //
  14. // DWORD
  15. // ROUND_UP_COUNT(
  16. // IN DWORD Count,
  17. // IN DWORD Pow2
  18. // );
  19. #define ROUND_UP_COUNT(Count,Pow2) \
  20. ( ((Count)+(Pow2)-1) & (~((Pow2)-1)) )
  21. #define ALIGN_DWORD 4
  22. #ifdef DEBUG
  23. DBGPARAM dpCurSettings = {
  24. TEXT("WSASYNC"), {
  25. TEXT("Init"), TEXT("HostName"),TEXT("Undefined"),TEXT("Undefined"),
  26. TEXT("Recv"),TEXT("Send"),TEXT("Undefined"),TEXT("Undefined"),
  27. TEXT("Undefined"),TEXT("Undefined"),TEXT("Interface"),TEXT("Misc"),
  28. TEXT("Alloc"), TEXT("Function"), TEXT("Warning"), TEXT("Error") },
  29. 0x0000c000
  30. };
  31. #define ZONE_INIT DEBUGZONE(0) // 0x0001
  32. #define ZONE_HNAME DEBUGZONE(1) // 0x0002
  33. //#define ZONE_??? DEBUGZONE(2) // 0x0004
  34. //#define ZONE_??? DEBUGZONE(3) // 0x0008
  35. #define ZONE_RECV DEBUGZONE(4) // 0x0010
  36. #define ZONE_SEND DEBUGZONE(5) // 0x0020
  37. #define ZONE_SELECT DEBUGZONE(6) // 0x0040
  38. #define ZONE_CLOSE DEBUGZONE(7) // 0x0080
  39. //#define ZONE_??? DEBUGZONE(8) // 0x0100
  40. #define ZONE_MSG DEBUGZONE(9) // 0x0200
  41. #define ZONE_INTERFACE DEBUGZONE(10) // 0x0400
  42. #define ZONE_MISC DEBUGZONE(11) // 0x0800
  43. #define ZONE_ALLOC DEBUGZONE(12) // 0x1000
  44. #define ZONE_FUNCTION DEBUGZONE(13) // 0x2000
  45. #define ZONE_WARN DEBUGZONE(14) // 0x4000
  46. #define ZONE_ERROR DEBUGZONE(15) // 0x8000
  47. #endif
  48. typedef struct GetNames {
  49. struct GetNames *pNext;
  50. HANDLE hThread;
  51. HWND hWnd;
  52. uint wMsg;
  53. char *pBuf;
  54. DWORD dwBufLen;
  55. char *pName;
  56. DWORD Status;
  57. } GetNames;
  58. GetNames *v_pNameList;
  59. CRITICAL_SECTION v_NameListCS;
  60. BOOL v_fNameListInit = FALSE;
  61. #define MAXALIASES 15 // We only support 5 aliases
  62. #define AVG_HOST_LEN 40 // To calculate buff space
  63. #define MAXADDRS 15 // Max of 5 IP addrs
  64. typedef struct FULL_HOSTENT {
  65. HOSTENT hostent;
  66. PSTR host_aliases[MAXALIASES+1];
  67. char hostbuf[(MAXALIASES+1)*AVG_HOST_LEN];
  68. PSTR h_addr_ptrs[MAXADDRS + 1];
  69. uchar hostaddr[MAXADDRS*4];
  70. } FULL_HOSTENT;
  71. GetNames **_FindName(HANDLE hThread) {
  72. GetNames **ppName;
  73. ppName = &v_pNameList;
  74. while (*ppName && hThread != (*ppName)->hThread)
  75. ppName = &(*ppName)->pNext;
  76. return ppName;
  77. } // _FindName()
  78. // HANDLE CreateThread(NULL, 0, Addr, pParam, NULL, ThreadId);
  79. // BOOL PostMessage(hWnd, wMsg, wParam, lParam);
  80. void CallGetHostByName(DWORD Name) {
  81. GetNames **ppName, *pName = (GetNames *)Name;
  82. HOSTENT *pHostent;
  83. #if 0
  84. FULL_HOSTENT *pFull;
  85. int cLen, i;
  86. char *p;
  87. #endif
  88. DWORD lParam;
  89. EnterCriticalSection(&v_NameListCS);
  90. // put it in list of pending items
  91. pName->pNext = v_pNameList;
  92. v_pNameList = pName;
  93. LeaveCriticalSection(&v_NameListCS);
  94. pHostent = gethostbyname(pName->pName);
  95. DEBUGMSG(ZONE_HNAME, (TEXT("gethostbyname returned %x\r\n"), pHostent));
  96. // take this task out of the pending items list
  97. EnterCriticalSection(&v_NameListCS);
  98. ppName = _FindName(pName->hThread);
  99. ASSERT(*ppName);
  100. ASSERT(*ppName == pName);
  101. *ppName = pName->pNext;
  102. pName->pNext = NULL;
  103. LeaveCriticalSection(&v_NameListCS);
  104. if (pName->Status != 0xffffffff) {
  105. if (pHostent) {
  106. #if 0
  107. lParam = 0;
  108. pFull = (FULL_HOSTENT *)pName->pBuf;
  109. memcpy(pFull, pHostent, sizeof(FULL_HOSTENT));
  110. // now change the pointers to point to the correct places
  111. pFull->hostent.h_name = pFull->hostbuf;
  112. cLen = strlen(pFull->hostbuf) + 1;
  113. p = pFull->hostbuf + cLen;
  114. // do the aliases
  115. pFull->hostent.h_aliases = pFull->host_aliases;
  116. i = 0;
  117. while (pHostent->h_aliases[i]) {
  118. p += strlen(pHostent->h_aliases[i]) + 1;
  119. pFull->hostent.h_aliases[i++] = p;
  120. }
  121. // h_addrtype & h_length should have been copied with memcpy
  122. // do the h_addr_list
  123. pFull->hostent.h_addr_list = pFull->h_addr_ptrs;
  124. while(pHostent->h_addr_list[i]) {
  125. pFull->h_adddr_ptrs[i] =
  126. }
  127. p = pFull->hostaddr;
  128. i = 0;
  129. while (pHostent->h_addr_list[i]) {
  130. pFull->h_addr_ptrs[i] = p;
  131. (int *)p = *(int *)pHostent->h_addr_list[i++];
  132. p += 4;
  133. }
  134. #endif
  135. lParam = CopyHostEnt(pHostent, (PHOSTENT)pName->pBuf,
  136. &pName->dwBufLen);
  137. lParam <<= 16;
  138. lParam += pName->dwBufLen;
  139. } else { // if (pHostent)
  140. // we must have some error condition
  141. lParam = GetLastError();
  142. lParam <<= 16;
  143. lParam += sizeof(FULL_HOSTENT);
  144. }
  145. // BUGBUG: we don't retry on failure
  146. PostMessage(pName->hWnd, pName->wMsg, (WPARAM)pName->hThread, lParam);
  147. } // if (pName->Status)
  148. LocalFree(pName->pName);
  149. LocalFree(pName);
  150. } // CallGetHostByName()
  151. HANDLE WSAAsyncGetHostByName(HWND hWnd, unsigned wMsg, const char FAR *name,
  152. char FAR * buf, int buflen) {
  153. HANDLE hThread;
  154. DWORD ThreadId;
  155. GetNames *pName;
  156. DWORD Status = 0;
  157. int cc;
  158. if (buflen < sizeof(HOSTENT)) {
  159. Status = WSAENOBUFS;
  160. } else if (pName = LocalAlloc(LPTR, sizeof(*pName))) {
  161. pName->hWnd = hWnd;
  162. pName->wMsg = wMsg;
  163. pName->pBuf = buf;
  164. pName->dwBufLen = (DWORD)buflen;
  165. cc = strlen(name) + 1;
  166. if (pName->pName = LocalAlloc(LPTR, cc)) {
  167. memcpy(pName->pName, name, cc);
  168. pName->Status = 0;
  169. if (!v_fNameListInit) {
  170. InitializeCriticalSection(&v_NameListCS);
  171. v_fNameListInit = TRUE;
  172. }
  173. EnterCriticalSection(&v_NameListCS);
  174. pName->hThread = hThread = CreateThread(NULL, 0,
  175. (LPTHREAD_START_ROUTINE)CallGetHostByName, pName, 0, &ThreadId);
  176. LeaveCriticalSection(&v_NameListCS);
  177. CloseHandle(hThread);
  178. } else {
  179. LocalFree(pName);
  180. Status = WSAENOBUFS;
  181. }
  182. } else {
  183. Status = WSAENOBUFS;
  184. }
  185. if (Status) {
  186. SetLastError(Status);
  187. return (HANDLE)0;
  188. } else
  189. return (HANDLE)hThread;
  190. } // WSAASyncGetHostByName()
  191. int WSACancelAsyncRequest (HANDLE hAsyncTaskHandle) {
  192. GetNames **ppName;
  193. int Status;
  194. EnterCriticalSection(&v_NameListCS);
  195. ppName = _FindName(hAsyncTaskHandle);
  196. if (*ppName) {
  197. (*ppName)->Status = 0xffffffff;
  198. LeaveCriticalSection(&v_NameListCS);
  199. Status = 0;
  200. } else {
  201. LeaveCriticalSection(&v_NameListCS);
  202. Status = SOCKET_ERROR;
  203. SetLastError(WSAEINVAL);
  204. }
  205. return Status;
  206. } // WSACancelAsyncRequest()
  207. typedef int (*WSRecvFn)(SOCKET, char *, int, int);
  208. typedef int (*WSSendFn)(SOCKET, const char *, int, int);
  209. typedef int (*WSCloseFn)(SOCKET);
  210. WSRecvFn v_pRecv;
  211. WSSendFn v_pSend;
  212. WSCloseFn v_pClose;
  213. SOCKADDR_IN SockAddr;
  214. #ifndef IP_LOOPBACK
  215. #define IP_LOOPBACK 0x100007f
  216. #endif
  217. static fd_set ReadSet, WriteSet, ExcSet;
  218. static int v_fDone;
  219. static SOCKET v_Sock= INVALID_SOCKET;
  220. static SOCKET v_WakeSock;
  221. static SOCKET v_SendSock;
  222. static int v_SelEvents;
  223. static int v_Disabled;
  224. static HWND v_hWnd;
  225. static int v_wMsg;
  226. static int v_fAlready; // implicitly set to FALSE
  227. CRITICAL_SECTION v_EventCS;
  228. void SelectWorker(DWORD Sock);
  229. int WSAAsyncSelect (SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent) {
  230. static int fInit = FALSE;
  231. HINSTANCE hinst;
  232. HANDLE hThread;
  233. DWORD ThreadId;
  234. int True = 1;
  235. int len;
  236. if (! fInit) {
  237. fInit = TRUE;
  238. InitializeCriticalSection(&v_EventCS);
  239. if (hinst = LoadLibrary(TEXT("winsock.dll"))) {
  240. v_pRecv = (WSRecvFn)GetProcAddressW(hinst, TEXT("recv"));
  241. v_pSend = (WSSendFn)GetProcAddressW(hinst, TEXT("send"));
  242. v_pClose = (WSCloseFn)GetProcAddressW(hinst, TEXT("closesocket"));
  243. if (! (v_pRecv && v_pSend && v_pClose)) {
  244. DEBUGMSG(ZONE_WARN | ZONE_ERROR,
  245. (TEXT("Couldn't get ProcAddr of winsock recv/send\r\n")));
  246. SetLastError(WSAENOBUFS);
  247. return SOCKET_ERROR;
  248. }
  249. } else {
  250. DEBUGMSG(ZONE_WARN | ZONE_ERROR,
  251. (TEXT("Couldn't LoadLibrary winsock.dll\r\n")));
  252. SetLastError(WSAENOBUFS);
  253. return SOCKET_ERROR;
  254. }
  255. // now WakeSock and SendSock initialized at init time only
  256. v_WakeSock = socket(AF_INET, SOCK_DGRAM, 0);
  257. if (INVALID_SOCKET == v_WakeSock) {
  258. DEBUGMSG(ZONE_WARN|ZONE_ERROR,
  259. (TEXT("Can't create dgram socket\r\n")));
  260. SetLastError(WSAENOBUFS);
  261. return SOCKET_ERROR;
  262. }
  263. memset ((char *)&SockAddr, 0, sizeof(SockAddr));
  264. SockAddr.sin_family = AF_INET;
  265. SockAddr.sin_port = 0;
  266. SockAddr.sin_addr.S_un.S_addr = IP_LOOPBACK;
  267. if (SOCKET_ERROR == bind(v_WakeSock, (SOCKADDR *)&SockAddr,
  268. sizeof(SockAddr))) {
  269. DEBUGMSG(ZONE_WARN|ZONE_ERROR, (TEXT("Can't bind WakeSock\r\n")));
  270. return SOCKET_ERROR;
  271. }
  272. v_SendSock = socket(AF_INET, SOCK_DGRAM, 0);
  273. if (INVALID_SOCKET == v_SendSock) {
  274. DEBUGMSG(ZONE_WARN|ZONE_ERROR,
  275. (TEXT("Can't create send socket\r\n")));
  276. v_pClose(v_WakeSock);
  277. SetLastError(WSAENOBUFS);
  278. return SOCKET_ERROR;
  279. }
  280. len = sizeof(SockAddr);
  281. getsockname (v_WakeSock, (SOCKADDR *)&SockAddr, &len);
  282. connect(v_SendSock, (SOCKADDR *)&SockAddr, sizeof(SockAddr));
  283. } // if (! fInit)
  284. EnterCriticalSection(&v_EventCS);
  285. if (! lEvent) {
  286. v_fDone = TRUE;
  287. LeaveCriticalSection(&v_EventCS);
  288. return 0;
  289. }
  290. if (v_fAlready) {
  291. LeaveCriticalSection(&v_EventCS);
  292. return 0;
  293. } else {
  294. v_fAlready = TRUE;
  295. v_fDone = FALSE;
  296. v_hWnd = hWnd;
  297. v_wMsg = wMsg;
  298. v_SelEvents = lEvent;
  299. ASSERT(INVALID_SOCKET == v_Sock);
  300. v_Sock = s;
  301. v_Disabled = 0;
  302. LeaveCriticalSection(&v_EventCS);
  303. // set socket to non-blocking
  304. if (SOCKET_ERROR == ioctlsocket(s, FIONBIO, &True)) {
  305. DEBUGMSG(ZONE_WARN, (TEXT("ioctlsocket FIONBIO failed w/ %d\r\n"),
  306. GetLastError()));
  307. }
  308. hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SelectWorker,
  309. (void *)s, 0, &ThreadId);
  310. CloseHandle(hThread);
  311. }
  312. return 0;
  313. }
  314. void SelectWorker(DWORD Sock) {
  315. SOCKET s = (SOCKET) Sock;
  316. char c;
  317. DWORD lParam = 0;
  318. int Status;
  319. #ifdef OS_WINCE
  320. TIMEVAL tv = {0, 25000};
  321. #endif // OS_WINCE
  322. while (2) {
  323. FD_ZERO(&ReadSet);
  324. FD_ZERO(&WriteSet);
  325. FD_ZERO(&ExcSet);
  326. if (INVALID_SOCKET != v_WakeSock) {
  327. FD_SET(v_WakeSock, &ReadSet);
  328. }
  329. EnterCriticalSection(&v_EventCS);
  330. if (v_fDone) { // do this here b/c of CS
  331. v_fAlready = FALSE;
  332. // LeaveCriticalSection(&v_EventCS);
  333. break;
  334. }
  335. if (v_SelEvents & ~v_Disabled & (FD_WRITE | FD_CONNECT)) {
  336. FD_SET(s, &WriteSet);
  337. DEBUGMSG(ZONE_MSG, (TEXT("W\r\n")));
  338. }
  339. if (v_SelEvents & ~v_Disabled & FD_READ) {
  340. FD_SET(s, &ReadSet);
  341. DEBUGMSG(ZONE_MSG, (TEXT("R\r\n")));
  342. }
  343. //FD_SET(s, &ExcSet);
  344. LeaveCriticalSection(&v_EventCS);
  345. DEBUGMSG(ZONE_SELECT, (TEXT("calling select\r\n")));
  346. #ifdef OS_WINCE
  347. /* When select(...) is called with a NULL timeval parameter,
  348. it does not return after closesocket(...) is called on
  349. that socket. To work around that behavior, use a time-
  350. out on the call to select(...) (and take advantage of
  351. the while(2) wrapping this code-block. */
  352. // This was only made for HPCs, WBT was always fine using the old way,
  353. // so we're going to keep it the same.
  354. if (g_CEConfig != CE_CONFIG_WBT)
  355. {
  356. Status = select(0, &ReadSet, &WriteSet, NULL, &tv);
  357. }
  358. else
  359. {
  360. Status = select(0, &ReadSet, &WriteSet, NULL, NULL);
  361. }
  362. #else // OS_WINCE
  363. Status = select(0, &ReadSet, &WriteSet, NULL, NULL);
  364. #endif // OS_WINCE
  365. if (SOCKET_ERROR == Status) {
  366. //v_fDone = TRUE;
  367. Status = GetLastError();
  368. DEBUGMSG(ZONE_WARN|ZONE_SELECT,
  369. (TEXT("Select returned error: %d \r\n"), Status));
  370. } else {
  371. if (FD_ISSET(v_WakeSock, &ReadSet)) {
  372. v_pRecv(v_WakeSock, &c, 1, 0);
  373. }
  374. EnterCriticalSection(&v_EventCS);
  375. if (FD_ISSET(s, &WriteSet)) {
  376. // we need to report connect events only once
  377. if (v_SelEvents & ~v_Disabled & FD_CONNECT) {
  378. v_Disabled |= FD_CONNECT;
  379. lParam = FD_CONNECT;
  380. DEBUGMSG(ZONE_MSG, (TEXT("p-C\r\n")));
  381. PostMessage(v_hWnd, v_wMsg, (WPARAM)s, lParam);
  382. }
  383. if (v_SelEvents & ~v_Disabled & FD_WRITE) {
  384. v_Disabled |= FD_WRITE;
  385. lParam = FD_WRITE;
  386. DEBUGMSG(ZONE_MSG, (TEXT("p-W\r\n")));
  387. PostMessage(v_hWnd, v_wMsg, (WPARAM)s, lParam);
  388. }
  389. }
  390. if (FD_ISSET(s, &ReadSet)) {
  391. v_Disabled |= FD_READ;
  392. lParam = FD_READ;
  393. DEBUGMSG(ZONE_MSG, (TEXT("p-R\r\n")));
  394. PostMessage(v_hWnd, v_wMsg, (WPARAM)s, lParam);
  395. }
  396. if (FD_ISSET(s, &ExcSet)) {
  397. DEBUGMSG(ZONE_WARN, (TEXT("Selects ExcSet is set!!\r\n")));
  398. }
  399. LeaveCriticalSection(&v_EventCS);
  400. } // else SOCKET_ERROR == Status
  401. }
  402. // note we have the CS here!!!
  403. v_Sock = INVALID_SOCKET;
  404. v_hWnd = NULL;
  405. LeaveCriticalSection(&v_EventCS);
  406. return;
  407. } // SelectWorker()
  408. int recv(SOCKET s, char *buf, int len, int flags) {
  409. char c = (char)7;
  410. int Status;
  411. DEBUGMSG(ZONE_RECV, (TEXT("+recv\r\n")));
  412. Status = v_pRecv(s, buf, len, flags);
  413. EnterCriticalSection(&v_EventCS);
  414. if (v_Sock != INVALID_SOCKET && v_Sock == s) {
  415. // BUGBUG: should we check for errors as well?
  416. if (! Status) { // recv'd 0 bytes
  417. DEBUGMSG(ZONE_MSG, (TEXT("p-Close\r\n")));
  418. PostMessage(v_hWnd, v_wMsg, (WPARAM)s, FD_CLOSE);
  419. // after this we don't want to re-enable FD_READ's
  420. } else if (v_Disabled & FD_READ) {
  421. v_Disabled &= ~FD_READ;
  422. v_pSend(v_SendSock, &c, 1, 0);
  423. }
  424. }
  425. LeaveCriticalSection(&v_EventCS);
  426. DEBUGMSG(ZONE_RECV, (TEXT("-recv\r\n")));
  427. return Status;
  428. } // recv
  429. int send(SOCKET s, const char *buf, int len, int flags) {
  430. char c = (char)8;
  431. int Status;
  432. DEBUGMSG(ZONE_SEND, (TEXT("+send\r\n")));
  433. Status = v_pSend(s, buf, len, flags);
  434. EnterCriticalSection(&v_EventCS);
  435. if (v_Sock != INVALID_SOCKET && v_Sock == s) {
  436. // BUGBUG: should we check for errors??
  437. if (v_Disabled & FD_WRITE) {
  438. v_Disabled &= ~FD_WRITE;
  439. v_pSend(v_SendSock, &c, 1, 0);
  440. }
  441. }
  442. LeaveCriticalSection(&v_EventCS);
  443. DEBUGMSG(ZONE_SEND, (TEXT("-send\r\n")));
  444. return Status;
  445. } // send()
  446. int closesocket(SOCKET s) {
  447. int Status;
  448. DEBUGMSG(ZONE_CLOSE, (TEXT("+close\r\n")));
  449. Status = v_pClose(s);
  450. EnterCriticalSection(&v_EventCS);
  451. if (v_Sock != INVALID_SOCKET && v_Sock == s) {
  452. v_fDone = TRUE;
  453. }
  454. LeaveCriticalSection(&v_EventCS);
  455. DEBUGMSG(ZONE_CLOSE, (TEXT("-close\r\n")));
  456. return Status;
  457. } // closesocket()
  458. BOOL __stdcall
  459. dllentry (
  460. HANDLE hinstDLL,
  461. DWORD Op,
  462. LPVOID lpvReserved
  463. )
  464. {
  465. switch (Op) {
  466. case DLL_PROCESS_ATTACH :
  467. DEBUGREGISTER(hinstDLL);
  468. DEBUGMSG (ZONE_INIT, (TEXT(" CXPORT:dllentry ProcessAttach\r\n")));
  469. break;
  470. case DLL_PROCESS_DETACH :
  471. break;
  472. default :
  473. break;
  474. }
  475. return TRUE;
  476. }
  477. DWORD
  478. CopyHostEnt(
  479. PHOSTENT lpWinsockHostEnt,
  480. PHOSTENT lpHostEnt,
  481. LPDWORD lpdwHostEntBufferSize
  482. )
  483. /*++
  484. Arguments:
  485. Return Value:
  486. Windows Error Code.
  487. --*/
  488. {
  489. DWORD dwSize;
  490. LPSTR *lpAliasNames;
  491. LPSTR *lpDestAliasNames;
  492. LPSTR *lpAddrList;
  493. LPSTR *lpDestAddrList;
  494. LPBYTE lpNextVariable;
  495. LPBYTE lpEndBuffer;
  496. DWORD dwNumAliasNames = 0;
  497. DWORD dwNumAddresses = 0;
  498. DWORD dwDnsNameLen;
  499. //
  500. // compute the size required.
  501. //
  502. dwSize = sizeof(HOSTENT);
  503. dwDnsNameLen =
  504. ROUND_UP_COUNT(
  505. (strlen(lpWinsockHostEnt->h_name) + sizeof(CHAR)),
  506. ALIGN_DWORD );
  507. dwSize += dwDnsNameLen;
  508. lpAliasNames = lpWinsockHostEnt->h_aliases;
  509. while( *lpAliasNames != NULL ) {
  510. dwSize += ROUND_UP_COUNT(
  511. (strlen(*lpAliasNames) + sizeof(CHAR)),
  512. ALIGN_DWORD );
  513. dwSize += sizeof(LPSTR);
  514. dwNumAliasNames++;
  515. lpAliasNames++;
  516. }
  517. dwSize += sizeof(LPSTR);
  518. lpAddrList = lpWinsockHostEnt->h_addr_list;
  519. while( *lpAddrList != NULL ) {
  520. dwSize += sizeof(DWORD);
  521. dwSize += sizeof(LPSTR);
  522. dwNumAddresses++;
  523. lpAddrList++;
  524. }
  525. dwSize += sizeof(LPSTR);
  526. if( dwSize > *lpdwHostEntBufferSize ) {
  527. *lpdwHostEntBufferSize = dwSize;
  528. return( WSAENOBUFS );
  529. }
  530. //
  531. // copy data.
  532. //
  533. lpNextVariable = (LPBYTE)lpHostEnt + sizeof(HOSTENT);
  534. lpEndBuffer = (LPBYTE)lpHostEnt + dwSize;
  535. //
  536. // copy fixed part.
  537. //
  538. lpHostEnt->h_addrtype = lpWinsockHostEnt->h_addrtype;
  539. lpHostEnt->h_length = lpWinsockHostEnt->h_length;
  540. //
  541. // copy variable parts.
  542. //
  543. lpHostEnt->h_name = (LPSTR)lpNextVariable;
  544. strcpy( lpHostEnt->h_name, lpWinsockHostEnt->h_name );
  545. lpNextVariable += dwDnsNameLen;
  546. ProxyDbgAssert( lpNextVariable < lpEndBuffer);
  547. lpHostEnt->h_aliases = (LPSTR *)lpNextVariable;
  548. lpNextVariable += (dwNumAliasNames + 1) * sizeof(LPSTR);
  549. ProxyDbgAssert( lpNextVariable < lpEndBuffer);
  550. lpAliasNames = lpWinsockHostEnt->h_aliases;
  551. lpDestAliasNames = lpHostEnt->h_aliases;
  552. while( *lpAliasNames != NULL ) {
  553. *lpDestAliasNames = (LPSTR)lpNextVariable;
  554. strcpy( *lpDestAliasNames, *lpAliasNames );
  555. lpNextVariable += ROUND_UP_COUNT(
  556. (strlen(*lpAliasNames) + sizeof(CHAR)),
  557. ALIGN_DWORD );
  558. ProxyDbgAssert( lpNextVariable < lpEndBuffer);
  559. lpDestAliasNames++;
  560. lpAliasNames++;
  561. }
  562. *lpDestAliasNames = NULL;
  563. lpHostEnt->h_addr_list = (LPSTR *)lpNextVariable;
  564. lpNextVariable += (dwNumAddresses + 1) * sizeof(LPSTR);
  565. ProxyDbgAssert( lpNextVariable < lpEndBuffer);
  566. lpAddrList = lpWinsockHostEnt->h_addr_list;
  567. lpDestAddrList = lpHostEnt->h_addr_list;
  568. while( *lpAddrList != NULL ) {
  569. *lpDestAddrList = (LPSTR)lpNextVariable;
  570. *(LPDWORD)(*lpDestAddrList) = *(LPDWORD)(*lpAddrList);
  571. lpNextVariable += sizeof(DWORD);
  572. ProxyDbgAssert( lpNextVariable <= lpEndBuffer);
  573. lpDestAddrList++;
  574. lpAddrList++;
  575. }
  576. *lpDestAddrList = NULL;
  577. return( ERROR_SUCCESS );
  578. }
  579. // ----------------------------------------------------------------
  580. //
  581. // The Windows Sockets WSAAsyncGetHostByName function gets host
  582. // information corresponding to a host name asynchronously.
  583. //
  584. // HANDLE WSAAsyncGetHostByName ( HWND hWnd, unsigned int wMsg, const
  585. // char FAR * name, char FAR * buf, int buflen );
  586. //
  587. // Parameters
  588. //
  589. // hWnd
  590. //
  591. // [in] The handle of the window that will receive a message when the
  592. // asynchronous request completes.
  593. //
  594. // wMsg
  595. //
  596. // [in] The message to be received when the asynchronous request
  597. // completes.
  598. //
  599. // name
  600. //
  601. // [in] A pointer to the null-terminated name of the host.
  602. //
  603. // buf
  604. //
  605. // [out] A pointer to the data area to receive the HOSTENT data. It must
  606. // be larger than the size of a HOSTENT structure because the supplied
  607. // data area is used by Windows Sockets to contain not only a HOSTENT
  608. // structure but any and all of the data referenced by members of the
  609. // HOSTENT structure. A buffer of MAXGETHOSTSTRUCT bytes is recommended.
  610. //
  611. // buflen
  612. //
  613. // [in] The size of data area the buf parameter.
  614. //
  615. // Remarks
  616. //
  617. // This function is an asynchronous version of gethostbyname, and is
  618. // used to retrieve host name and address information corresponding to a
  619. // host name. Windows Sockets initiates the operation and returns to the
  620. // caller immediately, passing back an opaque "asynchronous task handle"
  621. // that whichthe application can use to identify the operation. When the
  622. // operation is completed, the results (if any) are copied into the
  623. // buffer provided by the caller and a message is sent to the
  624. // application's window.
  625. //
  626. // When the asynchronous operation is complete the application's window
  627. // hWnd receives message wMsg. The wParam parameter contains the
  628. // asynchronous task handle as returned by the original function call.
  629. // The high 16 bits of lParam contain any error code. The error code can
  630. // be any error as defined in WINSOCK2.H. An error code of zero
  631. // indicates successful completion of the asynchronous operation. On
  632. // successful completion, the buffer supplied to the original function
  633. // call contains a HOSTENT structure. To access the elements of this
  634. // structure, the original buffer address should be cast to a HOSTENT
  635. // structure pointer and accessed as appropriate.
  636. //
  637. // If the error code is WSAENOBUFS, the size of the buffer specified by
  638. // buflen in the original call was too small to contain all the
  639. // resulting information. In this case, the low 16 bits of lParam
  640. // contain the size of buffer required to supply all the requisite
  641. // information. If the application decides that the partial data is
  642. // inadequate, it can reissue the WSAAsyncGetHostByAddr function call
  643. // with a buffer large enough to receive all the desired information
  644. // (that is, no smaller than the low 16 bits of lParam).
  645. //
  646. // The buffer supplied to this function is used by Windows Sockets to
  647. // construct a HOSTENT structure together with the contents of data
  648. // areas referenced by members of the same HOSTENT structure. To avoid
  649. // the WSAENOBUFS error, the application should provide a buffer of at
  650. // least MAXGETHOSTSTRUCT bytes (as defined in WINSOCK2.H).
  651. //
  652. // The error code and buffer length should be extracted from the lParam
  653. // using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in
  654. // WINSOCK2.H as:
  655. //
  656. // #define WSAGETASYNCERROR(lParam) HIWORD(lParam) #define
  657. // WSAGETASYNCBUFLEN(lParam) LOWORD(lParam) The use of these macros will
  658. // maximize the portability of the source code for the application.
  659. //
  660. // WSAAsyncGetHostByName is guaranteed to resolve the string returned by
  661. // a successful call to gethostname.
  662. //
  663. // Return Values
  664. //
  665. // The return value specifies whether or not the asynchronous operation
  666. // was successfully initiated. Note that it does not imply success or
  667. // failure of the operation itself.
  668. //
  669. // If the operation was successfully initiated, WSAAsyncGetHostByName
  670. // returns a nonzero value of type HANDLE that is the asynchronous task
  671. // handle (not to be confused with a Windows HTASK) for the request.
  672. // This value can be used in two ways. It can be used to cancel the
  673. // operation using WSACancelAsyncRequest. It can also be used to match
  674. // up asynchronous operations and completion messages by examining the
  675. // wParam message parameter.
  676. //
  677. // If the asynchronous operation could not be initiated,
  678. // WSAAsyncGetHostByName returns a zero value, and a specific error
  679. // number can be retrieved by calling WSAGetLastError.
  680. //
  681. // Error Codes
  682. //
  683. // The following error codes can be set when an application window
  684. // receives a message. As described above, they can be extracted from
  685. // the lParam in the reply message using the WSAGETASYNCERROR macro.
  686. //
  687. // WSAENETDOWN The network subsystem has failed.
  688. //
  689. // WSAENOBUFS Insufficient buffer space is available.
  690. //
  691. // WSAEFAULT name or buf is not in a valid part of the process address
  692. // space.
  693. //
  694. // WSAHOST_NOT_FOUND Authoritative Answer Host not found.
  695. //
  696. // WSATRY_AGAIN Non-Authoritative Host not found, or SERVERFAIL.
  697. //
  698. // WSANO_RECOVERY Nonrecoverable errors, FORMERR, REFUSED, NOTIMP.
  699. //
  700. // WSANO_DATA Valid name, no data record of requested type.
  701. //
  702. // The following errors can occur at the time of the function call, and
  703. // indicate that the asynchronous operation could not be initiated.
  704. //
  705. // WSANOTINITIALISED A successful WSAStartup must occur before using
  706. // this function.
  707. //
  708. // WSAENETDOWN The network subsystem has failed.
  709. //
  710. // WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or
  711. // the service provider is still processing a callback function.
  712. //
  713. // WSAEWOULDBLOCK The asynchronous operation cannot be scheduled at this
  714. // time due to resource or other constraints within the Windows Sockets
  715. // implementation.
  716. //
  717. // ----------------------------------------------------------------
  718. //
  719. // ----------------------------------------------------------------
  720. //
  721. // The Windows Sockets WSACancelAsyncRequest function cancels an
  722. // incomplete asynchronous operation.
  723. //
  724. // int WSACancelAsyncRequest (
  725. // HANDLE hAsyncTaskHandle
  726. // );
  727. //
  728. // Parameters
  729. // hAsyncTaskHandle
  730. // [in] Specifies the asynchronous operation to be canceled.
  731. //
  732. // Remarks
  733. // The WSACancelAsyncRequest function is used to cancel an asynchronous
  734. // operation that was initiated by one of the WSAAsyncGetXByY functions
  735. // such as WSAAsyncGetHostByName. The operation to be canceled is
  736. // identified by the hAsyncTaskHandle parameter, which should be set to
  737. // the asynchronous task handle as returned by the initiating
  738. // WSAAsyncGetXByY function.
  739. //
  740. // Return Values
  741. // The value returned by WSACancelAsyncRequest is zero if the operation
  742. // was successfully canceled. Otherwise, the value SOCKET_ERROR is
  743. // returned, and a specific error number may be retrieved by calling
  744. // WSAGetLastError.
  745. //
  746. // Comments
  747. // An attempt to cancel an existing asynchronous WSAAsyncGetXByY
  748. // operation can fail with an error code of WSAEALREADY for two reasons.
  749. // First, the original operation has already completed and the
  750. // application has dealt with the resultant message. Second, the
  751. // original operation has already completed but the resultant message is
  752. // still waiting in the application window queue.
  753. //
  754. // Note
  755. // It is unclear whether the application can usefully distinguish
  756. // between WSAEINVAL and WSAEALREADY, since in both cases the error
  757. // indicates that there is no asynchronous operation in progress with
  758. // the indicated handle. [Trivial exception: zero is always an invalid
  759. // asynchronous task handle.] The Windows Sockets specification does not
  760. // prescribe how a conformant Windows Sockets provider should
  761. // distinguish between the two cases. For maximum portability, a Windows
  762. // Sockets application should treat the two errors as equivalent.
  763. //
  764. //
  765. // Error Codes
  766. // WSANOTINITIALISED A successful WSAStartup must occur before using
  767. // this function.
  768. //
  769. // WSAENETDOWN The network subsystem has failed.
  770. //
  771. // WSAEINVAL Indicates that the specified asynchronous task handle was
  772. // invalid
  773. //
  774. // WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or
  775. // the service provider is still processing a callback function.
  776. //
  777. // WSAEALREADY The asynchronous routine being canceled has already
  778. // completed.
  779. //
  780. // ----------------------------------------------------------------
  781. // ----------------------------------------------------------------
  782. //
  783. //
  784. // The Windows Sockets WSAAsyncSelect function requests Windows message-based notification of network events for a socket.
  785. //
  786. // int WSAAsyncSelect (
  787. // SOCKET s,
  788. // HWND hWnd,
  789. // unsigned int wMsg,
  790. // long lEvent
  791. // );
  792. //
  793. // Parameters
  794. // s
  795. // [in] A descriptor identifying the socket for which event notification
  796. // is required.
  797. //
  798. // hWnd
  799. // [in] A handle identifying the window that should receive a message
  800. // when a network event occurs.
  801. //
  802. // wMsg
  803. // [in] The message to be received when a network event occurs.
  804. //
  805. // lEvent
  806. // [in] A bitmask that specifies a combination of network events in
  807. // which the application is interested.
  808. //
  809. // Remarks
  810. // This function is used to request that the Windows Sockets DLL should
  811. // send a message to the window hWnd whenever it detects any of the
  812. // network events specified by the lEvent parameter. The message that
  813. // should be sent is specified by the wMsg parameter. The socket for
  814. // which notification is required is identified by s.
  815. //
  816. // This function automatically sets socket s to nonblocking mode,
  817. // regardless of the value of lEvent. See ioctlsocket about how to set
  818. // the nonoverlapped socket back to blocking mode.
  819. //
  820. // The lEvent parameter is constructed by or'ing any of the values
  821. // specified in the following list.
  822. //
  823. // Value Meaning
  824. // FD_READ Want to receive notification of readiness for reading
  825. //
  826. // FD_WRITE Want to receive notification of readiness for writing
  827. //
  828. // FD_OOB Want to receive notification of the arrival of
  829. // out-of-band data
  830. //
  831. // FD_ACCEPT Want to receive notification of incoming connections
  832. //
  833. // FD_CONNECT Want to receive notification of completed connection
  834. //
  835. // FD_CLOSE Want to receive notification of socket closure
  836. //
  837. // FD_QOS Want to receive notification of socket Quality of Service
  838. // (QOS) changes
  839. //
  840. // FD_GROUP_QOS Want to receive notification of socket group Quality of
  841. // Service (QOS) changes
  842. //
  843. // Issuing a WSAAsyncSelect for a socket cancels any previous
  844. // WSAAsyncSelect or WSAEventSelect for the same socket. For example, to
  845. // receive notification for both reading and writing, the application
  846. // must call WSAAsyncSelect with both FD_READ and FD_WRITE, as follows:
  847. //
  848. // rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
  849. //
  850. // It is not possible to specify different messages for different
  851. // events. The following code will not work; the second call will cancel
  852. // the effects of the first, and only FD_WRITE events will be reported
  853. // with message wMsg2:
  854. //
  855. // rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
  856. // rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);
  857. //
  858. // To cancel all notification (that is, to indicate that Windows Sockets
  859. // should send no further messages related to network events on the
  860. // socket) lEvent should be set to zero.
  861. //
  862. // rc = WSAAsyncSelect(s, hWnd, 0, 0);
  863. //
  864. // Although in this instance WSAAsyncSelect immediately disables event
  865. // message posting for the socket, it is possible that messages can be
  866. // waiting in the application's message queue. The application must
  867. // therefore be prepared to receive network event messages even after
  868. // cancellation. Closing a socket with closesocket also cancels
  869. // WSAAsyncSelect message sending, but the same caveat about messages in
  870. // the queue prior to the closesocket still applies.
  871. //
  872. // Since an accept'ed socket has the same properties as the listening
  873. // socket used to accept it, any WSAAsyncSelect events set for the
  874. // listening socket apply to the accepted socket. For example, if a
  875. // listening socket has WSAAsyncSelect events FD_ACCEPT, FD_READ, and
  876. // FD_WRITE, then any socket accepted on that listening socket will also
  877. // have FD_ACCEPT, FD_READ, and FD_WRITE events with the same wMsg value
  878. // used for messages. If a different wMsg or events are desired, the
  879. // application should call WSAAsyncSelect, passing the accepted socket
  880. // and the desired new information.
  881. //
  882. // When one of the nominated network events occurs on the specified
  883. // socket s, the application's window hWnd receives message wMsg. The
  884. // wParam parameter identifies the socket on which a network event has
  885. // occurred. The low word of lParam specifies the network event that has
  886. // occurred. The high word of lParam contains any error code. The error
  887. // code be any error as defined in WINSOCK2.H. Note Upon receipt of an
  888. // event notification message the WSAGetLastError function cannot be
  889. // used to check the error value, because the error value returned can
  890. // differ from the value in the high word of lParam.
  891. //
  892. // The error and event codes can be extracted from the lParam using the
  893. // macros WSAGETSELECTERROR and WSAGETSELECTEVENT, defined in WINSOCK2.H
  894. // as:
  895. //
  896. // #define WSAGETSELECTERROR(lParam) HIWORD(lParam)
  897. // #define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
  898. //
  899. // The use of these macros will maximize the portability of the source
  900. // code for the application.
  901. //
  902. // The possible network event codes that can be returned are as follows:
  903. //
  904. // Value Meaning
  905. // FD_READ Socket s ready for reading
  906. //
  907. // FD_WRITE Socket s ready for writing
  908. //
  909. // FD_OOB Out-of-band data ready for reading on socket s
  910. //
  911. // FD_ACCEPT Socket s ready for accepting a new incoming connection
  912. //
  913. // FD_CONNECT Connection initiated on socket s completed
  914. //
  915. // FD_CLOSE Connection identified by socket s has been closed
  916. //
  917. // FD_QOS Quality of Service associated with socket s has changed
  918. //
  919. // FD_GROUP_QOS Quality of Service associated with the socket group to
  920. // which s belongs has changed
  921. //
  922. // Return Values
  923. //
  924. // The return value is zero if the application's declaration of interest
  925. // in the network event set was successful. Otherwise, the value
  926. // SOCKET_ERROR is returned, and a specific error number can be
  927. // retrieved by calling WSAGetLastError.
  928. //
  929. // Comments
  930. //
  931. // Although WSAAsyncSelect can be called with interest in multiple
  932. // events, the application window will receive a single message for each
  933. // network event.
  934. //
  935. // As in the case of the select function, WSAAsyncSelect will frequently
  936. // be used to determine when a data transfer operation (send or recv)
  937. // can be issued with the expectation of immediate success.
  938. // Nevertheless, a robust application must be prepared for the
  939. // possibility that it can receive a message and issue a Windows Sockets
  940. // 2 call that returns WSAEWOULDBLOCK immediately. For example, the
  941. // following sequence of events is possible:
  942. //
  943. // 1. data arrives on socket s; Windows Sockets 2 posts WSAAsyncSelect
  944. // message
  945. //
  946. // 2. application processes some other message
  947. //
  948. // 3. while processing, application issues an ioctlsocket(s,
  949. // FIONREAD...) and notices that there is data ready to be read
  950. //
  951. // 4. application issues a recv(s,...) to read the data
  952. //
  953. // 5. application loops to process next message, eventually reaching the
  954. // WSAAsyncSelect message indicating that data is ready to read
  955. //
  956. // 6. application issues recv(s,...), which fails with the error
  957. // WSAEWOULDBLOCK.
  958. //
  959. // Other sequences are possible.
  960. //
  961. // The Windows Sockets DLL will not continually flood an application
  962. // with messages for a particular network event. Having successfully
  963. // posted notification of a particular event to an application window,
  964. // no further message(s) for that network event will be posted to the
  965. // application window until the application makes the function call that
  966. // implicitly re-enables notification of that network event.
  967. //
  968. // Event Re-enabling function
  969. //
  970. // FD_READ recv, recvfrom, WSARecv, or WSARecvFrom
  971. //
  972. // FD_WRITE send, sendto, WSASend, or WSASendTo
  973. //
  974. // FD_OOB recv, recvfrom, WSARecv, or WSARecvFrom
  975. //
  976. // FD_ACCEPT accept or WSAAccept unless the error code is WSATRY_AGAIN
  977. // indicating that the condition function returned CF_DEFER
  978. //
  979. // FD_CONNECT NONE
  980. //
  981. // FD_CLOSE NONE
  982. //
  983. // FD_QOS WSAIoctl with command SIO_GET_QOS
  984. //
  985. // FD_GROUP_QOS WSAIoctl with command SIO_GET_GROUP_QOS
  986. //
  987. // Any call to the re-enabling routine, even one that fails, results in
  988. // re-enabling of message posting for the relevant event.
  989. //
  990. // For FD_READ, FD_OOB, and FD_ACCEPT events, message posting is
  991. // "level-triggered." This means that if the re-enabling routine is
  992. // called and the relevant condition is still met after the call, a
  993. // WSAAsyncSelect message is posted to the application. This allows an
  994. // application to be event-driven and not be concerned with the amount
  995. // of data that arrives at any one time. Consider the following sequence:
  996. //
  997. // 1. Network transport stack receives 100 bytes of data on socket s and
  998. // causes Windows Sockets 2 to post an FD_READ message.
  999. //
  1000. // 2. The application issues recv( s, buffptr, 50, 0) to read 50 bytes.
  1001. //
  1002. // 3. Another FD_READ message is posted since there is still data to be
  1003. // read.
  1004. //
  1005. // With these semantics, an application need not read all available data
  1006. // in response to an FD_READ message�a single recv in response to each
  1007. // FD_READ message is appropriate. If an application issues multiple
  1008. // recv calls in response to a single FD_READ, it can receive multiple
  1009. // FD_READ messages. Such an application may need to disable FD_READ
  1010. // messages before starting the recv calls by calling WSAAsyncSelect
  1011. // with the FD_READ event not set.
  1012. //
  1013. // The FD_QOS and FD_GROUP_QOS events are considered edge triggered. A
  1014. // message will be posted exactly once when a QOS change occurs. Further
  1015. // messages will not be forthcoming until either the provider detects a
  1016. // further change in QOS or the application renegotiates the QOS for the
  1017. // socket.
  1018. //
  1019. // If any event has already happened when the application calls
  1020. // WSAAsyncSelect or when the re-enabling function is called, then a
  1021. // message is posted as appropriate. For example, consider the following
  1022. // sequence:
  1023. //
  1024. // 1. an application calls listen,
  1025. //
  1026. // 2. a connect request is received but not yet accepted,
  1027. //
  1028. // 3. the application calls WSAAsyncSelect specifying that it wants to
  1029. // receive FD_ACCEPT messages for the socket. Due to the persistence of
  1030. // events, Windows Sockets 2 posts an FD_ACCEPT message immediately.
  1031. //
  1032. // The FD_WRITE event is handled slightly differently. An FD_WRITE
  1033. // message is posted when a socket is first connected with
  1034. // connect/WSAConnect (after FD_CONNECT, if also registered) or accepted
  1035. // with accept/WSAAccept, and then after a send operation fails with
  1036. // WSAEWOULDBLOCK and buffer space becomes available. Therefore, an
  1037. // application can assume that sends are possible starting from the
  1038. // first FD_WRITE message and lasting until a send returns
  1039. // WSAEWOULDBLOCK. After such a failure the application will be notified
  1040. // that sends are again possible with an FD_WRITE message.
  1041. //
  1042. // The FD_OOB event is used only when a socket is configured to receive
  1043. // out-of-band data separately. (See section Out-Of-Band data for a
  1044. // discussion of this topic.) If the socket is configured to receive
  1045. // out-of-band data in-line, the out-of-band (expedited) data is treated
  1046. // as normal data and the application should register an interest in,
  1047. // and will receive, FD_READ events, not FD_OOB events. An application
  1048. // may set or inspect the way in which out-of-band data is to be handled
  1049. // by using setsockopt or getsockopt for the SO_OOBINLINE option.
  1050. //
  1051. // The error code in an FD_CLOSE message indicates whether the socket
  1052. // close was graceful or abortive. If the error code is zero, then the
  1053. // close was graceful; if the error code is WSAECONNRESET, then the
  1054. // socket's virtual circuit was reset. This only applies to
  1055. // connection-oriented sockets such as SOCK_STREAM.
  1056. //
  1057. // The FD_CLOSE message is posted when a close indication is received
  1058. // for the virtual circuit corresponding to the socket. In TCP terms,
  1059. // this means that the FD_CLOSE is posted when the connection goes into
  1060. // the TIME WAIT or CLOSE WAIT states. This results from the remote end
  1061. // performing a shutdown on the send side or a closesocket. FD_CLOSE
  1062. // should only be posted after all data is read from a socket, but an
  1063. // application should check for remaining data upon receipt of FD_CLOSE
  1064. // to avoid any possibility of losing data.
  1065. //
  1066. // Please note your application will receive ONLY an FD_CLOSE message to
  1067. // indicate closure of a virtual circuit, and only when all the received
  1068. // data has been read if this is a graceful close. It will not receive
  1069. // an FD_READ message to indicate this condition.
  1070. //
  1071. // The FD_QOS or FD_GROUP_QOS message is posted when any field in the
  1072. // flow specification associated with socket s or the socket group that
  1073. // s belongs to has changed, respectively. Applications should use
  1074. // WSAIoctl with command SIO_GET_QOS or SIO_GET_GROUP_QOS to get the
  1075. // current QOS for socket s or for the socket group s belongs to,
  1076. // respectively.
  1077. //
  1078. // Here is a summary of events and conditions for each asynchronous
  1079. // notification message:
  1080. //
  1081. // FD_READ:
  1082. //
  1083. // 1. when WSAAsyncSelect called, if there is data currently available
  1084. // to receive,
  1085. //
  1086. // 2. when data arrives, if FD_READ not already posted,
  1087. //
  1088. // 3. after recv or recvfrom called (with or without MSG_PEEK), if data
  1089. // is still available to receive. Note when setsockopt SO_OOBINLINE is
  1090. // enabled "data" includes both normal data and out-of-band (OOB) data
  1091. // in the instances noted above. FD_WRITE:
  1092. //
  1093. // 1. when WSAAsyncSelect called, if a send or sendto is possible
  1094. //
  1095. // 2. after connect or accept called, when connection established
  1096. //
  1097. // 3. after send or sendto fail with WSAEWOULDBLOCK, when send or sendto
  1098. // are likely to succeed,
  1099. //
  1100. // 4. after bind on a datagram socket.
  1101. //
  1102. // FD_OOB: Only valid when setsockopt SO_OOBINLINE is disabled (default).
  1103. //
  1104. // 1. when WSAAsyncSelect called, if there is OOB data currently
  1105. // available to receive with the MSG_OOB flag,
  1106. //
  1107. // 2. when OOB data arrives, if FD_OOB not already posted,
  1108. //
  1109. // 3. after recv or recvfrom called with or without MSG_OOB flag, if OOB
  1110. // data is still available to receive.
  1111. //
  1112. // FD_ACCEPT:
  1113. //
  1114. // 1. when WSAAsyncSelect called, if there is currently a connection
  1115. // request available to accept,
  1116. //
  1117. // 2. when a connection request arrives, if FD_ACCEPT not already
  1118. // posted,
  1119. //
  1120. // 3. after accept called, if there is another connection request
  1121. // available to accept.
  1122. //
  1123. // FD_CONNECT:
  1124. //
  1125. // 1. when WSAAsyncSelect called, if there is currently a connection
  1126. // established,
  1127. //
  1128. // 2. after connect called, when connection is established (even when
  1129. // connect succeeds immediately, as is typical with a datagram socket)
  1130. //
  1131. // FD_CLOSE: Only valid on connection-oriented sockets (for example,
  1132. // SOCK_STREAM) 1. when WSAAsyncSelect called, if socket connection has
  1133. // been closed,
  1134. //
  1135. // 2. after remote system initiated graceful close, when no data
  1136. // currently available to receive (note: if data has been received and
  1137. // is waiting to be read when the remote system initiates a graceful
  1138. // close, the FD_CLOSE is not delivered until all pending data has been
  1139. // read),
  1140. //
  1141. // 3. after local system initiates graceful close with shutdown and
  1142. // remote system has responded with "End of Data" notification (for
  1143. // example, TCP FIN), when no data currently available to receive,
  1144. //
  1145. // 4. when remote system terminates connection (for example, sent TCP
  1146. // RST), and lParam will contain WSAECONNRESET error value.
  1147. //
  1148. //
  1149. // Note FD_CLOSE is not posted after closesocket is called. FD_QOS:
  1150. //
  1151. // 1. when WSAAsyncSelect called, if the QOS associated with the socket
  1152. // has been changed,
  1153. //
  1154. // 2. after WSAIoctl with SIO_GET_QOS called, when the QOS is changed.
  1155. //
  1156. // FD_GROUP_QOS:
  1157. //
  1158. // 1. when WSAAsyncSelect called, if the group QOS associated with the
  1159. // socket has been changed,
  1160. //
  1161. // 2. after WSAIoctl with SIO_GET_GROUP_QOS called, when the group QOS
  1162. // is changed. Error Codes
  1163. //
  1164. // WSANOTINITIALISED A successful WSAStartup must occur before using
  1165. // this function.
  1166. //
  1167. // WSAENETDOWN The network subsystem has failed.
  1168. //
  1169. // WSAEINVAL Indicates that one of the specified parameters was invalid
  1170. // such as the window handle not referring to an existing window, or the
  1171. // specified socket is in an invalid state.
  1172. //
  1173. // WSAEINPROGRESS A blocking Windows Sockets 1.1 call is in progress, or
  1174. // the service provider is still processing a callback function.
  1175. //
  1176. // WSAENOTSOCK The descriptor is not a socket. Additional error codes
  1177. // may be set when an application window receives a message. This error
  1178. // code is extracted from the lParam in the reply message using the
  1179. // WSAGETSELECTERROR macro. Possible error codes for each network event
  1180. // are:
  1181. //
  1182. // Event: FD_CONNECT
  1183. //
  1184. // Error Code Meaning
  1185. //
  1186. // WSAEADDRINUSE The specified address is already in use.
  1187. //
  1188. // WSAEADDRNOTAVAIL The specified address is not available from the
  1189. // local machine.
  1190. //
  1191. // WSAEAFNOSUPPORT Addresses in the specified family cannot be used with
  1192. // this socket.
  1193. //
  1194. // WSAECONNREFUSED The attempt to connect was forcefully rejected.
  1195. //
  1196. // WSAENETUNREACH The network cannot be reached from this host at this
  1197. // time.
  1198. //
  1199. // WSAEFAULT The namelen parameter is incorrect.
  1200. //
  1201. // WSAEINVAL The socket is already bound to an address.
  1202. //
  1203. // WSAEISCONN The socket is already connected.
  1204. //
  1205. // WSAEMFILE No more file descriptors are available.
  1206. //
  1207. // WSAENOBUFS No buffer space is available. The socket cannot be
  1208. // connected.
  1209. //
  1210. // WSAENOTCONN The socket is not connected.
  1211. //
  1212. // WSAETIMEDOUT Attempt to connect timed out without establishing a
  1213. // connection.
  1214. //
  1215. //
  1216. //
  1217. // Event: FD_CLOSE
  1218. //
  1219. // Error Code Meaning
  1220. //
  1221. // WSAENETDOWN The network subsystem has failed.
  1222. //
  1223. // WSAECONNRESET The connection was reset by the remote side.
  1224. //
  1225. // WSAECONNABORTED The connection was terminated due to a time-out or
  1226. // other failure.
  1227. //
  1228. //
  1229. // Event: FD_READ
  1230. //
  1231. // Event: FD_WRITE
  1232. //
  1233. // Event: FD_OOB
  1234. //
  1235. // Event: FD_ACCEPT
  1236. //
  1237. // Event: FD_QOS
  1238. //
  1239. // Event: FD_GROUP_QOS
  1240. //
  1241. // Error Code Meaning
  1242. //
  1243. // WSAENETDOWN The network subsystem has failed.
  1244. //
  1245. // ----------------------------------------------------------------