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