xref: /reactos/dll/win32/msafd/misc/event.c (revision 8540ab04)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS Ancillary Function Driver DLL
4  * FILE:        dll/win32/msafd/misc/event.c
5  * PURPOSE:     Event handling
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  *              Alex Ionescu (alex@relsoft.net)
8  * REVISIONS:
9  *   CSH  15/06/2001 - Created
10  *   Alex 16/07/2004 - Complete Rewrite
11  */
12 
13 #include <msafd.h>
14 
15 int
16 WSPAPI
17 WSPEventSelect(
18     IN SOCKET Handle,
19     IN WSAEVENT hEventObject,
20     IN long lNetworkEvents,
21     OUT LPINT lpErrno)
22 {
23     IO_STATUS_BLOCK        IOSB;
24     AFD_EVENT_SELECT_INFO  EventSelectInfo;
25     PSOCKET_INFORMATION    Socket = NULL;
26     NTSTATUS               Status;
27     BOOLEAN                BlockMode;
28     HANDLE                 SockEvent;
29 
30     TRACE("WSPEventSelect (%lx) %lx %lx\n", Handle, hEventObject, lNetworkEvents);
31 
32     /* Get the Socket Structure associate to this Socket*/
33     Socket = GetSocketStructure(Handle);
34     if (!Socket)
35     {
36         if (lpErrno) *lpErrno = WSAENOTSOCK;
37         return SOCKET_ERROR;
38     }
39 
40     Status = NtCreateEvent(&SockEvent, EVENT_ALL_ACCESS,
41                            NULL, SynchronizationEvent, FALSE);
42 
43     if (!NT_SUCCESS(Status)) return SOCKET_ERROR;
44 
45     /* Set Socket to Non-Blocking */
46     BlockMode = TRUE;
47     SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL, NULL, NULL);
48     Socket->SharedData->NonBlocking = TRUE;
49 
50     /* Deactivate Async Select if there is one */
51     if (Socket->EventObject) {
52         Socket->SharedData->hWnd = NULL;
53         Socket->SharedData->wMsg = 0;
54         Socket->SharedData->AsyncEvents = 0;
55         Socket->SharedData->SequenceNumber++; // This will kill Async Select after the next completion
56     }
57 
58     /* Set Structure Info */
59     EventSelectInfo.EventObject = hEventObject;
60     EventSelectInfo.Events = 0;
61 
62     /* Set Events to wait for */
63     if (lNetworkEvents & FD_READ) {
64         EventSelectInfo.Events |= AFD_EVENT_RECEIVE;
65     }
66 
67     if (lNetworkEvents & FD_WRITE) {
68         EventSelectInfo.Events |= AFD_EVENT_SEND;
69     }
70 
71     if (lNetworkEvents & FD_OOB) {
72         EventSelectInfo.Events |= AFD_EVENT_OOB_RECEIVE;
73     }
74 
75     if (lNetworkEvents & FD_ACCEPT) {
76         EventSelectInfo.Events |= AFD_EVENT_ACCEPT;
77     }
78 
79     if (lNetworkEvents & FD_CONNECT) {
80         EventSelectInfo.Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
81     }
82 
83     if (lNetworkEvents & FD_CLOSE) {
84         EventSelectInfo.Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
85     }
86 
87     if (lNetworkEvents & FD_QOS) {
88         EventSelectInfo.Events |= AFD_EVENT_QOS;
89     }
90 
91     if (lNetworkEvents & FD_GROUP_QOS) {
92         EventSelectInfo.Events |= AFD_EVENT_GROUP_QOS;
93     }
94 
95     /* Send IOCTL */
96     Status = NtDeviceIoControlFile((HANDLE)Handle,
97                                    SockEvent,
98                                    NULL,
99                                    NULL,
100                                    &IOSB,
101                                    IOCTL_AFD_EVENT_SELECT,
102                                    &EventSelectInfo,
103                                    sizeof(EventSelectInfo),
104                                    NULL,
105                                    0);
106 
107     /* Wait for return */
108     if (Status == STATUS_PENDING) {
109         WaitForSingleObject(SockEvent, INFINITE);
110         Status = IOSB.Status;
111     }
112 
113     NtClose (SockEvent);
114 
115     if (Status != STATUS_SUCCESS)
116     {
117         ERR("Got status 0x%08x.\n", Status);
118         return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
119     }
120 
121     /* Set Socket Data*/
122     Socket->EventObject = hEventObject;
123     Socket->NetworkEvents = lNetworkEvents;
124 
125     TRACE("Leaving\n");
126 
127     return 0;
128 }
129 
130 
131 INT
132 WSPAPI
133 WSPEnumNetworkEvents(
134     IN  SOCKET Handle,
135     IN  WSAEVENT hEventObject,
136     OUT LPWSANETWORKEVENTS lpNetworkEvents,
137     OUT LPINT lpErrno)
138 {
139     AFD_ENUM_NETWORK_EVENTS_INFO EnumReq;
140     IO_STATUS_BLOCK              IOSB;
141     PSOCKET_INFORMATION          Socket = NULL;
142     NTSTATUS                     Status;
143     HANDLE                       SockEvent;
144 
145     TRACE("Called (lpNetworkEvents %x)\n", lpNetworkEvents);
146 
147     /* Get the Socket Structure associate to this Socket*/
148     Socket = GetSocketStructure(Handle);
149     if (!Socket)
150     {
151        if (lpErrno) *lpErrno = WSAENOTSOCK;
152        return SOCKET_ERROR;
153     }
154     if (!lpNetworkEvents)
155     {
156        if (lpErrno) *lpErrno = WSAEFAULT;
157        return SOCKET_ERROR;
158     }
159 
160     Status = NtCreateEvent(&SockEvent, EVENT_ALL_ACCESS,
161                            NULL, SynchronizationEvent, FALSE);
162 
163     if( !NT_SUCCESS(Status) ) {
164         ERR("Could not make an event %x\n", Status);
165         return SOCKET_ERROR;
166     }
167 
168     EnumReq.Event = hEventObject;
169 
170     /* Send IOCTL */
171     Status = NtDeviceIoControlFile((HANDLE)Handle,
172                                    SockEvent,
173                                    NULL,
174                                    NULL,
175                                    &IOSB,
176                                    IOCTL_AFD_ENUM_NETWORK_EVENTS,
177                                    &EnumReq,
178                                    sizeof(EnumReq),
179                                    NULL,
180                                    0);
181 
182     /* Wait for return */
183     if (Status == STATUS_PENDING) {
184         WaitForSingleObject(SockEvent, INFINITE);
185         Status = IOSB.Status;
186     }
187 
188     NtClose (SockEvent);
189 
190     if (Status != STATUS_SUCCESS)
191     {
192         ERR("Status 0x%08x", Status);
193         return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
194     }
195 
196     lpNetworkEvents->lNetworkEvents = 0;
197 
198     /* Set Events to wait for */
199     if (EnumReq.PollEvents & AFD_EVENT_RECEIVE) {
200         lpNetworkEvents->lNetworkEvents |= FD_READ;
201         lpNetworkEvents->iErrorCode[FD_READ_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_READ_BIT]);
202     }
203 
204     if (EnumReq.PollEvents & AFD_EVENT_SEND) {
205         lpNetworkEvents->lNetworkEvents |= FD_WRITE;
206         lpNetworkEvents->iErrorCode[FD_WRITE_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_WRITE_BIT]);
207     }
208 
209     if (EnumReq.PollEvents & AFD_EVENT_OOB_RECEIVE) {
210         lpNetworkEvents->lNetworkEvents |= FD_OOB;
211         lpNetworkEvents->iErrorCode[FD_OOB_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_OOB_BIT]);
212     }
213 
214     if (EnumReq.PollEvents & AFD_EVENT_ACCEPT) {
215         lpNetworkEvents->lNetworkEvents |= FD_ACCEPT;
216         lpNetworkEvents->iErrorCode[FD_ACCEPT_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_ACCEPT_BIT]);
217     }
218 
219     if (EnumReq.PollEvents &
220             (AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL)) {
221         lpNetworkEvents->lNetworkEvents |= FD_CONNECT;
222         lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_CONNECT_BIT]);
223     }
224 
225     if (EnumReq.PollEvents &
226             (AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE)) {
227         lpNetworkEvents->lNetworkEvents |= FD_CLOSE;
228         lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_CLOSE_BIT]);
229     }
230 
231     if (EnumReq.PollEvents & AFD_EVENT_QOS) {
232         lpNetworkEvents->lNetworkEvents |= FD_QOS;
233         lpNetworkEvents->iErrorCode[FD_QOS_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_QOS_BIT]);
234     }
235 
236     if (EnumReq.PollEvents & AFD_EVENT_GROUP_QOS) {
237         lpNetworkEvents->lNetworkEvents |= FD_GROUP_QOS;
238         lpNetworkEvents->iErrorCode[FD_GROUP_QOS_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_GROUP_QOS_BIT]);
239     }
240 
241     TRACE("Leaving\n");
242 
243     return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, NULL);
244 }
245 
246 /* EOF */
247