1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
4 * FILE: dll/win32/ws2help/handle.c
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
ApcThread(ULONG_PTR Context)44 ApcThread(ULONG_PTR Context)
45 {
46
47 }
48
49 NTSTATUS
50 WINAPI
DoSocketCancel(PVOID Context1,PVOID Context2,PVOID Context3)51 DoSocketCancel(PVOID Context1,
52 PVOID Context2,
53 PVOID Context3)
54 {
55 return STATUS_SUCCESS;
56 }
57
58 NTSTATUS
59 WINAPI
DoSocketRequest(PVOID Context1,PVOID Context2,PVOID Context3)60 DoSocketRequest(PVOID Context1,
61 PVOID Context2,
62 PVOID Context3)
63 {
64 return STATUS_SUCCESS;
65 }
66
67 VOID
68 CALLBACK
ExitThreadApc(ULONG_PTR Context)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
WahCloseHandleHelper(IN HANDLE HelperHandle)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
WahCloseSocketHandle(IN HANDLE HelperHandle,IN SOCKET Socket)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
WahCreateSocketHandle(IN HANDLE HelperHandle,OUT SOCKET * Socket)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
WahDisableNonIFSHandleSupport(VOID)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 service */
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
WahEnableNonIFSHandleSupport(VOID)291 WahEnableNonIFSHandleSupport(VOID)
292 {
293 return 0;
294 }
295
296 DWORD
297 WINAPI
WahOpenHandleHelper(OUT PHANDLE HelperHandle)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 error code */
429 ErrorCode = GetLastError();
430 }
431
432 /* Return to caller */
433 return ErrorCode;
434 }
435
436 DWORD
437 WINAPI
WahCompleteRequest(IN HANDLE HelperHandle,IN SOCKET Socket,IN LPWSAOVERLAPPED lpOverlapped,IN DWORD ErrorCode,IN DWORD BytesTransferred)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 */
453