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