xref: /reactos/dll/win32/ws2help/handle.c (revision 9393fc32)
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