reactos/dll/win32/ws2help/handle.c

453 lines
13 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/ws2_32.h
* PURPOSE: WinSock 2 DLL header
*/
/* INCLUDES ******************************************************************/
#include "precomp.h"
#include <ndk/iofuncs.h>
#include "wshdrv.h"
/* DATA **********************************************************************/
typedef struct _WSH_HELPER_CONTEXT
{
HANDLE FileHandle;
HANDLE ThreadHandle;
HANDLE DllHandle;
} WSH_HELPER_CONTEXT, *PWAH_HELPER_CONTEXT;
LPFN_WSASEND pWSASend;
LPFN_WSARECV pWSARecv;
LPFN_WSASENDTO pWSASendTo;
LPFN_WSARECVFROM pWSARecvFrom;
LPFN_WSAGETLASTERROR pWSAGetLastError;
LPFN_WSACANCELBLOCKINGCALL pWSACancelBlockingCall;
LPFN_WSASETBLOCKINGHOOK pWSASetBlockingHook;
LPFN_SELECT pSelect;
LPFN_WSASTARTUP pWSAStartup;
LPFN_WSACLEANUP pWSACleanup;
LPFN_GETSOCKOPT pGetSockOpt;
LPFN_WSAIOCTL pWSAIoctl;
#define APCH (HANDLE)'SOR '
/* FUNCTIONS *****************************************************************/
VOID
CALLBACK
ApcThread(ULONG_PTR Context)
{
}
NTSTATUS
WINAPI
DoSocketCancel(PVOID Context1,
PVOID Context2,
PVOID Context3)
{
return STATUS_SUCCESS;
}
NTSTATUS
WINAPI
DoSocketRequest(PVOID Context1,
PVOID Context2,
PVOID Context3)
{
return STATUS_SUCCESS;
}
VOID
CALLBACK
ExitThreadApc(ULONG_PTR Context)
{
PWAH_HELPER_CONTEXT HelperContext = (PWAH_HELPER_CONTEXT)Context;
HMODULE DllHandle = HelperContext->DllHandle;
/* Close the file handle */
CloseHandle(HelperContext->FileHandle);
/* Free the context */
HeapFree(GlobalHeap, 0, HelperContext);
/* Exit the thread and library */
FreeLibraryAndExitThread(DllHandle, ERROR_SUCCESS);
}
DWORD
WINAPI
WahCloseHandleHelper(IN HANDLE HelperHandle)
{
DWORD ErrorCode;
PWAH_HELPER_CONTEXT Context = HelperHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the handle */
if (!Context) return ERROR_INVALID_PARAMETER;
/* Queue an APC to exit the thread */
if (QueueUserAPC(ExitThreadApc, Context->ThreadHandle, (ULONG_PTR)Context))
{
/* Done */
return ERROR_SUCCESS;
}
else
{
/* We failed somewhere */
return ERROR_GEN_FAILURE;
}
}
DWORD
WINAPI
WahCloseSocketHandle(IN HANDLE HelperHandle,
IN SOCKET Socket)
{
DWORD ErrorCode;
PWAH_HELPER_CONTEXT Context = HelperHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the handle */
if (!(Context) || (Socket == INVALID_SOCKET) || !(Socket))
{
/* Invalid handle and/or socket */
return ERROR_INVALID_PARAMETER;
}
/* Just close the handle and return */
CloseHandle((HANDLE)Socket);
return ERROR_SUCCESS;
}
DWORD
WINAPI
WahCreateSocketHandle(IN HANDLE HelperHandle,
OUT SOCKET *Socket)
{
DWORD ErrorCode;
INT OpenType;
DWORD Size = sizeof(OpenType);
DWORD CreateOptions = 0;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
PFILE_FULL_EA_INFORMATION Ea;
PWAH_EA_DATA EaData;
CHAR EaBuffer[sizeof(*Ea) + sizeof(*EaData)];
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
PWAH_HELPER_CONTEXT Context = (PWAH_HELPER_CONTEXT)HelperHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the handle and pointer */
if (!(Context) || !(Socket))
{
/* Invalid handle and/or socket */
return ERROR_INVALID_PARAMETER;
}
/* Set pointer to EA */
Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
/* Get the open type to determine the create options */
if ((pGetSockOpt(INVALID_SOCKET,
SOL_SOCKET,
SO_OPENTYPE,
(PCHAR)&OpenType,
(INT FAR*)&Size) == ERROR_SUCCESS) && (OpenType))
{
/* This is a sync open */
CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT;
}
/* Initialize the attributes for the driver */
RtlInitUnicodeString(&Name, L"\\Device\\WS2IFSL\\NifsSct");
InitializeObjectAttributes(&ObjectAttributes,
&Name,
0,
NULL,
NULL);
/* Set up the EA */
Ea->NextEntryOffset = 0;
Ea->Flags = 0;
Ea->EaNameLength = sizeof("NifsSct");
Ea->EaValueLength = sizeof(*EaData);
RtlCopyMemory(Ea->EaName, "NifsSct", Ea->EaNameLength);
/* Get our EA data */
EaData = (PWAH_EA_DATA)(Ea + 1);
/* Write the EA Data */
EaData->FileHandle = Context->FileHandle;
EaData->Context = NULL;
/* Call the driver */
Status = NtCreateFile((PHANDLE)Socket,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
CreateOptions,
Ea,
sizeof(*Ea) + sizeof(*EaData));
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Write the socket handle */
EaData->Context =(HANDLE)*Socket;
/* Tell the driver about it */
if (DeviceIoControl((HANDLE)*Socket,
IOCTL_WS2IFSL_SET_HANDLE,
&EaData,
sizeof(WSH_EA_DATA),
NULL,
0,
&Size,
NULL))
{
/* Set success */
ErrorCode = NO_ERROR;
}
else
{
/* We failed. Get the error and close the socket */
ErrorCode = GetLastError();
CloseHandle((HANDLE)*Socket);
*Socket = 0;
}
}
else
{
/* Create file failed, conver error code */
ErrorCode = RtlNtStatusToDosError(Status);
}
/* Return to caller */
return ErrorCode;
}
INT
WINAPI
WahDisableNonIFSHandleSupport(VOID)
{
DWORD ErrorCode;
SC_HANDLE ServiceMgrHandle, Ws2IfsHandle;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Open the service DB */
ServiceMgrHandle = OpenSCManager(NULL,
SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CREATE_SERVICE);
if (!ServiceMgrHandle) return GetLastError();
/* Open the service */
Ws2IfsHandle = OpenService(ServiceMgrHandle, "WS2IFSL", SERVICE_ALL_ACCESS);
/* Disable the service */
ChangeServiceConfig(Ws2IfsHandle,
SERVICE_NO_CHANGE,
SERVICE_DISABLED,
SERVICE_NO_CHANGE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
/* Close the handles and return */
CloseServiceHandle(ServiceMgrHandle);
CloseServiceHandle(Ws2IfsHandle);
return ERROR_SUCCESS;
}
INT
WINAPI
WahEnableNonIFSHandleSupport(VOID)
{
return 0;
}
DWORD
WINAPI
WahOpenHandleHelper(OUT PHANDLE HelperHandle)
{
DWORD ErrorCode;
HINSTANCE hWs2_32;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
PFILE_FULL_EA_INFORMATION Ea;
PWAH_EA_DATA2 EaData;
CHAR EaBuffer[sizeof(*Ea) + sizeof(*EaData)];
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
DWORD Tid;
PWAH_HELPER_CONTEXT Context;
/* Enter the prolog, make sure we're initialized */
ErrorCode = WS2HELP_PROLOG();
if (ErrorCode != ERROR_SUCCESS) return ErrorCode;
/* Validate the pointer */
if (!HelperHandle)
{
/* Invalid handle and/or socket */
return ERROR_INVALID_PARAMETER;
}
/* Get ws2_32.dll's handle. We don't load it: it MUST be here */
hWs2_32 = GetModuleHandle ("WS2_32.DLL");
if (!hWs2_32) return WSASYSCALLFAILURE;
/* Dynamically load all its APIs */
if (!((pGetSockOpt = (LPFN_GETSOCKOPT)GetProcAddress(hWs2_32, "getsockopt"))) ||
!((pSelect = (LPFN_SELECT)GetProcAddress(hWs2_32, "select"))) ||
!((pWSACancelBlockingCall = (LPFN_WSACANCELBLOCKINGCALL)GetProcAddress(hWs2_32, "WSACancelBlockingCall"))) ||
!((pWSACleanup = (LPFN_WSACLEANUP)GetProcAddress(hWs2_32, "WSACleanup"))) ||
!((pWSAGetLastError = (LPFN_WSAGETLASTERROR)GetProcAddress(hWs2_32, "WSAGetLastError"))) ||
!((pWSASetBlockingHook = (LPFN_WSASETBLOCKINGHOOK)GetProcAddress(hWs2_32, "WSASetBlockingHook"))) ||
!((pWSARecv = (LPFN_WSARECV)GetProcAddress(hWs2_32, "WSARecv"))) ||
!((pWSASend = (LPFN_WSASEND)GetProcAddress(hWs2_32, "WSASend"))) ||
!((pWSASendTo = (LPFN_WSASENDTO)GetProcAddress(hWs2_32, "WSASendTo"))) ||
!((pWSAStartup = (LPFN_WSASTARTUP)GetProcAddress(hWs2_32, "WSAStartup"))) ||
!((pWSARecvFrom = (LPFN_WSARECVFROM)GetProcAddress(hWs2_32, "WSARecvFrom"))) ||
!((pWSAIoctl = (LPFN_WSAIOCTL)GetProcAddress(hWs2_32, "WSAIoctl"))))
{
/* Uh, guess we failed somewhere */
return WSASYSCALLFAILURE;
}
/* Set pointer EA structure */
Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
/* Create the helper context */
Context = HeapAlloc(GlobalHeap, 0, sizeof(WSH_HELPER_CONTEXT));
if (Context)
{
/* Create the special request thread */
Context->ThreadHandle = CreateThread(NULL,
0,
(PVOID)ApcThread,
Context,
CREATE_SUSPENDED,
&Tid);
if (Context->ThreadHandle)
{
/* Create the attributes for the driver open */
RtlInitUnicodeString(&Name, L"\\Device\\WS2IFSL\\NifsPvd");
InitializeObjectAttributes(&ObjectAttributes,
&Name,
0,
NULL,
NULL);
/* Setup the EA */
Ea->NextEntryOffset = 0;
Ea->Flags = 0;
Ea->EaNameLength = sizeof("NifsPvd");
Ea->EaValueLength = sizeof(*EaData);
RtlCopyMemory(Ea->EaName, "NifsPvd", Ea->EaNameLength);
/* Get our EA data */
EaData = (PWAH_EA_DATA2)(Ea + 1);
/* Fill out the EA Data */
EaData->ThreadHandle = Context->ThreadHandle;
EaData->RequestRoutine = DoSocketRequest;
EaData->CancelRoutine = DoSocketCancel;
EaData->ApcContext = Context;
EaData->Reserved = 0;
/* Call the driver */
Status = NtCreateFile(&Context->FileHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
0,
Ea,
sizeof(*Ea) + sizeof(*EaData));
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Resume the thread and return a handle to the context */
ResumeThread(Context->ThreadHandle);
*HelperHandle = (HANDLE)Context;
return ERROR_SUCCESS;
}
else
{
/* Get the error code */
ErrorCode = RtlNtStatusToDosError(Status);
}
/* We failed, mark us as such */
Context->FileHandle = NULL;
ResumeThread(Context->ThreadHandle);
}
else
{
/* Get the error code */
ErrorCode = GetLastError();
}
/* If we got here, we failed, so free the context */
HeapFree(GlobalHeap, 0, Context);
}
else
{
/* Get the error code */
ErrorCode = GetLastError();
}
/* Return to caller */
return ErrorCode;
}
DWORD
WINAPI
WahCompleteRequest(IN HANDLE HelperHandle,
IN SOCKET Socket,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD ErrorCode,
IN DWORD BytesTransferred)
{
UNREFERENCED_PARAMETER(HelperHandle);
UNREFERENCED_PARAMETER(Socket);
UNREFERENCED_PARAMETER(lpOverlapped);
UNREFERENCED_PARAMETER(ErrorCode);
UNREFERENCED_PARAMETER(BytesTransferred);
return ERROR_SUCCESS;
}
/* EOF */