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