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