source: trunk/src/wsock32/asyncapi.cpp@ 3439

Last change on this file since 3439 was 3439, checked in by sandervl, 25 years ago

don't send FD_CLOSE ack when select returns and there's no data to be read

File size: 20.4 KB
Line 
1/* $Id: asyncapi.cpp,v 1.6 2000-04-23 15:55:52 sandervl Exp $ */
2
3/*
4 *
5 * Win32 SOCK32 for OS/2 (Async apis)
6 *
7 * Copyright (C) 2000 Sander van Leeuwen (sandervl@xs4all.nl)
8 *
9 * Parts based on Wine code: (dlls\winsock\async.c)
10 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
11 * (C) 1999 Marcus Meissner
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#define INCL_BASE
17#include <os2wrap.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <odin.h>
22#include <odinwrap.h>
23#include <os2sel.h>
24#include <misc.h>
25#include <win32api.h>
26#include "wsock32.h"
27#include "asyncthread.h"
28#include "wsastruct.h"
29
30#define DBG_LOCALLOG DBG_async
31#include "dbglocal.h"
32
33ODINDEBUGCHANNEL(WSOCK32-ASYNC)
34
35//******************************************************************************
36//NOTE: Must execute RemoveFromQueue before returning
37//******************************************************************************
38void ASYNCCNV WSAsyncThreadProc(void *pparm)
39{
40 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
41 LPARAM lParam;
42 int size = 0;
43 int fail = NO_ERROR;
44
45 if(!pThreadParm->fCancelled)
46 {
47 switch(pThreadParm->request)
48 {
49 case ASYNC_GETHOSTBYNAME:
50 case ASYNC_GETHOSTBYADDR:
51 {
52 struct hostent *ret;
53
54 if(pThreadParm->request == ASYNC_GETHOSTBYNAME) {
55 ret = gethostbyname(pThreadParm->u.gethostbyname.name);
56
57 free(pThreadParm->u.gethostbyname.name);
58 pThreadParm->u.gethostbyname.name = 0;
59 }
60 else {
61 ret = gethostbyaddr(pThreadParm->u.gethostbyaddr.addr,
62 pThreadParm->u.gethostbyaddr.len,
63 pThreadParm->u.gethostbyaddr.type);
64
65 free(pThreadParm->u.gethostbyaddr.addr);
66 pThreadParm->u.gethostbyaddr.addr = 0;
67 }
68 if (ret != NULL) {
69 size = WS_copy_he((struct ws_hostent *)pThreadParm->buf,
70 pThreadParm->buf,
71 pThreadParm->buflen,
72 ret);
73 if(size < 0) {
74 fail = WSAENOBUFS;
75 size = -size;
76 }
77 }
78 else fail = wsaHerrno();
79 break;
80 }
81
82 case ASYNC_GETPROTOBYNAME:
83 case ASYNC_GETPROTOBYNUMBER:
84 {
85 struct protoent *ret;
86
87 if(pThreadParm->request == ASYNC_GETPROTOBYNAME) {
88 ret = getprotobyname(pThreadParm->u.getprotobyname.name);
89
90 free(pThreadParm->u.getprotobyname.name);
91 pThreadParm->u.getprotobyname.name = 0;
92 }
93 else ret = getprotobynumber(pThreadParm->u.getprotobynumber.number);
94
95 if (ret != NULL) {
96 size = WS_copy_pe((struct ws_protoent *)pThreadParm->buf,
97 pThreadParm->buf,
98 pThreadParm->buflen,
99 ret);
100 if(size < 0) {
101 fail = WSAENOBUFS;
102 size = -size;
103 }
104 }
105 else fail = WSANO_DATA;
106
107 break;
108 }
109
110 case ASYNC_GETSERVBYNAME:
111 case ASYNC_GETSERVBYPORT:
112 {
113 struct servent *ret;
114
115 if(pThreadParm->request == ASYNC_GETSERVBYNAME) {
116 ret = getservbyname(pThreadParm->u.getservbyname.name, pThreadParm->u.getservbyname.proto);
117
118 free(pThreadParm->u.getservbyname.name);
119 pThreadParm->u.getservbyname.name = 0;
120
121 if(pThreadParm->u.getservbyname.proto) {
122 free(pThreadParm->u.getservbyname.proto);
123 pThreadParm->u.getservbyname.proto = 0;
124 }
125
126 }
127 else {
128 ret = getservbyport(pThreadParm->u.getservbyport.port, pThreadParm->u.getservbyport.proto);
129 if(pThreadParm->u.getservbyport.proto) {
130 free(pThreadParm->u.getservbyport.proto);
131 pThreadParm->u.getservbyport.proto = 0;
132 }
133 }
134
135 if (ret != NULL) {
136 size = WS_copy_se((struct ws_servent *)pThreadParm->buf,
137 pThreadParm->buf,
138 pThreadParm->buflen,
139 ret);
140 if(size < 0) {
141 fail = WSAENOBUFS;
142 size = -size;
143 }
144 }
145 else fail = WSANO_DATA;
146 break;
147 }
148 }
149 }
150 lParam = (fail << 16) | size;
151
152 if(!pThreadParm->fCancelled) {
153 dprintf(("WSAsyncThreadProc %x %x %x %x", pThreadParm->hwnd, pThreadParm->msg, pThreadParm->hAsyncTaskHandle, lParam));
154 PostMessageA(pThreadParm->hwnd, pThreadParm->msg,
155 (WPARAM)pThreadParm->hAsyncTaskHandle, lParam);
156 }
157 pThreadParm->fActive = FALSE;
158 RemoveFromQueue(pThreadParm);
159}
160//******************************************************************************
161//******************************************************************************
162LHANDLE WSAAsyncRequest(AsyncRequestType requesttype, HWND hwnd, int msg, char *buf,
163 int buflen, PVOID param1, PVOID param2, PVOID param3,
164 PVOID param4)
165{
166 PASYNCTHREADPARM pThreadParm;
167 LHANDLE hAsyncRequest = 0;
168 LPSTR tempname = 0;
169 LPSTR tempproto = 0;
170 LPSTR tempaddr = 0;
171
172 if(!fWSAInitialized)
173 {
174 WSASetLastError(WSANOTINITIALISED);
175 }
176 else
177 if(WSAIsBlocking())
178 {
179 WSASetLastError(WSAEINPROGRESS); // blocking call in progress
180 }
181 else
182 if(!IsWindow(hwnd))
183 {
184 WSASetLastError(WSAEINVAL); // invalid parameter
185 }
186 else
187 if(buf == NULL || buflen == 0) {
188 WSASetLastError(WSAENOBUFS); // invalid parameter
189 }
190 else
191 {
192 pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
193 if(pThreadParm == NULL) {
194 dprintf(("WSAAsyncRequest: malloc failure!"));
195 DebugInt3();
196 WSASetLastError(WSAEFAULT);
197 return 0;
198 }
199 memset(pThreadParm, 0, sizeof(*pThreadParm));
200 pThreadParm->request= requesttype;
201 pThreadParm->hwnd = hwnd;
202 pThreadParm->msg = msg;
203 pThreadParm->buf = buf;
204 pThreadParm->buflen = buflen;
205
206 switch(requesttype) {
207 case ASYNC_GETHOSTBYNAME:
208 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
209 if(tempname == NULL)
210 {
211 dprintf(("WSAAsyncGetHostByName: malloc failure!"));
212 DebugInt3();
213 WSASetLastError(WSAEFAULT);
214 return 0;
215 }
216 pThreadParm->u.gethostbyname.name = tempname;
217 strcpy(pThreadParm->u.gethostbyname.name, (char *)param1);
218 break;
219
220 case ASYNC_GETHOSTBYADDR:
221 tempaddr = (LPSTR)malloc(strlen((char *)param1)+1);
222 if(tempaddr == NULL)
223 {
224 dprintf(("WSAAsyncGetHostByAddr: malloc failure!"));
225 DebugInt3();
226 WSASetLastError(WSAEFAULT);
227 return 0;
228 }
229
230 pThreadParm->u.gethostbyaddr.len = (int)param2;
231 pThreadParm->u.gethostbyaddr.type = (int)param3;
232 pThreadParm->u.gethostbyaddr.addr = tempaddr;
233 strcpy(pThreadParm->u.gethostbyaddr.addr, (char *)param1);
234 break;
235
236 case ASYNC_GETPROTOBYNAME:
237 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
238 if(tempname == NULL)
239 {
240 dprintf(("WSAAsyncGetProtoByName: malloc failure!"));
241 DebugInt3();
242 WSASetLastError(WSAEFAULT);
243 return 0;
244 }
245 pThreadParm->u.getprotobyname.name = tempname;
246 strcpy(pThreadParm->u.getprotobyname.name, (char *)param1);
247 break;
248
249 case ASYNC_GETPROTOBYNUMBER:
250 pThreadParm->u.getprotobynumber.number = (int)param1;
251 break;
252
253 case ASYNC_GETSERVBYNAME:
254 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
255 tempproto = NULL;
256 if(param2) {
257 tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
258 }
259 if(tempname == NULL || (param2 && !tempproto))
260 {
261 dprintf(("WSAAsyncGetServByName: malloc failure!"));
262 DebugInt3();
263 WSASetLastError(WSAEFAULT);
264 return 0;
265 }
266 pThreadParm->u.getservbyname.name = tempname;
267 strcpy(pThreadParm->u.getservbyname.name, (char *)param1);
268 pThreadParm->u.getservbyname.proto = tempproto;
269 if(param2)
270 strcpy(pThreadParm->u.getservbyname.proto, (char *)param2);
271 break;
272
273 case ASYNC_GETSERVBYPORT:
274 if(param2) {
275 tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
276 }
277 if(param2 && !tempproto)
278 {
279 dprintf(("WSAAsyncGetServByPort: malloc failure!"));
280 DebugInt3();
281 WSASetLastError(WSAEFAULT);
282 return 0;
283 }
284 pThreadParm->u.getservbyport.port = (int)param1;
285 pThreadParm->u.getservbyport.proto = tempproto;
286 if(param2)
287 strcpy(pThreadParm->u.getservbyport.proto, (char *)param2);
288 break;
289 }
290 hAsyncRequest = (LHANDLE)QueueAsyncJob(WSAsyncThreadProc, pThreadParm);
291 if(hAsyncRequest == 0) {
292 free(pThreadParm);
293 if(tempname) free(tempname);
294 if(tempaddr) free(tempaddr);
295 if(tempproto) free(tempproto);
296
297 dprintf(("WSAAsyncRequest: QueueAsyncJob failure!"));
298 DebugInt3();
299 WSASetLastError(WSAEFAULT);
300 return 0;
301 }
302 return hAsyncRequest;
303 }
304 return 0;
305}
306//******************************************************************************
307//******************************************************************************
308ODINFUNCTION5(LHANDLE,WSAAsyncGetHostByName,
309 HWND,hWnd,
310 u_int,wMsg,
311 const char *,name,
312 char *,buf,
313 int,buflen)
314{
315 dprintf(("WSAAsyncGetHostByName %s", name));
316
317 return WSAAsyncRequest(ASYNC_GETHOSTBYNAME, hWnd, wMsg, buf, buflen,
318 (PVOID)name, 0, 0, 0);
319}
320//******************************************************************************
321//******************************************************************************
322ODINFUNCTION7(LHANDLE,WSAAsyncGetHostByAddr,
323 HWND,hWnd,
324 u_int,wMsg,
325 const char *,addr,
326 int,len,
327 int,type,
328 char *,buf,
329 int,buflen)
330{
331 dprintf(("WSAAsyncGetHostByAddr %s", addr));
332
333 return WSAAsyncRequest(ASYNC_GETHOSTBYADDR, hWnd, wMsg, buf, buflen,
334 (PVOID)addr, (PVOID)len, (PVOID)type, 0);
335}
336//******************************************************************************
337//******************************************************************************
338ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByName,
339 HWND,hWnd,
340 u_int,wMsg,
341 const char *,name,
342 char *,buf,
343 int,buflen)
344{
345 dprintf(("WSAAsyncGetProtoByName %s", name));
346
347 return WSAAsyncRequest(ASYNC_GETPROTOBYNAME, hWnd, wMsg, buf, buflen,
348 (PVOID)name, 0, 0, 0);
349}
350//******************************************************************************
351//******************************************************************************
352ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByNumber,
353 HWND,hWnd,
354 u_int,wMsg,
355 int,number,
356 char *,buf,
357 int,buflen)
358{
359 dprintf(("WSAAsyncGetProtoByNumber %d", number));
360
361 return WSAAsyncRequest(ASYNC_GETPROTOBYNUMBER, hWnd, wMsg, buf, buflen,
362 (PVOID)number, 0, 0, 0);
363}
364//******************************************************************************
365//******************************************************************************
366ODINFUNCTION6(LHANDLE,WSAAsyncGetServByName,
367 HWND,hWnd,
368 u_int,wMsg,
369 const char *,name,
370 const char *,proto,
371 char *,buf,
372 int,buflen)
373{
374 dprintf(("WSAAsyncGetServByName %s", name));
375
376 return WSAAsyncRequest(ASYNC_GETSERVBYNAME, hWnd, wMsg, buf, buflen,
377 (PVOID)name, (PVOID)proto, 0, 0);
378}
379//******************************************************************************
380//******************************************************************************
381ODINFUNCTION6(LHANDLE,WSAAsyncGetServByPort,
382 HWND,hWnd,
383 u_int,wMsg,
384 int,port,
385 const char *,proto,
386 char *,buf,
387 int,buflen)
388{
389 dprintf(("WSAAsyncGetServByPort %d %s", port, proto));
390
391 return WSAAsyncRequest(ASYNC_GETSERVBYPORT, hWnd, wMsg, buf, buflen,
392 (PVOID)port, (PVOID)proto, 0, 0);
393}
394//******************************************************************************
395//******************************************************************************
396void AsyncNotifyEvent(PASYNCTHREADPARM pThreadParm, ULONG event, ULONG socket_error)
397{
398 pThreadParm->u.asyncselect.lEventsPending &= ~event;
399
400 event = WSAMAKESELECTREPLY(event, socket_error);
401
402 dprintf(("AsyncNotifyEvent %x %x %x %x", pThreadParm->u.asyncselect.s, pThreadParm->hwnd, pThreadParm->msg, event));
403 PostMessageA(pThreadParm->hwnd, pThreadParm->msg, (WPARAM)pThreadParm->u.asyncselect.s,
404 (LPARAM)event);
405}
406//******************************************************************************
407#define nr(i) ((i != -1) ? 1 : 0)
408#define ready(i) ((i != -1) && (sockets[i] != -1))
409//NOTE: Must execute RemoveFromQueue before returning
410//******************************************************************************
411void ASYNCCNV WSAsyncSelectThreadProc(void *pparm)
412{
413 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
414 SOCKET sockets[3];
415 SOCKET s = pThreadParm->u.asyncselect.s;
416 int noread, nowrite, noexcept, state, sockoptlen, sockoptval;
417 int tmp, i, lEventsPending, ret, bytesread;
418
419 while(TRUE)
420 {
421asyncloopstart:
422 i = 0;
423 noread = nowrite = noexcept = -1;
424
425 //break if user cancelled request
426 if(pThreadParm->u.asyncselect.lEvents == 0) {
427 break;
428 }
429
430 lEventsPending = pThreadParm->u.asyncselect.lEventsPending;
431 //block if no events are pending
432 if(lEventsPending == 0)
433 {
434 //wait for events to be enabled
435 pThreadParm->u.asyncselect.asyncSem->wait();
436 //reset event semaphore
437 pThreadParm->u.asyncselect.asyncSem->reset();
438 continue;
439 }
440
441 if(lEventsPending & (FD_READ | FD_CLOSE | FD_ACCEPT)) {
442 noread = i++;
443 sockets[noread] = s;
444 }
445 if((lEventsPending & FD_CONNECT) ||
446 ((lEventsPending & FD_WRITE) &&
447 (!(ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp)) & SS_CANTSENDMORE))))
448 {
449 nowrite = i++;
450 sockets[nowrite] = s;
451 }
452 if(lEventsPending & FD_OOB) {
453 noexcept = i++;
454 sockets[noexcept] = s;
455 }
456
457//// dprintf(("WSAsyncSelectThreadProc %x rds=%d, wrs=%d, oos =%d, pending = %x", pThreadParm->u.asyncselect.s, noread, nowrite, noexcept, lEventsPending));
458
459 ret = select((int *)sockets, nr(noread), nr(nowrite), nr(noexcept), -1);
460 if(ret == SOCKET_ERROR) {
461 int selecterr = sock_errno();
462//// dprintf(("WSAsyncSelectThreadProc %x rds=%d, wrs=%d, oos =%d, pending = %x select returned %x", pThreadParm->u.asyncselect.s, noread, nowrite, noexcept, lEventsPending, selecterr));
463 if(selecterr && selecterr < SOCBASEERR) {
464 selecterr += SOCBASEERR;
465 }
466 switch(selecterr)
467 {
468 case SOCEINTR:
469//// state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
470//// dprintf(("SOCEINTR; state = %x", state));
471 goto asyncloopstart; //so_cancel was called
472
473 case SOCECONNRESET:
474 case SOCEPIPE:
475 if(lEventsPending & FD_CLOSE) {
476 dprintf(("FD_CLOSE; broken connection"));
477 AsyncNotifyEvent(pThreadParm, FD_CLOSE, WSAECONNRESET);
478 }
479
480 //remote connection broken (so can't receive data anymore)
481 //but can still send
482 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
483 goto asyncloopstart;
484
485 case SOCEINVAL:
486 if(lEventsPending & FD_CLOSE) {
487 dprintf(("FD_CLOSE; SOCEINVAL"));
488 AsyncNotifyEvent(pThreadParm, FD_CLOSE, selecterr);
489 }
490 break;
491 default:
492 dprintf(("WSAsyncSelectThreadProc: select SOCKET_ERROR %x", selecterr));
493 break; //something bad happened
494 }
495 break;
496 }
497
498 if(ready(nowrite))
499 {
500 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
501
502 if(lEventsPending & FD_CONNECT) {
503 if(state & SS_ISCONNECTED) {
504 AsyncNotifyEvent(pThreadParm, FD_CONNECT, NO_ERROR);
505 }
506 else {
507 sockoptlen = sizeof(int);
508
509 ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
510 (char *) &sockoptval, &sockoptlen);
511 //SvL: WSeB returns SOCECONNREFUSED, Warp 4 0x3d
512 if(sockoptval == SOCECONNREFUSED || sockoptval == (SOCECONNREFUSED - SOCBASEERR)) {
513 AsyncNotifyEvent(pThreadParm, FD_CONNECT, WSAECONNREFUSED);
514 }
515 }
516 }
517 else
518 if(!(state & SS_CANTSENDMORE) && (lEventsPending & FD_WRITE)) {
519 AsyncNotifyEvent(pThreadParm, FD_WRITE, NO_ERROR);
520 }
521 }
522
523 if(ready(noread))
524 {
525 state = ioctl(s, FIONREAD, (CHAR *) &bytesread, sizeof(bytesread));
526 if(state == SOCKET_ERROR)
527 {
528 if(lEventsPending & FD_CLOSE)
529 {
530 dprintf(("FD_CLOSE; ioctl; socket error"));
531 AsyncNotifyEvent(pThreadParm, FD_CLOSE, NO_ERROR);
532 //remote connection broken (so can't receive data anymore)
533 //but can still send
534 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
535 continue;
536 }
537 else {
538 dprintf(("WSAsyncSelectThreadProc: ioctl SOCKET_ERROR!"));
539 break; //todo: correct???
540 }
541 }
542 if(lEventsPending & FD_ACCEPT)
543 {
544 sockoptlen = sizeof(sockoptlen);
545
546 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS,
547 (char *) &sockoptval, &sockoptlen);
548 if(ret == SOCKET_ERROR) {
549 dprintf(("WSAsyncSelectThreadProc: getsockopt SOCKET_ERROR!"));
550 break;
551 }
552 if((sockoptval & SO_ACCEPTCONN) == SO_ACCEPTCONN) {
553 AsyncNotifyEvent(pThreadParm, FD_ACCEPT, NO_ERROR);
554 }
555 }
556 if((lEventsPending & FD_READ) && bytesread > 0) {
557 AsyncNotifyEvent(pThreadParm, FD_READ, NO_ERROR);
558 }
559#if 0
560//SvL: This generates FD_CLOSE messages when the connection is just fine
561// (recv executed in another thread when select returns)
562 else
563 if((lEventsPending & FD_CLOSE) && (state == 0 && bytesread == 0)) {
564 dprintf(("FD_CLOSE; state == 0 && bytesread == 0"));
565 AsyncNotifyEvent(pThreadParm, FD_CLOSE, NO_ERROR);
566 }
567#endif
568 }
569 if(ready(noexcept))
570 {
571 if(lEventsPending & FD_OOB) {
572 AsyncNotifyEvent(pThreadParm, FD_OOB, NO_ERROR);
573 }
574 }
575 if((pThreadParm->u.asyncselect.lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT)) ==
576 (lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT))) {
577 DosSleep(10);
578 }
579 }
580 //remove it first, then delete semaphore object
581 pThreadParm->fActive = FALSE;
582 RemoveFromQueue(pThreadParm);
583 delete pThreadParm->u.asyncselect.asyncSem;
584 pThreadParm->u.asyncselect.asyncSem = 0;
585}
586//******************************************************************************
587//******************************************************************************
588ODINFUNCTION4(int,WSAAsyncSelect,
589 SOCKET,s,
590 HWND,hWnd,
591 u_int,wMsg,
592 long,lEvent)
593{
594 PASYNCTHREADPARM pThreadParm;
595 int nonblock = 1;
596 int ret;
597
598 if(!fWSAInitialized)
599 {
600 WSASetLastError(WSANOTINITIALISED);
601 return SOCKET_ERROR;
602 }
603 else
604 if(WSAIsBlocking())
605 {
606 WSASetLastError(WSAEINPROGRESS); // blocking call in progress
607 return SOCKET_ERROR;
608 }
609 else
610 if(hWnd && !IsWindow(hWnd))
611 {
612 WSASetLastError(WSAEINVAL); // invalid parameter
613 return SOCKET_ERROR;
614 }
615 //Set socket to non-blocking mode
616 ret = ioctl(s, FIONBIO, (char *) &nonblock, sizeof(nonblock));
617 if(ret == SOCKET_ERROR) {
618 WSASetLastError(wsaErrno());
619 return SOCKET_ERROR;
620 }
621 if(FindAndSetAsyncEvent(s, hWnd, wMsg, lEvent) == TRUE) {
622 //found and changed active async event
623 WSASetLastError(NO_ERROR);
624 return NO_ERROR;
625 }
626 pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
627 if(pThreadParm == NULL) {
628 dprintf(("WSAAsyncSelect: malloc failure!"));
629 DebugInt3();
630 WSASetLastError(WSAEFAULT);
631 return SOCKET_ERROR;
632 }
633 memset(pThreadParm, 0, sizeof(*pThreadParm));
634 pThreadParm->request= ASYNC_SELECT;
635 pThreadParm->hwnd = hWnd;
636 pThreadParm->msg = wMsg;
637 pThreadParm->u.asyncselect.lEvents = lEvent;
638 pThreadParm->u.asyncselect.lEventsPending = lEvent;
639 pThreadParm->u.asyncselect.s = s;
640 pThreadParm->u.asyncselect.asyncSem = new VSemaphore;
641 if(pThreadParm->u.asyncselect.asyncSem == NULL) {
642 dprintf(("WSAAsyncSelect: VSemaphore alloc failure!"));
643 DebugInt3();
644 WSASetLastError(WSAEFAULT);
645 return SOCKET_ERROR;
646 }
647 if(QueueAsyncJob(WSAsyncSelectThreadProc, pThreadParm) == 0) {
648 delete pThreadParm->u.asyncselect.asyncSem;
649 free(pThreadParm);
650 dprintf(("WSAAsyncSelect: QueueAsyncJob failure!"));
651 DebugInt3();
652 WSASetLastError(WSAEFAULT);
653 return SOCKET_ERROR;
654 }
655 WSASetLastError(NO_ERROR);
656 return NO_ERROR;
657}
658//******************************************************************************
659//******************************************************************************
Note: See TracBrowser for help on using the repository browser.