diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2022-09-09 17:13:15 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2022-09-09 17:13:15 +0200 |
commit | 683db70689b8e09fda983b254325fdc4b409ea14 (patch) | |
tree | bc8f40525e662d5f72ec40b0c8127676150ff8cf /ksocket.c | |
parent | 38495d423f23b145a4377f87a536db5d2721f814 (diff) |
Cleaned up includes, splitted common.h in the ksocket and examples part.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'ksocket.c')
-rw-r--r-- | ksocket.c | 713 |
1 files changed, 0 insertions, 713 deletions
diff --git a/ksocket.c b/ksocket.c deleted file mode 100644 index 3b6ba4d..0000000 --- a/ksocket.c +++ /dev/null @@ -1,713 +0,0 @@ -#include "ksocket.h" - -////////////////////////////////////////////////////////////////////////// -// Definitions. -////////////////////////////////////////////////////////////////////////// - -#define MEMORY_TAG ((ULONG)0x2e2e4142) - -////////////////////////////////////////////////////////////////////////// -// Structures. -////////////////////////////////////////////////////////////////////////// - -typedef struct _KSOCKET_ASYNC_CONTEXT { - KEVENT CompletionEvent; - PIRP Irp; -} KSOCKET_ASYNC_CONTEXT, *PKSOCKET_ASYNC_CONTEXT; - -typedef struct _KSOCKET { - PWSK_SOCKET WskSocket; - - union { - PVOID WskDispatch; - - PWSK_PROVIDER_CONNECTION_DISPATCH WskConnectionDispatch; - PWSK_PROVIDER_LISTEN_DISPATCH WskListenDispatch; - PWSK_PROVIDER_DATAGRAM_DISPATCH WskDatagramDispatch; -#if (NTDDI_VERSION >= NTDDI_WIN10_RS2) - PWSK_PROVIDER_STREAM_DISPATCH WskStreamDispatch; -#endif - }; - - KSOCKET_ASYNC_CONTEXT AsyncContext; -} KSOCKET, *PKSOCKET; - -////////////////////////////////////////////////////////////////////////// -// Variables. -////////////////////////////////////////////////////////////////////////// - -WSK_REGISTRATION WskRegistration; -WSK_PROVIDER_NPI WskProvider; -WSK_CLIENT_DISPATCH WskDispatch = {MAKE_WSK_VERSION(1, 0), 0, NULL}; - -////////////////////////////////////////////////////////////////////////// -// Function prototypes. -////////////////////////////////////////////////////////////////////////// - -NTSTATUS -NTAPI -KspAsyncContextAllocate(_Out_ PKSOCKET_ASYNC_CONTEXT AsyncContext); - -VOID NTAPI KspAsyncContextFree(_In_ PKSOCKET_ASYNC_CONTEXT AsyncContext); - -VOID NTAPI KspAsyncContextReset(_In_ PKSOCKET_ASYNC_CONTEXT AsyncContext); - -static NTSTATUS -KspAsyncContextCompletionRoutine(_In_ PDEVICE_OBJECT DeviceObject, - _In_ PIRP Irp, _In_ PVOID CompletionEvent); - -NTSTATUS -NTAPI -KspAsyncContextWaitForCompletion(_In_ PKSOCKET_ASYNC_CONTEXT AsyncContext, - _Inout_ PNTSTATUS Status); - -////////////////////////////////////////////////////////////////////////// -// Private functions. -////////////////////////////////////////////////////////////////////////// - -NTSTATUS -NTAPI -KspAsyncContextAllocate(_Out_ PKSOCKET_ASYNC_CONTEXT AsyncContext) { - // - // Initialize the completion event. - // - - KeInitializeEvent(&AsyncContext->CompletionEvent, SynchronizationEvent, - FALSE); - - // - // Initialize the IRP. - // - - AsyncContext->Irp = IoAllocateIrp(1, FALSE); - - if (AsyncContext->Irp == NULL) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // KspAsyncContextCompletionRoutine will set - // the CompletionEvent. - // - - IoSetCompletionRoutine(AsyncContext->Irp, &KspAsyncContextCompletionRoutine, - &AsyncContext->CompletionEvent, TRUE, TRUE, TRUE); - - return STATUS_SUCCESS; -} - -VOID NTAPI KspAsyncContextFree(_In_ PKSOCKET_ASYNC_CONTEXT AsyncContext) { - // - // Free the IRP. - // - - IoFreeIrp(AsyncContext->Irp); -} - -VOID NTAPI KspAsyncContextReset(_In_ PKSOCKET_ASYNC_CONTEXT AsyncContext) { - // - // If the WSK application allocated the IRP, or is reusing an IRP - // that it previously allocated, then it must set an IoCompletion - // routine for the IRP before calling a WSK function. In this - // situation, the WSK application must specify TRUE for the - // InvokeOnSuccess, InvokeOnError, and InvokeOnCancel parameters that - // are passed to the IoSetCompletionRoutine function to ensure that - // the IoCompletion routine is always called. Furthermore, the IoCompletion - // routine that is set for the IRP must always return - // STATUS_MORE_PROCESSING_REQUIRED to terminate the completion processing - // of the IRP. If the WSK application is done using the IRP after the - // IoCompletion routine has been called, then it should call the IoFreeIrp - // function to free the IRP before returning from the IoCompletion routine. - // If the WSK application does not free the IRP then it can reuse the IRP - // for a call to another WSK function. - // - // (ref: - // https://docs.microsoft.com/en-us/windows-hardware/drivers/network/using-irps-with-winsock-kernel-functions) - // - - // - // Reset the completion event. - // - - KeResetEvent(&AsyncContext->CompletionEvent); - - // - // Reuse the IRP. - // - - IoReuseIrp(AsyncContext->Irp, STATUS_UNSUCCESSFUL); - - IoSetCompletionRoutine(AsyncContext->Irp, &KspAsyncContextCompletionRoutine, - &AsyncContext->CompletionEvent, TRUE, TRUE, TRUE); -} - -static NTSTATUS -KspAsyncContextCompletionRoutine(_In_ PDEVICE_OBJECT DeviceObject, - _In_ PIRP Irp, _In_ PVOID CompletionEvent) { - UNREFERENCED_PARAMETER(DeviceObject); - UNREFERENCED_PARAMETER(Irp); - - KeSetEvent((PKEVENT)CompletionEvent, IO_NO_INCREMENT, FALSE); - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -KspAsyncContextWaitForCompletion(_In_ PKSOCKET_ASYNC_CONTEXT AsyncContext, - _Inout_ PNTSTATUS Status) { - if (*Status == STATUS_PENDING) { - KeWaitForSingleObject(&AsyncContext->CompletionEvent, Executive, KernelMode, - FALSE, NULL); - - *Status = AsyncContext->Irp->IoStatus.Status; - } - - return *Status; -} - -////////////////////////////////////////////////////////////////////////// -// Public functions. -////////////////////////////////////////////////////////////////////////// - -NTSTATUS -NTAPI -KsInitialize(VOID) { - OSVERSIONINFOEXW OsVersionInfo; - NTSTATUS Status; - - OsVersionInfo.dwOSVersionInfoSize = sizeof(OsVersionInfo); - Status = RtlGetVersion((POSVERSIONINFOW)&OsVersionInfo); - - if (!NT_SUCCESS(Status)) { - return Status; - } - - if (OsVersionInfo.wProductType != VER_NT_WORKSTATION || - OsVersionInfo.dwMajorVersion != 10 || OsVersionInfo.dwMinorVersion != 0) { - return STATUS_UNSUPPORTED_WINDOWS_VERSION; - } - - // - // Register as a WSK client. - // - - WSK_CLIENT_NPI WskClient; - WskClient.ClientContext = NULL; - WskClient.Dispatch = &WskDispatch; - - Status = WskRegister(&WskClient, &WskRegistration); - - if (!NT_SUCCESS(Status)) { - return Status; - } - - // - // Capture the provider NPI. - // - - return WskCaptureProviderNPI(&WskRegistration, WSK_INFINITE_WAIT, - &WskProvider); -} - -VOID NTAPI KsDestroy(VOID) { - // - // Release the provider NPI instance. - // - - WskReleaseProviderNPI(&WskRegistration); - - // - // Deregister as a WSK client. - // - - WskDeregister(&WskRegistration); -} - -NTSTATUS -NTAPI -KsGetAddrInfo(_In_ PUNICODE_STRING NodeName, _In_ PUNICODE_STRING ServiceName, - _In_ PADDRINFOEXW Hints, _Out_ PADDRINFOEXW *Result) { - NTSTATUS Status; - - // - // Allocate async context. - // - - KSOCKET_ASYNC_CONTEXT AsyncContext; - Status = KspAsyncContextAllocate(&AsyncContext); - - if (!NT_SUCCESS(Status)) { - return Status; - } - - // - // Call the WSK API. - // - - Status = WskProvider.Dispatch->WskGetAddressInfo(WskProvider.Client, // Client - NodeName, // NodeName - ServiceName, // ServiceName - 0, // NameSpace - NULL, // Provider - Hints, // Hints - Result, // Result - NULL, // OwningProcess - NULL, // OwningThread - AsyncContext.Irp // Irp - ); - - KspAsyncContextWaitForCompletion(&AsyncContext, &Status); - - // - // Free the async context. - // - - KspAsyncContextFree(&AsyncContext); - - return Status; -} - -VOID NTAPI KsFreeAddrInfo(_In_ PADDRINFOEXW AddrInfo) { - WskProvider.Dispatch->WskFreeAddressInfo(WskProvider.Client, // Client - AddrInfo // AddrInfo - ); -} - -NTSTATUS -NTAPI -KsCreateSocket(_Out_ PKSOCKET *Socket, _In_ ADDRESS_FAMILY AddressFamily, - _In_ USHORT SocketType, _In_ ULONG Protocol, _In_ ULONG Flags) { - NTSTATUS Status; - - // - // Allocate memory for the socket structure. - // - - PKSOCKET NewSocket = - (PKSOCKET)ExAllocatePoolWithTag(PagedPool, sizeof(KSOCKET), MEMORY_TAG); - - if (!NewSocket) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Allocate async context for the socket. - // - - Status = KspAsyncContextAllocate(&NewSocket->AsyncContext); - - if (!NT_SUCCESS(Status)) { - return Status; - } - - // - // Create the WSK socket. - // - - Status = WskProvider.Dispatch->WskSocket(WskProvider.Client, // Client - AddressFamily, // AddressFamily - SocketType, // SocketType - Protocol, // Protocol - Flags, // Flags - NULL, // SocketContext - NULL, // Dispatch - NULL, // OwningProcess - NULL, // OwningThread - NULL, // SecurityDescriptor - NewSocket->AsyncContext.Irp // Irp - ); - - KspAsyncContextWaitForCompletion(&NewSocket->AsyncContext, &Status); - - // - // Save the socket instance and the socket dispatch table. - // - - if (NT_SUCCESS(Status)) { - NewSocket->WskSocket = - (PWSK_SOCKET)NewSocket->AsyncContext.Irp->IoStatus.Information; - NewSocket->WskDispatch = (PVOID)NewSocket->WskSocket->Dispatch; - - *Socket = NewSocket; - } - - return Status; -} - -NTSTATUS -NTAPI -KsCreateConnectionSocket(_Out_ PKSOCKET *Socket, - _In_ ADDRESS_FAMILY AddressFamily, - _In_ USHORT SocketType, _In_ ULONG Protocol) { - return KsCreateSocket(Socket, AddressFamily, SocketType, Protocol, - WSK_FLAG_CONNECTION_SOCKET); -} - -NTSTATUS -NTAPI -KsCreateListenSocket(_Out_ PKSOCKET *Socket, _In_ ADDRESS_FAMILY AddressFamily, - _In_ USHORT SocketType, _In_ ULONG Protocol) { - return KsCreateSocket(Socket, AddressFamily, SocketType, Protocol, - WSK_FLAG_LISTEN_SOCKET); -} - -NTSTATUS -NTAPI -KsCreateDatagramSocket(_Out_ PKSOCKET *Socket, - _In_ ADDRESS_FAMILY AddressFamily, - _In_ USHORT SocketType, _In_ ULONG Protocol) { - return KsCreateSocket(Socket, AddressFamily, SocketType, Protocol, - WSK_FLAG_DATAGRAM_SOCKET); -} - -NTSTATUS -NTAPI -KsCloseSocket(_In_ PKSOCKET Socket) { - NTSTATUS Status; - - // - // Reset the async context. - // - - KspAsyncContextReset(&Socket->AsyncContext); - - // - // Close the WSK socket. - // - - Status = Socket->WskConnectionDispatch->WskCloseSocket( - Socket->WskSocket, Socket->AsyncContext.Irp); - - KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status); - - // - // Free the async context. - // - - KspAsyncContextFree(&Socket->AsyncContext); - - // - // Free memory for the socket structure. - // - - ExFreePoolWithTag(Socket, MEMORY_TAG); - - return Status; -} - -NTSTATUS -NTAPI -KsBind(_In_ PKSOCKET Socket, _In_ PSOCKADDR LocalAddress) { - NTSTATUS Status; - - // - // Reset the async context. - // - - KspAsyncContextReset(&Socket->AsyncContext); - - // - // Bind the socket. - // - - Status = Socket->WskListenDispatch->WskBind(Socket->WskSocket, // Socket - LocalAddress, // LocalAddress - 0, // Flags (reserved) - Socket->AsyncContext.Irp // Irp - ); - - KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status); - - return Status; -} - -NTSTATUS -NTAPI -KsAccept(_In_ PKSOCKET Socket, _Out_ PKSOCKET *NewSocket, - _Out_opt_ PSOCKADDR LocalAddress, _Out_opt_ PSOCKADDR RemoteAddress) { - NTSTATUS Status; - - // - // Reset the async context. - // - - KspAsyncContextReset(&Socket->AsyncContext); - - // - // Accept the connection. - // - - Status = - Socket->WskListenDispatch->WskAccept(Socket->WskSocket, // ListenSocket - 0, // Flags - NULL, // AcceptSocketContext - NULL, // AcceptSocketDispatch - LocalAddress, // LocalAddress - RemoteAddress, // RemoteAddress - Socket->AsyncContext.Irp // Irp - ); - - KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status); - - // - // Save the socket instance and the socket dispatch table. - // - - if (NT_SUCCESS(Status)) { - PKSOCKET KNewSocket = - ExAllocatePoolWithTag(PagedPool, sizeof(KSOCKET), MEMORY_TAG); - - if (!KNewSocket) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - KNewSocket->WskSocket = - (PWSK_SOCKET)Socket->AsyncContext.Irp->IoStatus.Information; - KNewSocket->WskDispatch = (PVOID)KNewSocket->WskSocket->Dispatch; - KspAsyncContextAllocate(&KNewSocket->AsyncContext); - - *NewSocket = KNewSocket; - } - - return Status; -} - -NTSTATUS -NTAPI -KsConnect(_In_ PKSOCKET Socket, _In_ PSOCKADDR RemoteAddress) { - NTSTATUS Status; - - // - // Reset the async context. - // - - KspAsyncContextReset(&Socket->AsyncContext); - - // - // Bind the socket to the local address. - // - - SOCKADDR_IN LocalAddress; - LocalAddress.sin_family = AF_INET; - LocalAddress.sin_addr.s_addr = INADDR_ANY; - LocalAddress.sin_port = 0; - - Status = Socket->WskConnectionDispatch->WskBind( - Socket->WskSocket, // Socket - (PSOCKADDR)&LocalAddress, // LocalAddress - 0, // Flags (reserved) - Socket->AsyncContext.Irp // Irp - ); - - KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status); - - if (!NT_SUCCESS(Status)) { - return Status; - } - - // - // Reset the async context (again). - // - - KspAsyncContextReset(&Socket->AsyncContext); - - // - // Connect to the remote host. - // - // N.B.: Instead of calling WskSocket(), WskBind() and WskConnect(), - // it is possible to just call WskSocketConnect(). - // - - Status = - Socket->WskConnectionDispatch->WskConnect(Socket->WskSocket, // Socket - RemoteAddress, // RemoteAddress - 0, // Flags (reserved) - Socket->AsyncContext.Irp // Irp - ); - - KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status); - - return Status; -} - -NTSTATUS -NTAPI -KsSendRecv(_In_ PKSOCKET Socket, _In_ PVOID Buffer, _Inout_ PULONG Length, - _In_ ULONG Flags, _In_ BOOLEAN Send) { - NTSTATUS Status; - - // - // Wrap the buffer into the "WSK buffer". - // - - WSK_BUF WskBuffer; - WskBuffer.Offset = 0; - WskBuffer.Length = *Length; - WskBuffer.Mdl = - IoAllocateMdl(Buffer, (ULONG)WskBuffer.Length, FALSE, FALSE, NULL); - - //__try - { MmProbeAndLockPages(WskBuffer.Mdl, KernelMode, IoWriteAccess); } -#if 0 - __except (EXCEPTION_EXECUTE_HANDLER) - { - Status = STATUS_ACCESS_VIOLATION; - goto Error; - } -#endif - - // - // Reset the async context. - // - - KspAsyncContextReset(&Socket->AsyncContext); - - // - // Send / receive the data. - // - - if (Send) { - Status = - Socket->WskConnectionDispatch->WskSend(Socket->WskSocket, // Socket - &WskBuffer, // Buffer - Flags, // Flags - Socket->AsyncContext.Irp // Irp - ); - } else { - Status = Socket->WskConnectionDispatch->WskReceive( - Socket->WskSocket, // Socket - &WskBuffer, // Buffer - Flags, // Flags - Socket->AsyncContext.Irp // Irp - ); - } - - KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status); - - // - // Set the number of bytes sent / received. - // - - if (NT_SUCCESS(Status)) { - *Length = (ULONG)Socket->AsyncContext.Irp->IoStatus.Information; - } - - // - // Free the MDL. - // - - MmUnlockPages(WskBuffer.Mdl); - - // Error: - IoFreeMdl(WskBuffer.Mdl); - return Status; -} - -NTSTATUS -NTAPI -KsSendRecvUdp(_In_ PKSOCKET Socket, _In_ PVOID Buffer, _Inout_ PULONG Length, - _In_ ULONG Flags, _In_ PSOCKADDR RemoteAddress, - _In_ BOOLEAN Send) { - NTSTATUS Status; - - // - // Wrap the buffer into the "WSK buffer". - // - - WSK_BUF WskBuffer; - WskBuffer.Offset = 0; - WskBuffer.Length = *Length; - WskBuffer.Mdl = - IoAllocateMdl(Buffer, (ULONG)WskBuffer.Length, FALSE, FALSE, NULL); - - //__try - { MmProbeAndLockPages(WskBuffer.Mdl, KernelMode, IoWriteAccess); } -#if 0 - __except (EXCEPTION_EXECUTE_HANDLER) - { - Status = STATUS_ACCESS_VIOLATION; - goto Error; - } -#endif - - // - // Reset the async context. - // - - KspAsyncContextReset(&Socket->AsyncContext); - - // - // Send / receive the data. - // - - if (Send) { - Status = - Socket->WskDatagramDispatch->WskSendTo(Socket->WskSocket, // Socket - &WskBuffer, // Buffer - Flags, // Flags (reserved) - RemoteAddress, // RemoteAddress - 0, // ControlInfoLength - NULL, // ControlInfo - Socket->AsyncContext.Irp // Irp - ); - } else { - Status = Socket->WskDatagramDispatch->WskReceiveFrom( - Socket->WskSocket, // Socket - &WskBuffer, // Buffer - Flags, // Flags (reserved) - RemoteAddress, // RemoteAddress - NULL, // ControlInfoLength - NULL, // ControlInfo - NULL, // ControlFlags - Socket->AsyncContext.Irp // Irp - ); - } - - KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status); - - // - // Set the number of bytes sent / received. - // - - if (NT_SUCCESS(Status)) { - *Length = (ULONG)Socket->AsyncContext.Irp->IoStatus.Information; - } - - // - // Free the MDL. - // - - MmUnlockPages(WskBuffer.Mdl); - - // Error: - IoFreeMdl(WskBuffer.Mdl); - return Status; -} - -NTSTATUS -NTAPI -KsSend(_In_ PKSOCKET Socket, _In_ PVOID Buffer, _Inout_ PULONG Length, - _In_ ULONG Flags) { - return KsSendRecv(Socket, Buffer, Length, Flags, TRUE); -} - -NTSTATUS -NTAPI -KsRecv(_In_ PKSOCKET Socket, _In_ PVOID Buffer, _Inout_ PULONG Length, - _In_ ULONG Flags) { - return KsSendRecv(Socket, Buffer, Length, Flags, FALSE); -} - -NTSTATUS -NTAPI -KsSendTo(_In_ PKSOCKET Socket, _In_ PVOID Buffer, _Inout_ PULONG Length, - _In_ ULONG Flags, _In_ PSOCKADDR RemoteAddress) { - return KsSendRecvUdp(Socket, Buffer, Length, Flags, RemoteAddress, TRUE); -} - -NTSTATUS -NTAPI -KsRecvFrom(_In_ PKSOCKET Socket, _In_ PVOID Buffer, _Inout_ PULONG Length, - _In_ ULONG Flags, _In_ PSOCKADDR RemoteAddress) { - return KsSendRecvUdp(Socket, Buffer, Length, Flags, RemoteAddress, FALSE); -} |