source: trunk/src/wsock32/async.cpp@ 1816

Last change on this file since 1816 was 1816, checked in by sandervl, 26 years ago

compilation fix

File size: 45.5 KB
Line 
1/* $Id: async.cpp,v 1.17 1999-11-23 19:32:27 sandervl Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 * Asynchronous Winsock code
8 *
9 * Copyright 1999 Patrick Haller
10 *
11 *
12 * Remark:
13 * - do NOT call WSASetLastError in the async worker thread, since there we don't
14 * know anything about the caller thread.
15 *
16 * Idea is to separate requests:
17 * - all database requests and DNS requests are handled by one thread
18 * - asynchronous selects are each handled by its own thread
19 */
20
21
22/*****************************************************************************
23 * Includes *
24 *****************************************************************************/
25
26#include <odin.h>
27#include <odinwrap.h>
28#include <os2sel.h>
29#define INCL_DOSERRORS
30#define INCL_DOSSEMAPHORES
31#include <os2.h>
32
33#include <types.h>
34#include <utils.h>
35
36#include <netdb.h>
37#include <nerrno.h>
38#include <sys/socket.h>
39#include <sys/ioctl.h>
40#include <sys/select.h>
41#include <sys/time.h>
42
43#include <wsock32const.h>
44
45#include <process.h>
46#include <string.h>
47#include <stdlib.h>
48
49#include <misc.h>
50
51
52/*****************************************************************************
53 * Definitions *
54 *****************************************************************************/
55
56ODINDEBUGCHANNEL(WSOCK32-ASYNC)
57
58
59#define ERROR_SUCCESS 0
60
61
62typedef enum tagSocketStatus
63{
64 SOCKSTAT_UNKNOWN = 0, // unknown socket state
65 SOCKSTAT_NORMAL, // normal socket state
66 SOCKSTAT_CONNECT_PENDING // non-blocking connect attempted
67};
68
69typedef struct tagSocketAsync
70{
71 int hSocket; /* operating system socket descriptor */
72 int iStatus;
73
74 int iEventMaskAllowed; // bits of valid socket events are set to 1
75} SOCKETASYNC, *PSOCKETASYNC;
76
77
78// prototype of the OS/2 select!
79int _System os2_select(int* socket,
80 int fd_read,
81 int fd_write,
82 int fd_exception,
83 long timeout);
84
85int _System bsd_select(int,
86 fd_set *,
87 fd_set *,
88 fd_set *,
89 struct timeval*);
90
91// wsock32.cpp: error code translation
92int iTranslateSockErrToWSock(int iError);
93
94
95/*****************************************************************************
96 * Structures *
97 *****************************************************************************/
98
99// request types
100enum tagAsyncRequestType
101{
102 WSAASYNC_TERMINATE, // internal message
103 WSAASYNC_GETHOSTBYADDR,
104 WSAASYNC_GETHOSTBYNAME,
105 WSAASYNC_GETPROTOBYNAME,
106 WSAASYNC_GETPROTOBYNUMBER,
107 WSAASYNC_GETSERVBYNAME,
108 WSAASYNC_GETSERVBYPORT,
109 WSAASYNC_SELECT
110};
111
112
113// request states
114enum tagAsyncRequestStates
115{
116 RS_WAITING, // request is waiting in queue
117 RS_BUSY, // request is currently being serviced
118 RS_CANCELLED, // request has been cancelled
119 RS_DONE
120};
121
122
123typedef struct tagAsyncRequest
124{
125 struct tagAsyncRequest* pPrev; // pointer to previous request
126 struct tagAsyncRequest* pNext; // pointer to next request
127
128 ULONG ulType; // type of request
129 ULONG ulState; // state of request
130 PWSOCKTHREADDATA pwstd; // save pointer of caller thread's wsock data
131
132 HWND hwnd; // window handle to post message to
133 ULONG ulMessage; // message to post
134
135 PVOID pBuffer; // result buffer
136 ULONG ulBufferLength; // length of the return buffer
137
138 ULONG ul1; // multi purpose parameters
139 ULONG ul2;
140 ULONG ul3;
141
142} ASYNCREQUEST, *PASYNCREQUEST;
143
144
145/*****************************************************************************
146 * Prototypes *
147 *****************************************************************************/
148
149void _Optlink WorkerThreadProc(void* pParam);
150BOOL _System PostMessageA(HWND hwnd, UINT ulMessage, WPARAM wParam, LPARAM lParam);
151
152
153/*****************************************************************************
154 * Implementation *
155 *****************************************************************************/
156
157class WSAAsyncWorker
158{
159 // protected members
160 protected:
161 PASYNCREQUEST pRequestHead; // chain root
162 PASYNCREQUEST pRequestTail; // chain root
163 TID tidWorker; // worker thread id
164 HEV hevRequest; // fired upon new request
165 HMTX hmtxRequestQueue; // request queue protection
166 BOOL fTerminate; // got to die ?
167 BOOL fBlocking; // currently busy ?
168
169 TID startWorker (void); // start worker thread
170 void processingLoop (void); // "work"
171 int dispatchRequest(PASYNCREQUEST pRequest); // complete request
172 PASYNCREQUEST popRequest (void); // get one request from queue
173 BOOL deleteRequest (PASYNCREQUEST pRequest); // remove particular request
174
175 void lockQueue (void); // enter mutex
176 void unlockQueue (void); // leave mutex
177
178 // the real worker methods
179 void asyncGetHostByAddr (PASYNCREQUEST pRequest);
180 void asyncGetHostByName (PASYNCREQUEST pRequest);
181 void asyncGetProtoByName (PASYNCREQUEST pRequest);
182 void asyncGetProtoByNumber(PASYNCREQUEST pRequest);
183 void asyncGetServByName (PASYNCREQUEST pRequest);
184 void asyncGetServByPort (PASYNCREQUEST pRequest);
185 void asyncSelect (PASYNCREQUEST pRequest);
186
187 // public members
188 public:
189 WSAAsyncWorker(void); // constructor
190 ~WSAAsyncWorker(); // destructor
191
192 PASYNCREQUEST createRequest (ULONG ulType,
193 HWND hwnd,
194 ULONG ulMessage,
195 PVOID pBuffer,
196 ULONG ulBufferLength,
197 ULONG ul1 = 0,
198 ULONG ul2 = 0,
199 ULONG ul3 = 0);
200
201 void pushRequest (PASYNCREQUEST pRequest); // put request on queue
202 BOOL cancelAsyncRequest (PASYNCREQUEST pRequest);
203 BOOL isBlocking (void) {return fBlocking;}
204
205 // the thread procedure
206 friend void _Optlink WorkerThreadProc(void* pParam);
207};
208
209
210/*****************************************************************************
211 * Local variables *
212 *****************************************************************************/
213
214//static WSAAsyncWorker* wsaWorker = NULL;
215static WSAAsyncWorker* wsaWorker = new WSAAsyncWorker();
216
217
218/*****************************************************************************
219 * Name :
220 * Purpose :
221 * Parameters:
222 * Variables :
223 * Result :
224 * Remark :
225 * Status : UNTESTED STUB
226 *
227 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
228 *****************************************************************************/
229// constructor
230WSAAsyncWorker::WSAAsyncWorker(void)
231{
232 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::WSAAsyncWorker\n"));
233
234 pRequestHead = NULL; // chain root
235 pRequestTail = NULL; // chain root
236 tidWorker = 0; // worker thread id
237 fTerminate = FALSE; // got to die ?
238
239 startWorker();
240}
241
242
243/*****************************************************************************
244 * Name :
245 * Purpose :
246 * Parameters:
247 * Variables :
248 * Result :
249 * Remark :
250 * Status : UNTESTED STUB
251 *
252 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
253 *****************************************************************************/
254// destructor
255WSAAsyncWorker::~WSAAsyncWorker(void)
256{
257 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::~WSAAsyncWorker (%08xh)\n",
258 this));
259
260 // remove all requests
261 while (popRequest() != NULL);
262
263 // just in case ... terminate worker thread
264 if (tidWorker != 0)
265 {
266 fTerminate = TRUE;
267 DosPostEventSem(hevRequest);
268 }
269
270 DosCloseEventSem(hevRequest);
271 DosCloseMutexSem(hmtxRequestQueue);
272}
273
274
275
276/*****************************************************************************
277 * Name :
278 * Purpose :
279 * Parameters:
280 * Variables :
281 * Result :
282 * Remark :
283 * Status : UNTESTED STUB
284 *
285 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
286 *****************************************************************************/
287// start worker thread if necessary
288TID WSAAsyncWorker::startWorker(void)
289{
290 APIRET rc;
291
292 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::startWorker (%08xh)\n",
293 this));
294
295 if (tidWorker == 0)
296 {
297 // create semaphores
298 rc = DosCreateEventSem(NULL, // unnamed
299 &hevRequest,
300 0, // unshared
301 FALSE); // reset
302 if (rc != NO_ERROR)
303 {
304 dprintf(("WSOCK32: WSAAsyncWorker::startWorker - DosCreateEventSem = %08xh\n",
305 rc));
306
307 return 0;
308 }
309
310 rc = DosCreateMutexSem(NULL, // unnamed
311 &hmtxRequestQueue,
312 0, // unshared
313 FALSE); // unowned
314 if (rc != NO_ERROR)
315 {
316 dprintf(("WSOCK32: WSAAsyncWorker::startWorker - DosCreateMutexSem = %08xh\n",
317 rc));
318
319 DosCloseEventSem(hevRequest);
320 return 0;
321 }
322
323 // create thread
324#if defined(__IBMCPP__)
325 tidWorker = _beginthread(WorkerThreadProc,
326 NULL,
327 16384,
328 (PVOID)this);
329#else
330 tidWorker = _beginthread(WorkerThreadProc,
331 16384,
332 (PVOID)this);
333#endif
334 if (tidWorker == -1)
335 {
336 // cancel the whole thing
337 tidWorker = 0;
338 DosCloseEventSem(hevRequest);
339 DosCloseMutexSem(hmtxRequestQueue);
340 }
341 }
342
343 return tidWorker; // thread already running
344}
345
346
347/*****************************************************************************
348 * Name :
349 * Purpose :
350 * Parameters:
351 * Variables :
352 * Result :
353 * Remark :
354 * Status : UNTESTED STUB
355 *
356 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
357 *****************************************************************************/
358// lock double-linked request chain
359void WSAAsyncWorker::lockQueue(void)
360{
361 DosRequestMutexSem(hmtxRequestQueue, SEM_INDEFINITE_WAIT);
362}
363
364
365/*****************************************************************************
366 * Name :
367 * Purpose :
368 * Parameters:
369 * Variables :
370 * Result :
371 * Remark :
372 * Status : UNTESTED STUB
373 *
374 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
375 *****************************************************************************/
376// unlock double-linked request chain
377void WSAAsyncWorker::unlockQueue(void)
378{
379 DosReleaseMutexSem(hmtxRequestQueue);
380}
381
382
383/*****************************************************************************
384 * Name :
385 * Purpose :
386 * Parameters:
387 * Variables :
388 * Result :
389 * Remark :
390 * Status : UNTESTED STUB
391 *
392 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
393 *****************************************************************************/
394// get request from queue
395PASYNCREQUEST WSAAsyncWorker::popRequest(void)
396{
397 PASYNCREQUEST pLast;
398
399 lockQueue(); // lock queue
400
401 // alter queue
402 pLast = pRequestTail;
403
404 if (pRequestTail != NULL)
405 {
406 if (pRequestTail->pPrev)
407 {
408 pRequestTail->pPrev->pNext = NULL; // cut off element
409 pRequestTail = pRequestTail->pPrev; // unlink previous element
410 }
411 else
412 {
413 // this is the last request on the queue
414 pRequestTail = NULL;
415 pRequestHead = NULL;
416 }
417 }
418
419 unlockQueue(); // unlock queue
420
421 return (pLast); // return element
422}
423
424
425/*****************************************************************************
426 * Name :
427 * Purpose :
428 * Parameters:
429 * Variables :
430 * Result :
431 * Remark :
432 * Status : UNTESTED STUB
433 *
434 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
435 *****************************************************************************/
436// insert request into queue
437void WSAAsyncWorker::pushRequest(PASYNCREQUEST pNew)
438{
439 if (pNew == NULL) // ensure proper parameters
440 return;
441
442 lockQueue(); // lock queue
443
444 // alter queue
445 if (pRequestHead == NULL)
446 {
447 // first element in queue
448 pRequestHead = pNew;
449 pRequestTail = pNew;
450 pNew->pPrev = NULL;
451 pNew->pNext = NULL;
452 }
453 else
454 {
455 // chain in request
456 pNew->pPrev = NULL;
457 pNew->pNext = pRequestHead;
458 pRequestHead->pPrev = pNew;
459 pRequestHead = pNew;
460 }
461
462 // queue debug
463 {
464 PASYNCREQUEST pTemp;
465
466 dprintf(("WSOCK32: WSAAsyncWorker pRequest type state hwnd message\n"));
467 for (pTemp = pRequestHead;
468 pTemp;
469 pTemp = pTemp->pNext)
470 dprintf(("WSOCK32: WSAAsyncWorker %08xh %08xh %08xh %08xh %08xh",
471 pTemp,
472 pTemp->ulType,
473 pTemp->ulState,
474 pTemp->hwnd,
475 pTemp->ulMessage));
476 }
477
478 // trigger thread!
479 DosPostEventSem(hevRequest);
480
481 unlockQueue(); // unlock queue
482}
483
484
485/*****************************************************************************
486 * Name :
487 * Purpose :
488 * Parameters:
489 * Variables :
490 * Result :
491 * Remark :
492 * Status : UNTESTED STUB
493 *
494 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
495 *****************************************************************************/
496// delete particular request from queue
497BOOL WSAAsyncWorker::deleteRequest(PASYNCREQUEST pDelete)
498{
499 PASYNCREQUEST pRequest; // for verification
500 BOOL bResult = FALSE;
501
502 lockQueue(); // lock queue
503
504 // find request (optional, just for verification)
505 for (pRequest = pRequestHead;
506 pRequest != NULL;
507 pRequest = pRequest->pNext)
508 if (pRequest == pDelete)
509 break;
510
511 if (pRequest == pDelete) // if request has been found
512 {
513 // is request the head of the list ?
514 if (pDelete == pRequestHead)
515 {
516 pRequestHead = pDelete->pNext;
517 if (pRequestHead == NULL) // last element ?
518 pRequestTail = NULL;
519 else
520 pRequestHead->pPrev = NULL;
521 }
522 else
523 // if request the last in the list ?
524 if (pDelete == pRequestTail)
525 {
526 pRequestTail = pDelete->pPrev;
527 if (pRequestTail == NULL) // last element ?
528 pRequestHead = NULL;
529 else
530 pRequestTail->pNext = NULL;
531 }
532 else
533 // request is somewhere in the middle of the list
534 {
535 if (pDelete->pPrev != NULL)
536 pDelete->pPrev->pNext = pDelete->pNext;
537
538 if (pDelete->pNext != NULL)
539 pDelete->pNext->pPrev = pDelete->pPrev;
540 }
541
542 delete pDelete; // free the memory
543 bResult = TRUE; // OK
544 }
545
546 unlockQueue(); // unlock queue
547 return bResult;
548}
549
550
551/*****************************************************************************
552 * Name :
553 * Purpose :
554 * Parameters:
555 * Variables :
556 * Result :
557 * Remark :
558 * Status : UNTESTED STUB
559 *
560 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
561 *****************************************************************************/
562
563BOOL WSAAsyncWorker::cancelAsyncRequest(PASYNCREQUEST pRequest)
564{
565 PASYNCREQUEST pRequestTemp;
566 BOOL rc = TRUE;
567
568 lockQueue();
569
570 // verify pRequest
571 // find request (optional, just for verification)
572 for (pRequestTemp = pRequestHead;
573 pRequestTemp != NULL;
574 pRequestTemp = pRequestTemp->pNext)
575 if (pRequestTemp == pRequest)
576 break;
577
578 // is request in queue ?
579 if (pRequestTemp == pRequest)
580 {
581 // is it busy?
582 if (pRequest->ulState != RS_BUSY)
583 {
584 // if not: set RS_CANCELLED
585 pRequest->ulState = RS_CANCELLED;
586 }
587 else
588 {
589 // if busy: ???
590 dprintf(("WSOCK32:Async: WSAAsyncWorker::cancelAsyncRequest(%08xh, %08xh) how to cancel?\n",
591 this,
592 pRequest));
593 rc = FALSE;
594 }
595 }
596 else
597 rc = FALSE;
598
599 unlockQueue();
600 return rc;
601}
602
603
604/*****************************************************************************
605 * Name :
606 * Purpose :
607 * Parameters:
608 * Variables :
609 * Result :
610 * Remark :
611 * Status : UNTESTED STUB
612 *
613 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
614 *****************************************************************************/
615
616PASYNCREQUEST WSAAsyncWorker::createRequest (ULONG ulType,
617 HWND hwnd,
618 ULONG ulMessage,
619 PVOID pBuffer,
620 ULONG ulBufferLength,
621 ULONG ul1,
622 ULONG ul2,
623 ULONG ul3)
624{
625 PASYNCREQUEST pNew = new ASYNCREQUEST();
626
627 if (pNew != NULL) // check for proper allocation
628 {
629 // fill the structure
630 pNew->pPrev = NULL;
631 pNew->pNext = NULL;
632 pNew->ulType = ulType;
633 pNew->ulState = RS_WAITING;
634 pNew->hwnd = hwnd;
635 pNew->ulMessage = ulMessage;
636 pNew->pBuffer = pBuffer;
637 pNew->ulBufferLength = ulBufferLength;
638 pNew->ul1 = ul1;
639 pNew->ul2 = ul2;
640 pNew->ul3 = ul3;
641
642 // save caller thread's wsock data
643 pNew->pwstd = iQueryWsockThreadData();
644 }
645
646 dprintf(("WSOCK32: WSAAsyncWorker:createRequest = %08xh\n",
647 pNew));
648
649 return pNew;
650}
651
652
653/*****************************************************************************
654 * Name :
655 * Purpose :
656 * Parameters:
657 * Variables :
658 * Result :
659 * Remark :
660 * Status : UNTESTED STUB
661 *
662 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
663 *****************************************************************************/
664
665void WSAAsyncWorker::asyncGetHostByAddr (PASYNCREQUEST pRequest)
666{
667 struct hostent* pHostent;
668 USHORT usLength = sizeof(struct Whostent);
669 USHORT rc;
670 struct Whostent* pwhostent = (struct Whostent*)pRequest->pBuffer;
671
672 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetHostByAddr (%08xh, %08xh)\n",
673 this,
674 pRequest));
675
676 // result buffer length
677 if (pRequest->ulBufferLength < sizeof(struct Whostent))
678 {
679 rc = WSAEINVAL;
680 //WSASetLastError(rc); // same as Winsock return codes
681 }
682 else
683 {
684 // call API
685 pHostent = gethostbyaddr((char*)pRequest->ul1,
686 (int) pRequest->ul2,
687 (int) pRequest->ul3);
688 if (pHostent == NULL) // error ?
689 {
690 // build error return code
691 rc = iTranslateSockErrToWSock(sock_errno());
692 //WSASetLastError(rc);
693 }
694 else
695 {
696 // translate result to Wsock32-style structure
697 pwhostent->h_name = pHostent->h_name;
698 pwhostent->h_aliases = pHostent->h_aliases;
699 pwhostent->h_addrtype = pHostent->h_addrtype;
700 pwhostent->h_length = pHostent->h_length;
701 pwhostent->h_addr_list = pHostent->h_addr_list;
702 rc = 0;
703 }
704 }
705
706 // post result
707 PostMessageA(pRequest->hwnd,
708 pRequest->ulMessage,
709 (WPARAM)pRequest,
710 (LPARAM)(rc << 16 | usLength));
711
712 // M$ says, if PostMessageA fails, spin as long as window exists
713}
714
715
716/*****************************************************************************
717 * Name :
718 * Purpose :
719 * Parameters:
720 * Variables :
721 * Result :
722 * Remark :
723 * Status : UNTESTED STUB
724 *
725 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
726 *****************************************************************************/
727
728void WSAAsyncWorker::asyncGetHostByName (PASYNCREQUEST pRequest)
729{
730 struct hostent* pHostent;
731 USHORT usLength = sizeof(struct Whostent);
732 USHORT rc;
733 struct Whostent* pwhostent = (struct Whostent*)pRequest->pBuffer;
734
735 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetHostByName (%08xh, %08xh)\n",
736 this,
737 pRequest));
738
739 // result buffer length
740 if (pRequest->ulBufferLength < sizeof(struct Whostent))
741 {
742 rc = WSAEINVAL;
743 //WSASetLastError(rc); // same as Winsock return codes
744 }
745 else
746 {
747 // call API
748 pHostent = gethostbyname((char*)pRequest->ul1);
749 if (pHostent == NULL) // error ?
750 {
751 // build error return code
752 rc = iTranslateSockErrToWSock(sock_errno());
753 //WSASetLastError(rc);
754 }
755 else
756 {
757 // translate result to Wsock32-style structure
758 pwhostent->h_name = pHostent->h_name;
759 pwhostent->h_aliases = pHostent->h_aliases;
760 pwhostent->h_addrtype = pHostent->h_addrtype;
761 pwhostent->h_length = pHostent->h_length;
762 pwhostent->h_addr_list = pHostent->h_addr_list;
763 rc = 0;
764 }
765 }
766
767 // post result
768 PostMessageA(pRequest->hwnd,
769 pRequest->ulMessage,
770 (WPARAM)pRequest,
771 (LPARAM)(rc << 16 | usLength));
772
773 // M$ says, if PostMessageA fails, spin as long as window exists
774}
775
776
777/*****************************************************************************
778 * Name :
779 * Purpose :
780 * Parameters:
781 * Variables :
782 * Result :
783 * Remark :
784 * Status : UNTESTED STUB
785 *
786 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
787 *****************************************************************************/
788
789void WSAAsyncWorker::asyncGetProtoByName (PASYNCREQUEST pRequest)
790{
791 struct protoent* pProtoent;
792 USHORT usLength = sizeof(struct Wprotoent);
793 USHORT rc;
794 struct Wprotoent* pwprotoent= (struct Wprotoent*)pRequest->pBuffer;
795
796 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetProtoByName (%08xh, %08xh)\n",
797 this,
798 pRequest));
799
800 // result buffer length
801 if (pRequest->ulBufferLength < sizeof(struct Wprotoent))
802 {
803 rc = WSAEINVAL;
804 //WSASetLastError(rc); // same as Winsock return codes
805 }
806 else
807 {
808 // call API
809 pProtoent = getprotobyname((char*)pRequest->ul1);
810 if (pProtoent == NULL) // error ?
811 {
812 // build error return code
813 rc = iTranslateSockErrToWSock(sock_errno());
814 //WSASetLastError(rc);
815 }
816 else
817 {
818 // build result buffer
819 pwprotoent->p_name = pProtoent->p_name;
820 pwprotoent->p_aliases = pProtoent->p_aliases;
821 pwprotoent->p_proto = pProtoent->p_proto;
822 rc = 0;
823 }
824 }
825
826 // post result
827 PostMessageA(pRequest->hwnd,
828 pRequest->ulMessage,
829 (WPARAM)pRequest,
830 (LPARAM)(rc << 16 | usLength));
831
832 // M$ says, if PostMessageA fails, spin as long as window exists
833}
834
835
836/*****************************************************************************
837 * Name :
838 * Purpose :
839 * Parameters:
840 * Variables :
841 * Result :
842 * Remark :
843 * Status : UNTESTED STUB
844 *
845 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
846 *****************************************************************************/
847
848void WSAAsyncWorker::asyncGetProtoByNumber(PASYNCREQUEST pRequest)
849{
850 struct protoent* pProtoent;
851 USHORT usLength = sizeof(struct Wprotoent);
852 USHORT rc;
853 struct Wprotoent* pwprotoent= (struct Wprotoent*)pRequest->pBuffer;
854
855 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetProtoByNumber (%08xh, %08xh)\n",
856 this,
857 pRequest));
858
859 // result buffer length
860 if (pRequest->ulBufferLength < sizeof(struct Wprotoent))
861 {
862 rc = WSAEINVAL;
863 //WSASetLastError(rc); // same as Winsock return codes
864 }
865 else
866 {
867 // call API
868 pProtoent = getprotobyname(( char*)pRequest->ul1);
869 if (pProtoent == NULL) // error ?
870 {
871 // build error return code
872 rc = iTranslateSockErrToWSock(sock_errno());
873 //WSASetLastError(rc);
874 }
875 else
876 {
877 // build result buffer
878 pwprotoent->p_name = pProtoent->p_name;
879 pwprotoent->p_aliases = pProtoent->p_aliases;
880 pwprotoent->p_proto = pProtoent->p_proto;
881 rc = 0;
882 }
883 }
884
885 // post result
886 PostMessageA(pRequest->hwnd,
887 pRequest->ulMessage,
888 (WPARAM)pRequest,
889 (LPARAM)(rc << 16 | usLength));
890
891 // M$ says, if PostMessageA fails, spin as long as window exists
892}
893
894
895/*****************************************************************************
896 * Name :
897 * Purpose :
898 * Parameters:
899 * Variables :
900 * Result :
901 * Remark :
902 * Status : UNTESTED STUB
903 *
904 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
905 *****************************************************************************/
906
907void WSAAsyncWorker::asyncGetServByName(PASYNCREQUEST pRequest)
908{
909 struct servent* pServent;
910 USHORT usLength = sizeof(struct Wservent);
911 USHORT rc;
912 struct Wservent* pwservent= (struct Wservent*)pRequest->pBuffer;
913
914 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetServByName (%08xh, %08xh)\n",
915 this,
916 pRequest));
917
918 // result buffer length
919 if (pRequest->ulBufferLength < sizeof(struct Wservent))
920 {
921 rc = WSAEINVAL;
922 //WSASetLastError(rc); // same as Winsock return codes
923 }
924 else
925 {
926 // call API
927 pServent = getservbyname((char*)pRequest->ul1,
928 (char*)pRequest->ul2);
929 if (pServent == NULL) // error ?
930 {
931 // build error return code
932 rc = iTranslateSockErrToWSock(sock_errno());
933 //WSASetLastError(rc);
934 }
935 else
936 {
937 // build result buffer
938 pwservent->s_name = pServent->s_name;
939 pwservent->s_aliases = pServent->s_aliases;
940 pwservent->s_port = pServent->s_port;
941 pwservent->s_proto = pServent->s_proto;
942 rc = 0;
943 }
944 }
945
946 // post result
947 PostMessageA(pRequest->hwnd,
948 pRequest->ulMessage,
949 (WPARAM)pRequest,
950 (LPARAM)(rc << 16 | usLength));
951
952 // M$ says, if PostMessageA fails, spin as long as window exists
953}
954
955
956/*****************************************************************************
957 * Name :
958 * Purpose :
959 * Parameters:
960 * Variables :
961 * Result :
962 * Remark :
963 * Status : UNTESTED STUB
964 *
965 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
966 *****************************************************************************/
967
968void WSAAsyncWorker::asyncGetServByPort(PASYNCREQUEST pRequest)
969{
970 struct servent* pServent;
971 USHORT usLength = sizeof(struct Wservent);
972 USHORT rc;
973 struct Wservent* pwservent= (struct Wservent*)pRequest->pBuffer;
974
975 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetServByPort (%08xh, %08xh)\n",
976 this,
977 pRequest));
978
979 // result buffer length
980 if (pRequest->ulBufferLength < sizeof(struct Whostent))
981 {
982 rc = WSAEINVAL;
983 //WSASetLastError(rc); // same as Winsock return codes
984 }
985 else
986 {
987 // call API
988 pServent = getservbyport((int )pRequest->ul1,
989 (char*)pRequest->ul2);
990 if (pServent == NULL) // error ?
991 {
992 // build error return code
993 rc = iTranslateSockErrToWSock(sock_errno());
994 //WSASetLastError(rc);
995 }
996 else
997 {
998 // build result buffer
999 pwservent->s_name = pServent->s_name;
1000 pwservent->s_aliases = pServent->s_aliases;
1001 pwservent->s_port = pServent->s_port;
1002 pwservent->s_proto = pServent->s_proto;
1003
1004 rc = 0;
1005 }
1006 }
1007
1008 // post result
1009 PostMessageA(pRequest->hwnd,
1010 pRequest->ulMessage,
1011 (WPARAM)pRequest,
1012 (LPARAM)(rc << 16 | usLength));
1013
1014 // M$ says, if PostMessageA fails, spin as long as window exists
1015}
1016
1017
1018
1019/*****************************************************************************
1020 * Name : WSAAsyncWorker::asyncSelect
1021 * Purpose :
1022 * Parameters:
1023 * Variables :
1024 * Result :
1025 * Remark :
1026 * Status : UNTESTED
1027 *
1028 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1029 *****************************************************************************/
1030
1031typedef int SOCKET;
1032
1033void WSAAsyncWorker::asyncSelect(PASYNCREQUEST pRequest)
1034{
1035 ULONG wParam;
1036 ULONG lParam;
1037 int irc;
1038 int iUnknown;
1039
1040 SOCKET sockWin;
1041 ULONG ulEvent;
1042 USHORT usResult = 0;
1043
1044 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncSelect (%08xh, %08xh) not correctly implemented\n",
1045 this,
1046 pRequest));
1047
1048
1049 // setup variables
1050 sockWin = (SOCKET)pRequest->ul1;
1051 ulEvent = (ULONG) pRequest->ul2;
1052
1053 //@@@PH to do
1054 // 1. automatically set socket to non-blocking mode
1055 // 2. loop until WSAAsyncSelect(s,hwnd,0,0) ?
1056
1057
1058 //@@@PH how to implement other events?
1059
1060
1061 // finally do the select!
1062#ifdef BSDSELECT
1063 irc = os2_select(&sockWin,
1064 (ulEvent & FD_READ) ? 1 : 0,
1065 (ulEvent & FD_WRITE) ? 1 : 0,
1066 (ulEvent & FD_OOB) ? 1 : 0,
1067 10000); // @@@PH timeout
1068#else
1069
1070 // BSD implementation
1071 fd_set fds_read, *pfds_read = &fds_read;
1072 fd_set fds_write, *pfds_write = &fds_write;
1073 fd_set fds_exception,*pfds_exception = &fds_exception;
1074 struct timeval tv;
1075
1076 FD_ZERO(&fds_read); FD_SET(sockWin,&fds_read);
1077 FD_ZERO(&fds_write); FD_SET(sockWin,&fds_write);
1078 FD_ZERO(&fds_exception); FD_SET(sockWin,&fds_exception);
1079
1080 tv.tv_sec = 10;
1081 tv.tv_usec = 0;
1082
1083 if (!(ulEvent & FD_READ)) pfds_read = NULL;
1084 if (!(ulEvent & FD_WRITE)) pfds_write = NULL;
1085 if (!(ulEvent & FD_OOB)) pfds_exception = NULL;
1086
1087 irc = bsd_select(sockWin+1,
1088 pfds_read,
1089 pfds_write,
1090 pfds_exception,
1091 &tv);
1092#endif
1093
1094 if (irc < 0) /* an error occurred */
1095 {
1096 lParam = sock_errno(); /* raise error condition */
1097 if (lParam == SOCENOTSOCK)
1098 {
1099 usResult = FD_CLOSE;
1100 lParam = 0;
1101 }
1102 }
1103 else
1104 if (irc == 0) /* this means timeout */
1105 {
1106 lParam = iTranslateSockErrToWSock(WSAETIMEDOUT);/* raise error condition */
1107 }
1108 else
1109 {
1110 //@@@PH check the socket for any event and report!
1111 usResult = 0;
1112
1113 // readiness for reading bytes ?
1114/*
1115 if (FD_ISSET(sockWin, pfds_read)) usResult |= FD_READ;
1116 if (FD_ISSET(sockWin, pfds_write)) usResult |= FD_WRITE;
1117 if (FD_ISSET(sockWin, pfds_exception)) usResult |= FD_OOB;
1118*/
1119
1120/*
1121#define FD_READ 0x01
1122#define FD_WRITE 0x02
1123#define FD_OOB 0x04
1124#define FD_ACCEPT 0x08
1125#define FD_CONNECT 0x10
1126#define FD_CLOSE 0x20
1127*/
1128
1129 irc = ioctl(sockWin, FIONREAD, (char *)&iUnknown, sizeof(iUnknown));
1130 if ( (irc == 0) && (iUnknown > 0))
1131 usResult |= FD_READ | FD_CONNECT;
1132 }
1133
1134 // post result
1135 irc = (LPARAM)((lParam << 16) | usResult);
1136 dprintf(("WSOCK32:asyncSelect() posting %08xh hwnd%08xh, msg=%08xh, wparam=%08xh, lparam=%08xh\n",
1137 pRequest,
1138 pRequest->hwnd,
1139 pRequest->ulMessage,
1140 sockWin,
1141 irc));
1142
1143 PostMessageA(pRequest->hwnd,
1144 pRequest->ulMessage,
1145 (WPARAM)sockWin,
1146 (LPARAM)irc);
1147
1148 // M$ says, if PostMessageA fails, spin as long as window exists
1149}
1150
1151
1152
1153/*****************************************************************************
1154 * Name :
1155 * Purpose :
1156 * Parameters:
1157 * Variables :
1158 * Result :
1159 * Remark :
1160 * Status : UNTESTED STUB
1161 *
1162 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1163 *****************************************************************************/
1164// process one request
1165int WSAAsyncWorker::dispatchRequest(PASYNCREQUEST pRequest)
1166{
1167 int rc;
1168
1169 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::dispatchRequest (%08xh, %08xh)\n",
1170 this,
1171 pRequest));
1172
1173 // check request state first
1174 switch(pRequest->ulState)
1175 {
1176 case RS_WAITING: // OK, proceed
1177 break;
1178
1179 case RS_BUSY: // oops, shouldn't happen
1180 dprintf(("WSOCK32: WSAAsyncWorker::dispatchRequest - got already busy request %08xh\n",
1181 pRequest));
1182 return 1;
1183
1184 case RS_CANCELLED: // don't service request
1185 // request has been removed from queue already
1186 return 1;
1187 }
1188
1189 // OK, servicing request
1190 pRequest->ulState = RS_BUSY;
1191
1192 switch(pRequest->ulType)
1193 {
1194 case WSAASYNC_TERMINATE: // internal message
1195 fTerminate = TRUE;
1196 return 1;
1197
1198 case WSAASYNC_GETHOSTBYADDR: asyncGetHostByAddr (pRequest); rc = 1; break;
1199 case WSAASYNC_GETHOSTBYNAME: asyncGetHostByName (pRequest); rc = 1; break;
1200 case WSAASYNC_GETPROTOBYNAME: asyncGetProtoByName (pRequest); rc = 1; break;
1201 case WSAASYNC_GETPROTOBYNUMBER: asyncGetProtoByNumber(pRequest); rc = 1; break;
1202 case WSAASYNC_GETSERVBYNAME: asyncGetServByName (pRequest); rc = 1; break;
1203 case WSAASYNC_GETSERVBYPORT: asyncGetServByPort (pRequest); rc = 1; break;
1204 case WSAASYNC_SELECT: asyncSelect (pRequest); rc = 1; break;
1205
1206 default:
1207 dprintf(("WSOCK32: WSAAsyncWorker::dispatchRequest - invalid request type %d\n",
1208 pRequest->ulType));
1209 rc = 1; break;
1210 }
1211
1212 pRequest->ulState = RS_DONE;
1213 return rc;
1214}
1215
1216
1217/*****************************************************************************
1218 * Name :
1219 * Purpose :
1220 * Parameters:
1221 * Variables :
1222 * Result :
1223 * Remark :
1224 * Status : UNTESTED STUB
1225 *
1226 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1227 *****************************************************************************/
1228// process all requests in queue until termination
1229void WSAAsyncWorker::processingLoop(void)
1230{
1231 PASYNCREQUEST pRequest;
1232 APIRET rc;
1233 ULONG ulPostCount;
1234
1235 do
1236 {
1237 // work as long as there are requests
1238 do
1239 {
1240 pRequest = popRequest(); // get request from queue
1241 if (pRequest != NULL)
1242 {
1243 dispatchRequest(pRequest); // process request
1244 delete pRequest; // free the memory
1245 }
1246 }
1247 while (pRequest != NULL);
1248
1249 // wait for semaphore
1250 fBlocking = FALSE;
1251 rc = DosWaitEventSem(hevRequest, SEM_INDEFINITE_WAIT);
1252 fBlocking = TRUE;
1253 rc = DosResetEventSem(hevRequest, &ulPostCount);
1254 }
1255 while (fTerminate == FALSE);
1256
1257 tidWorker = 0; // clear worker thread id
1258}
1259
1260
1261/*****************************************************************************
1262 * Name :
1263 * Purpose :
1264 * Parameters:
1265 * Variables :
1266 * Result :
1267 * Remark :
1268 * Status : UNTESTED STUB
1269 *
1270 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1271 *****************************************************************************/
1272// thread procedure
1273void _Optlink WorkerThreadProc(void* pParam)
1274{
1275 // convert object pointer
1276 WSAAsyncWorker* pWSAAsyncWorker = (WSAAsyncWorker*)pParam;
1277 pWSAAsyncWorker->processingLoop(); // processing loop
1278}
1279
1280
1281/*****************************************************************************
1282 * Name :
1283 * Purpose :
1284 * Parameters:
1285 * Variables :
1286 * Result :
1287 * Remark :
1288 * Status : UNTESTED STUB
1289 *
1290 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1291 *****************************************************************************/
1292// the real function calls
1293ODINFUNCTION5(HANDLE, WSAAsyncGetHostByName, HWND, hwnd,
1294 unsigned int, wMsg,
1295 const char*, name,
1296 char*, buf,
1297 int, buflen)
1298{
1299 dprintf(("name = %s\n", name));
1300 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYNAME,
1301 (HWND) hwnd,
1302 (ULONG)wMsg,
1303 (PVOID)buf,
1304 (ULONG)buflen,
1305 (ULONG)name);
1306 if (pRequest != NULL)
1307 {
1308 // success
1309 wsaWorker->pushRequest(pRequest);
1310 WSASetLastError(ERROR_SUCCESS);
1311 return (HANDLE)pRequest;
1312 }
1313 else
1314 {
1315 // error
1316 WSASetLastError(WSAENOBUFS);
1317 return 0;
1318 }
1319}
1320
1321
1322/*****************************************************************************
1323 * Name :
1324 * Purpose :
1325 * Parameters:
1326 * Variables :
1327 * Result :
1328 * Remark :
1329 * Status : UNTESTED STUB
1330 *
1331 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1332 *****************************************************************************/
1333// the real function calls
1334ODINFUNCTION7(HANDLE, WSAAsyncGetHostByAddr, HWND, hwnd,
1335 unsigned int, wMsg,
1336 const char*, addr,
1337 int, len,
1338 int, type,
1339 char*, buf,
1340 int, buflen)
1341{
1342 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYADDR,
1343 (HWND) hwnd,
1344 (ULONG)wMsg,
1345 (PVOID)buf,
1346 (ULONG)buflen,
1347 (ULONG)addr,
1348 (ULONG)len,
1349 (ULONG)type);
1350 if (pRequest != NULL)
1351 {
1352 // success
1353 wsaWorker->pushRequest(pRequest);
1354 WSASetLastError(ERROR_SUCCESS);
1355 return (HANDLE)pRequest;
1356 }
1357 else
1358 {
1359 // error
1360 WSASetLastError(WSAENOBUFS);
1361 return 0;
1362 }
1363}
1364
1365
1366/*****************************************************************************
1367 * Name :
1368 * Purpose :
1369 * Parameters:
1370 * Variables :
1371 * Result :
1372 * Remark :
1373 * Status : UNTESTED STUB
1374 *
1375 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1376 *****************************************************************************/
1377// the real function calls
1378ODINFUNCTION6(HANDLE, WSAAsyncGetServByName, HWND, hwnd,
1379 unsigned int, wMsg,
1380 const char*, name,
1381 const char*, proto,
1382 char*, buf,
1383 int, buflen)
1384{
1385 dprintf(("name = %s, proto = %s\n", name, proto));
1386 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYNAME,
1387 (HWND) hwnd,
1388 (ULONG)wMsg,
1389 (PVOID)buf,
1390 (ULONG)buflen,
1391 (ULONG)name,
1392 (ULONG)proto);
1393 if (pRequest != NULL)
1394 {
1395 // success
1396 wsaWorker->pushRequest(pRequest);
1397 WSASetLastError(ERROR_SUCCESS);
1398 return (HANDLE)pRequest;
1399 }
1400 else
1401 {
1402 // error
1403 WSASetLastError(WSAENOBUFS);
1404 return 0;
1405 }
1406}
1407
1408
1409/*****************************************************************************
1410 * Name :
1411 * Purpose :
1412 * Parameters:
1413 * Variables :
1414 * Result :
1415 * Remark :
1416 * Status : UNTESTED STUB
1417 *
1418 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1419 *****************************************************************************/
1420// the real function calls
1421ODINFUNCTION6(HANDLE, WSAAsyncGetServByPort, HWND, hwnd,
1422 unsigned int, wMsg,
1423 int, port,
1424 const char*, proto,
1425 char*, buf,
1426 int, buflen)
1427{
1428 dprintf(("proto = %s\n", proto));
1429 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYPORT,
1430 (HWND) hwnd,
1431 (ULONG)wMsg,
1432 (PVOID)buf,
1433 (ULONG)buflen,
1434 (ULONG)port,
1435 (ULONG)proto);
1436 if (pRequest != NULL)
1437 {
1438 // success
1439 wsaWorker->pushRequest(pRequest);
1440 WSASetLastError(ERROR_SUCCESS);
1441 return (HANDLE)pRequest;
1442 }
1443 else
1444 {
1445 // error
1446 WSASetLastError(WSAENOBUFS);
1447 return 0;
1448 }
1449}
1450
1451
1452/*****************************************************************************
1453 * Name :
1454 * Purpose :
1455 * Parameters:
1456 * Variables :
1457 * Result :
1458 * Remark :
1459 * Status : UNTESTED STUB
1460 *
1461 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1462 *****************************************************************************/
1463// the real function calls
1464ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByName, HWND, hwnd,
1465 unsigned int, wMsg,
1466 const char*, name,
1467 char*, buf,
1468 int, buflen)
1469{
1470 dprintf(("name = %s\n", name));
1471 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNAME,
1472 (HWND) hwnd,
1473 (ULONG)wMsg,
1474 (PVOID)buf,
1475 (ULONG)buflen,
1476 (ULONG)name);
1477 if (pRequest != NULL)
1478 {
1479 // success
1480 wsaWorker->pushRequest(pRequest);
1481 WSASetLastError(ERROR_SUCCESS);
1482 return (HANDLE)pRequest;
1483 }
1484 else
1485 {
1486 // error
1487 WSASetLastError(WSAENOBUFS);
1488 return 0;
1489 }
1490}
1491
1492
1493/*****************************************************************************
1494 * Name :
1495 * Purpose :
1496 * Parameters:
1497 * Variables :
1498 * Result :
1499 * Remark :
1500 * Status : UNTESTED STUB
1501 *
1502 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1503 *****************************************************************************/
1504// the real function calls
1505ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByNumber, HWND, hwnd,
1506 unsigned int, wMsg,
1507 int, number,
1508 char*, buf,
1509 int, buflen)
1510{
1511 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNUMBER,
1512 (HWND) hwnd,
1513 (ULONG)wMsg,
1514 (PVOID)buf,
1515 (ULONG)buflen,
1516 (ULONG)number);
1517 if (pRequest != NULL)
1518 {
1519 // success
1520 wsaWorker->pushRequest(pRequest);
1521 WSASetLastError(ERROR_SUCCESS);
1522 return (HANDLE)pRequest;
1523 }
1524 else
1525 {
1526 // error
1527 WSASetLastError(WSAENOBUFS);
1528 return 0;
1529 }
1530}
1531
1532
1533/*****************************************************************************
1534 * Name :
1535 * Purpose : cancel a queued or busy request
1536 * Parameters:
1537 * Variables :
1538 * Result :
1539 * Remark :
1540 * Status : UNTESTED STUB
1541 *
1542 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1543 *****************************************************************************/
1544
1545ODINFUNCTION1(int, WSACancelAsyncRequest, HANDLE, hAsyncTaskHandle)
1546{
1547 PASYNCREQUEST pRequest = (PASYNCREQUEST)hAsyncTaskHandle;
1548 BOOL rc;
1549
1550 // remove request from queue
1551 rc = wsaWorker->cancelAsyncRequest(pRequest);
1552 if (rc == TRUE)
1553 {
1554 WSASetLastError(ERROR_SUCCESS);
1555 return ERROR_SUCCESS; // success
1556 }
1557 else
1558 {
1559 // error
1560 WSASetLastError(WSAEINVAL);
1561 return (SOCKET_ERROR);
1562 }
1563}
1564
1565
1566/*****************************************************************************
1567 * Name : WSAIsBlocking
1568 * Purpose :
1569 * Parameters:
1570 * Variables :
1571 * Result :
1572 * Remark :
1573 * Status : UNTESTED STUB
1574 *
1575 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1576 *****************************************************************************/
1577
1578ODINFUNCTION0(BOOL, WSAIsBlocking)
1579{
1580 return(wsaWorker->isBlocking());
1581}
1582
1583
1584/*****************************************************************************
1585 * Name :
1586 * Purpose :
1587 * Parameters:
1588 * Variables :
1589 * Result :
1590 * Remark :
1591 * Status : UNTESTED STUB
1592 *
1593 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1594 *****************************************************************************/
1595// the real function calls
1596
1597ODINFUNCTION4(int, WSAAsyncSelect,SOCKET, s,
1598 HWND, hwnd,
1599 unsigned int, wMsg,
1600 long, lEvent)
1601{
1602 // @@@PH 1999/11/21 implementation is completely wrong!
1603 // handle async select in a completely different way:
1604 // one thread per socket!
1605 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_SELECT,
1606 (HWND) hwnd,
1607 (ULONG)wMsg,
1608 (PVOID)NULL,
1609 (ULONG)0,
1610 (ULONG)s,
1611 (ULONG)lEvent);
1612 if (pRequest != NULL) // request is OK ?
1613 {
1614 wsaWorker->pushRequest(pRequest);
1615
1616 // WSAAsyncSelect() can only fail if the flags specified don't match
1617 WSASetLastError(ERROR_SUCCESS);
1618 return ERROR_SUCCESS;
1619 }
1620 else
1621 {
1622 // error !
1623 WSASetLastError(WSAEINVAL);
1624 return SOCKET_ERROR;
1625 }
1626}
1627
Note: See TracBrowser for help on using the repository browser.