xref: /reactos/dll/win32/ws2help/handle.c (revision 682f85ad)
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
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 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
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 error 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 */
453