* Sync up to trunk head (r64377).
[reactos.git] / dll / win32 / ws2help / handle.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
4 * FILE: include/ws2_32.h
5 * PURPOSE: WinSock 2 DLL header
6 */
7
8 /* INCLUDES ******************************************************************/
9
10 #include "precomp.h"
11
12 #include <ndk/iofuncs.h>
13
14 #include "wshdrv.h"
15
16 /* DATA **********************************************************************/
17
18 typedef struct _WSH_HELPER_CONTEXT
19 {
20 HANDLE FileHandle;
21 HANDLE ThreadHandle;
22 HANDLE DllHandle;
23 } WSH_HELPER_CONTEXT, *PWAH_HELPER_CONTEXT;
24
25 LPFN_WSASEND pWSASend;
26 LPFN_WSARECV pWSARecv;
27 LPFN_WSASENDTO pWSASendTo;
28 LPFN_WSARECVFROM pWSARecvFrom;
29 LPFN_WSAGETLASTERROR pWSAGetLastError;
30 LPFN_WSACANCELBLOCKINGCALL pWSACancelBlockingCall;
31 LPFN_WSASETBLOCKINGHOOK pWSASetBlockingHook;
32 LPFN_SELECT pSelect;
33 LPFN_WSASTARTUP pWSAStartup;
34 LPFN_WSACLEANUP pWSACleanup;
35 LPFN_GETSOCKOPT pGetSockOpt;
36 LPFN_WSAIOCTL pWSAIoctl;
37
38 #define APCH (HANDLE)'SOR '
39
40 /* FUNCTIONS *****************************************************************/
41
42 VOID
43 CALLBACK
44 ApcThread(ULONG_PTR Context)
45 {
46
47 }
48
49 NTSTATUS
50 WINAPI
51 DoSocketCancel(PVOID Context1,
52 PVOID Context2,
53 PVOID Context3)
54 {
55 return STATUS_SUCCESS;
56 }
57
58 NTSTATUS
59 WINAPI
60 DoSocketRequest(PVOID Context1,
61 PVOID Context2,
62 PVOID Context3)
63 {
64 return STATUS_SUCCESS;
65 }
66
67 VOID
68 CALLBACK
69 ExitThreadApc(ULONG_PTR Context)
70 {
71 PWAH_HELPER_CONTEXT HelperContext = (PWAH_HELPER_CONTEXT)Context;
72 HMODULE DllHandle = HelperContext->DllHandle;
73
74 /* Close the file handle */
75 CloseHandle(HelperContext->FileHandle);
76
77 /* Free the context */
78 HeapFree(GlobalHeap, 0, HelperContext);
79
80 /* Exit the thread and library */
81 FreeLibraryAndExitThread(DllHandle, ERROR_SUCCESS);
82 }
83
84 DWORD
85 WINAPI
86 WahCloseHandleHelper(IN HANDLE HelperHandle)
87 {
88 DWORD ErrorCode;
89 PWAH_HELPER_CONTEXT Context = HelperHandle;
90
91 /* Enter the prolog, make sure we're initialized */
92 ErrorCode = WS2HELP_PROLOG();
93 if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
94
95 /* Validate the handle */
96 if (!Context) return ERROR_INVALID_PARAMETER;
97
98 /* Queue an APC to exit the thread */
99 if (QueueUserAPC(ExitThreadApc, Context->ThreadHandle, (ULONG_PTR)Context))
100 {
101 /* Done */
102 return ERROR_SUCCESS;
103 }
104 else
105 {
106 /* We failed somewhere */
107 return ERROR_GEN_FAILURE;
108 }
109 }
110
111 DWORD
112 WINAPI
113 WahCloseSocketHandle(IN HANDLE HelperHandle,
114 IN SOCKET Socket)
115 {
116 DWORD ErrorCode;
117 PWAH_HELPER_CONTEXT Context = HelperHandle;
118
119 /* Enter the prolog, make sure we're initialized */
120 ErrorCode = WS2HELP_PROLOG();
121 if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
122
123 /* Validate the handle */
124 if (!(Context) || (Socket == INVALID_SOCKET) || !(Socket))
125 {
126 /* Invalid handle and/or socket */
127 return ERROR_INVALID_PARAMETER;
128 }
129
130 /* Just close the handle and return */
131 CloseHandle((HANDLE)Socket);
132 return ERROR_SUCCESS;
133 }
134
135 DWORD
136 WINAPI
137 WahCreateSocketHandle(IN HANDLE HelperHandle,
138 OUT SOCKET *Socket)
139 {
140 DWORD ErrorCode;
141 INT OpenType;
142 DWORD Size = sizeof(OpenType);
143 DWORD CreateOptions = 0;
144 UNICODE_STRING Name;
145 OBJECT_ATTRIBUTES ObjectAttributes;
146 PFILE_FULL_EA_INFORMATION Ea;
147 PWAH_EA_DATA EaData;
148 CHAR EaBuffer[sizeof(*Ea) + sizeof(*EaData)];
149 NTSTATUS Status;
150 IO_STATUS_BLOCK IoStatusBlock;
151 PWAH_HELPER_CONTEXT Context = (PWAH_HELPER_CONTEXT)HelperHandle;
152
153 /* Enter the prolog, make sure we're initialized */
154 ErrorCode = WS2HELP_PROLOG();
155 if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
156
157 /* Validate the handle and pointer */
158 if (!(Context) || !(Socket))
159 {
160 /* Invalid handle and/or socket */
161 return ERROR_INVALID_PARAMETER;
162 }
163
164 /* Set pointer to EA */
165 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
166
167 /* Get the open type to determine the create options */
168 if ((pGetSockOpt(INVALID_SOCKET,
169 SOL_SOCKET,
170 SO_OPENTYPE,
171 (PCHAR)&OpenType,
172 (INT FAR*)&Size) == ERROR_SUCCESS) && (OpenType))
173 {
174 /* This is a sync open */
175 CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT;
176 }
177
178 /* Initialize the attributes for the driver */
179 RtlInitUnicodeString(&Name, L"\\Device\\WS2IFSL\\NifsSct");
180 InitializeObjectAttributes(&ObjectAttributes,
181 &Name,
182 0,
183 NULL,
184 NULL);
185
186 /* Set up the EA */
187 Ea->NextEntryOffset = 0;
188 Ea->Flags = 0;
189 Ea->EaNameLength = sizeof("NifsSct");
190 Ea->EaValueLength = sizeof(*EaData);
191 RtlCopyMemory(Ea->EaName, "NifsSct", Ea->EaNameLength);
192
193 /* Get our EA data */
194 EaData = (PWAH_EA_DATA)(Ea + 1);
195
196 /* Write the EA Data */
197 EaData->FileHandle = Context->FileHandle;
198 EaData->Context = NULL;
199
200 /* Call the driver */
201 Status = NtCreateFile((PHANDLE)Socket,
202 FILE_ALL_ACCESS,
203 &ObjectAttributes,
204 &IoStatusBlock,
205 NULL,
206 FILE_ATTRIBUTE_NORMAL,
207 0,
208 FILE_OPEN_IF,
209 CreateOptions,
210 Ea,
211 sizeof(*Ea) + sizeof(*EaData));
212
213 /* Check for success */
214 if (NT_SUCCESS(Status))
215 {
216 /* Write the socket handle */
217 EaData->Context =(HANDLE)*Socket;
218
219 /* Tell the driver about it */
220 if (DeviceIoControl((HANDLE)*Socket,
221 IOCTL_WS2IFSL_SET_HANDLE,
222 &EaData,
223 sizeof(WSH_EA_DATA),
224 NULL,
225 0,
226 &Size,
227 NULL))
228 {
229 /* Set success */
230 ErrorCode = NO_ERROR;
231 }
232 else
233 {
234 /* We failed. Get the error and close the socket */
235 ErrorCode = GetLastError();
236 CloseHandle((HANDLE)*Socket);
237 *Socket = 0;
238 }
239 }
240 else
241 {
242 /* Create file failed, conver error code */
243 ErrorCode = RtlNtStatusToDosError(Status);
244 }
245
246 /* Return to caller */
247 return ErrorCode;
248 }
249
250 INT
251 WINAPI
252 WahDisableNonIFSHandleSupport(VOID)
253 {
254 DWORD ErrorCode;
255 SC_HANDLE ServiceMgrHandle, Ws2IfsHandle;
256
257 /* Enter the prolog, make sure we're initialized */
258 ErrorCode = WS2HELP_PROLOG();
259 if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
260
261 /* Open the service DB */
262 ServiceMgrHandle = OpenSCManager(NULL,
263 SERVICES_ACTIVE_DATABASE,
264 SC_MANAGER_CREATE_SERVICE);
265 if (!ServiceMgrHandle) return GetLastError();
266
267 /* Open the service */
268 Ws2IfsHandle = OpenService(ServiceMgrHandle, "WS2IFSL", SERVICE_ALL_ACCESS);
269
270 /* Disable the servce */
271 ChangeServiceConfig(Ws2IfsHandle,
272 SERVICE_NO_CHANGE,
273 SERVICE_DISABLED,
274 SERVICE_NO_CHANGE,
275 NULL,
276 NULL,
277 NULL,
278 NULL,
279 NULL,
280 NULL,
281 NULL);
282
283 /* Close the handles and return */
284 CloseServiceHandle(ServiceMgrHandle);
285 CloseServiceHandle(Ws2IfsHandle);
286 return ERROR_SUCCESS;
287 }
288
289 INT
290 WINAPI
291 WahEnableNonIFSHandleSupport(VOID)
292 {
293 return 0;
294 }
295
296 DWORD
297 WINAPI
298 WahOpenHandleHelper(OUT PHANDLE HelperHandle)
299 {
300 DWORD ErrorCode;
301 HINSTANCE hWs2_32;
302 UNICODE_STRING Name;
303 OBJECT_ATTRIBUTES ObjectAttributes;
304 PFILE_FULL_EA_INFORMATION Ea;
305 PWAH_EA_DATA2 EaData;
306 CHAR EaBuffer[sizeof(*Ea) + sizeof(*EaData)];
307 NTSTATUS Status;
308 IO_STATUS_BLOCK IoStatusBlock;
309 DWORD Tid;
310 PWAH_HELPER_CONTEXT Context;
311
312 /* Enter the prolog, make sure we're initialized */
313 ErrorCode = WS2HELP_PROLOG();
314 if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
315
316 /* Validate the pointer */
317 if (!HelperHandle)
318 {
319 /* Invalid handle and/or socket */
320 return ERROR_INVALID_PARAMETER;
321 }
322
323 /* Get ws2_32.dll's handle. We don't load it: it MUST be here */
324 hWs2_32 = GetModuleHandle ("WS2_32.DLL");
325 if (!hWs2_32) return WSASYSCALLFAILURE;
326
327 /* Dynamically load all its APIs */
328 if (!((pGetSockOpt = (LPFN_GETSOCKOPT)GetProcAddress(hWs2_32, "getsockopt"))) ||
329 !((pSelect = (LPFN_SELECT)GetProcAddress(hWs2_32, "select"))) ||
330 !((pWSACancelBlockingCall = (LPFN_WSACANCELBLOCKINGCALL)GetProcAddress(hWs2_32, "WSACancelBlockingCall"))) ||
331 !((pWSACleanup = (LPFN_WSACLEANUP)GetProcAddress(hWs2_32, "WSACleanup"))) ||
332 !((pWSAGetLastError = (LPFN_WSAGETLASTERROR)GetProcAddress(hWs2_32, "WSAGetLastError"))) ||
333 !((pWSASetBlockingHook = (LPFN_WSASETBLOCKINGHOOK)GetProcAddress(hWs2_32, "WSASetBlockingHook"))) ||
334 !((pWSARecv = (LPFN_WSARECV)GetProcAddress(hWs2_32, "WSARecv"))) ||
335 !((pWSASend = (LPFN_WSASEND)GetProcAddress(hWs2_32, "WSASend"))) ||
336 !((pWSASendTo = (LPFN_WSASENDTO)GetProcAddress(hWs2_32, "WSASendTo"))) ||
337 !((pWSAStartup = (LPFN_WSASTARTUP)GetProcAddress(hWs2_32, "WSAStartup"))) ||
338 !((pWSARecvFrom = (LPFN_WSARECVFROM)GetProcAddress(hWs2_32, "WSARecvFrom"))) ||
339 !((pWSAIoctl = (LPFN_WSAIOCTL)GetProcAddress(hWs2_32, "WSAIoctl"))))
340 {
341 /* Uh, guess we failed somewhere */
342 return WSASYSCALLFAILURE;
343 }
344
345 /* Set pointer EA structure */
346 Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
347
348 /* Create the helper context */
349 Context = HeapAlloc(GlobalHeap, 0, sizeof(WSH_HELPER_CONTEXT));
350 if (Context)
351 {
352 /* Create the special request thread */
353 Context->ThreadHandle = CreateThread(NULL,
354 0,
355 (PVOID)ApcThread,
356 Context,
357 CREATE_SUSPENDED,
358 &Tid);
359 if (Context->ThreadHandle)
360 {
361 /* Create the attributes for the driver open */
362 RtlInitUnicodeString(&Name, L"\\Device\\WS2IFSL\\NifsPvd");
363 InitializeObjectAttributes(&ObjectAttributes,
364 &Name,
365 0,
366 NULL,
367 NULL);
368
369 /* Setup the EA */
370 Ea->NextEntryOffset = 0;
371 Ea->Flags = 0;
372 Ea->EaNameLength = sizeof("NifsPvd");
373 Ea->EaValueLength = sizeof(*EaData);
374 RtlCopyMemory(Ea->EaName, "NifsPvd", Ea->EaNameLength);
375
376 /* Get our EA data */
377 EaData = (PWAH_EA_DATA2)(Ea + 1);
378
379 /* Fill out the EA Data */
380 EaData->ThreadHandle = Context->ThreadHandle;
381 EaData->RequestRoutine = DoSocketRequest;
382 EaData->CancelRoutine = DoSocketCancel;
383 EaData->ApcContext = Context;
384 EaData->Reserved = 0;
385
386 /* Call the driver */
387 Status = NtCreateFile(&Context->FileHandle,
388 FILE_ALL_ACCESS,
389 &ObjectAttributes,
390 &IoStatusBlock,
391 NULL,
392 FILE_ATTRIBUTE_NORMAL,
393 0,
394 FILE_OPEN_IF,
395 0,
396 Ea,
397 sizeof(*Ea) + sizeof(*EaData));
398
399 /* Check for success */
400 if (NT_SUCCESS(Status))
401 {
402 /* Resume the thread and return a handle to the context */
403 ResumeThread(Context->ThreadHandle);
404 *HelperHandle = (HANDLE)Context;
405 return ERROR_SUCCESS;
406 }
407 else
408 {
409 /* Get the error code */
410 ErrorCode = RtlNtStatusToDosError(Status);
411 }
412
413 /* We failed, mark us as such */
414 Context->FileHandle = NULL;
415 ResumeThread(Context->ThreadHandle);
416 }
417 else
418 {
419 /* Get the error code */
420 ErrorCode = GetLastError();
421 }
422
423 /* If we got here, we failed, so free the context */
424 HeapFree(GlobalHeap, 0, Context);
425 }
426 else
427 {
428 /* Get the errror code */
429 ErrorCode = GetLastError();
430 }
431
432 /* Return to caller */
433 return ErrorCode;
434 }
435
436 DWORD
437 WINAPI
438 WahCompleteRequest(IN HANDLE HelperHandle,
439 IN SOCKET Socket,
440 IN LPWSAOVERLAPPED lpOverlapped,
441 IN DWORD ErrorCode,
442 IN DWORD BytesTransferred)
443 {
444 UNREFERENCED_PARAMETER(HelperHandle);
445 UNREFERENCED_PARAMETER(Socket);
446 UNREFERENCED_PARAMETER(lpOverlapped);
447 UNREFERENCED_PARAMETER(ErrorCode);
448 UNREFERENCED_PARAMETER(BytesTransferred);
449 return ERROR_SUCCESS;
450 }
451
452 /* EOF */