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

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

socket error fixes

File size: 19.9 KB
Line 
1/* $Id: asyncapi.cpp,v 1.4 2000-03-28 17:13:05 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 AsyncNotifyEvent(pThreadParm, FD_CLOSE, WSAECONNRESET);
477
478 //remote connection broken (so can't receive data anymore)
479 //but can still send
480 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
481 goto asyncloopstart;
482
483 case SOCEINVAL:
484 if(lEventsPending & FD_CLOSE)
485 AsyncNotifyEvent(pThreadParm, FD_CLOSE, selecterr);
486 break;
487 default:
488 dprintf(("WSAsyncSelectThreadProc: select SOCKET_ERROR %x", selecterr));
489 break; //something bad happened
490 }
491 break;
492 }
493
494 if(ready(nowrite))
495 {
496 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
497
498 if(lEventsPending & FD_CONNECT) {
499 if(state & SS_ISCONNECTED) {
500 AsyncNotifyEvent(pThreadParm, FD_CONNECT, NO_ERROR);
501 }
502 else {
503 sockoptlen = sizeof(int);
504
505 ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
506 (char *) &sockoptval, &sockoptlen);
507 //SvL: WSeB returns SOCECONNREFUSED, Warp 4 0x3d
508 if(sockoptval == SOCECONNREFUSED || sockoptval == (SOCECONNREFUSED - SOCBASEERR)) {
509 AsyncNotifyEvent(pThreadParm, FD_CONNECT, WSAECONNREFUSED);
510 }
511 }
512 }
513 else
514 if(!(state & SS_CANTSENDMORE) && (lEventsPending & FD_WRITE)) {
515 AsyncNotifyEvent(pThreadParm, FD_WRITE, NO_ERROR);
516 }
517 }
518
519 if(ready(noread))
520 {
521 state = ioctl(s, FIONREAD, (CHAR *) &bytesread, sizeof(bytesread));
522 if(state == SOCKET_ERROR) {
523 if(lEventsPending & FD_CLOSE)
524 {
525 AsyncNotifyEvent(pThreadParm, FD_CLOSE, NO_ERROR);
526 //remote connection broken (so can't receive data anymore)
527 //but can still send
528 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
529 continue;
530 }
531 else {
532 dprintf(("WSAsyncSelectThreadProc: ioctl SOCKET_ERROR!"));
533 break; //todo: correct???
534 }
535 }
536 if(lEventsPending & FD_ACCEPT)
537 {
538 sockoptlen = sizeof(sockoptlen);
539
540 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS,
541 (char *) &sockoptval, &sockoptlen);
542 if(ret == SOCKET_ERROR) {
543 dprintf(("WSAsyncSelectThreadProc: getsockopt SOCKET_ERROR!"));
544 break;
545 }
546 if((sockoptval & SO_ACCEPTCONN) == SO_ACCEPTCONN) {
547 AsyncNotifyEvent(pThreadParm, FD_ACCEPT, NO_ERROR);
548 }
549 }
550 if((lEventsPending & FD_READ) && bytesread > 0) {
551 AsyncNotifyEvent(pThreadParm, FD_READ, NO_ERROR);
552 }
553 }
554 if(ready(noexcept))
555 {
556 if(lEventsPending & FD_OOB) {
557 AsyncNotifyEvent(pThreadParm, FD_OOB, NO_ERROR);
558 }
559 }
560 if((pThreadParm->u.asyncselect.lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT)) ==
561 (lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT))) {
562 DosSleep(10);
563 }
564 }
565 //remove it first, then delete semaphore object
566 pThreadParm->fActive = FALSE;
567 RemoveFromQueue(pThreadParm);
568 delete pThreadParm->u.asyncselect.asyncSem;
569 pThreadParm->u.asyncselect.asyncSem = 0;
570}
571//******************************************************************************
572//******************************************************************************
573ODINFUNCTION4(int,WSAAsyncSelect,
574 SOCKET,s,
575 HWND,hWnd,
576 u_int,wMsg,
577 long,lEvent)
578{
579 PASYNCTHREADPARM pThreadParm;
580 int nonblock = 1;
581 int ret;
582
583 if(!fWSAInitialized)
584 {
585 WSASetLastError(WSANOTINITIALISED);
586 return SOCKET_ERROR;
587 }
588 else
589 if(WSAIsBlocking())
590 {
591 WSASetLastError(WSAEINPROGRESS); // blocking call in progress
592 return SOCKET_ERROR;
593 }
594 else
595 if(hWnd && !IsWindow(hWnd))
596 {
597 WSASetLastError(WSAEINVAL); // invalid parameter
598 return SOCKET_ERROR;
599 }
600 //Set socket to non-blocking mode
601 ret = ioctl(s, FIONBIO, (char *) &nonblock, sizeof(nonblock));
602 if(ret == SOCKET_ERROR) {
603 WSASetLastError(wsaErrno());
604 return SOCKET_ERROR;
605 }
606 if(FindAndSetAsyncEvent(s, hWnd, wMsg, lEvent) == TRUE) {
607 //found and changed active async event
608 WSASetLastError(NO_ERROR);
609 return NO_ERROR;
610 }
611 pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
612 if(pThreadParm == NULL) {
613 dprintf(("WSAAsyncSelect: malloc failure!"));
614 DebugInt3();
615 WSASetLastError(WSAEFAULT);
616 return SOCKET_ERROR;
617 }
618 memset(pThreadParm, 0, sizeof(*pThreadParm));
619 pThreadParm->request= ASYNC_SELECT;
620 pThreadParm->hwnd = hWnd;
621 pThreadParm->msg = wMsg;
622 pThreadParm->u.asyncselect.lEvents = lEvent;
623 pThreadParm->u.asyncselect.lEventsPending = lEvent;
624 pThreadParm->u.asyncselect.s = s;
625 pThreadParm->u.asyncselect.asyncSem = new VSemaphore;
626 if(pThreadParm->u.asyncselect.asyncSem == NULL) {
627 dprintf(("WSAAsyncSelect: VSemaphore alloc failure!"));
628 DebugInt3();
629 WSASetLastError(WSAEFAULT);
630 return SOCKET_ERROR;
631 }
632 if(QueueAsyncJob(WSAsyncSelectThreadProc, pThreadParm) == 0) {
633 delete pThreadParm->u.asyncselect.asyncSem;
634 free(pThreadParm);
635 dprintf(("WSAAsyncSelect: QueueAsyncJob failure!"));
636 DebugInt3();
637 WSASetLastError(WSAEFAULT);
638 return SOCKET_ERROR;
639 }
640 WSASetLastError(NO_ERROR);
641 return NO_ERROR;
642}
643//******************************************************************************
644//******************************************************************************
Note: See TracBrowser for help on using the repository browser.