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