Some work on winsock stack

svn path=/trunk/; revision=1514
This commit is contained in:
Casper Hornstrup 2001-01-14 17:44:38 +00:00
parent 2dd3473a90
commit 05ccbb2696
42 changed files with 5353 additions and 305 deletions

View file

@ -16,41 +16,43 @@ include rules.mak
# Required to run the system
#
COMPONENTS = iface_native iface_additional ntoskrnl
DLLS = ntdll kernel32 crtdll advapi32 fmifs gdi32 secur32 user32 ws2_32 msvcrt
DLLS = ntdll kernel32 crtdll advapi32 fmifs gdi32 secur32 user32 ws2_32 msafd msvcrt
SUBSYS = smss win32k csrss
#
# Select the server(s) you want to build
#
#SERVERS = posix linux os2
SERVERS = win32
# SERVERS = posix linux os2
#
# Select the loader(s) you want to build
#
#LOADERS = boot dos
LOADERS = dos
# LOADERS = boot
#
# Select the device drivers and filesystems you want
#
#DEVICE_DRIVERS = beep event floppy ide_test mouse sound test test1 parallel serial
DEVICE_DRIVERS = vidport vga blue ide null floppy
# DEVICE_DRIVERS = beep event floppy ide_test mouse sound test test1 parallel serial
#INPUT_DRIVERS = keyboard
INPUT_DRIVERS = keyboard
FS_DRIVERS = vfat
# FS_DRIVERS = minix ext2 template
#FS_DRIVERS = vfat minix ext2 template
FS_DRIVERS = vfat
# ndis tdi tcpip tditest wshtcpip
NET_DRIVERS = ndis tcpip tditest wshtcpip
#NET_DRIVERS = ndis tdi tcpip tditest wshtcpip afd
NET_DRIVERS = ndis tcpip tditest wshtcpip afd
# ne2000
#NET_DEVICE_DRIVERS = ne2000
NET_DEVICE_DRIVERS = ne2000
#
# system applications (required for startup)
#
#SYS_APPS = shell winlogon services
SYS_APPS = shell winlogon services
APPS = args hello test cat bench apc shm lpc thread event file gditest \
@ -58,8 +60,8 @@ APPS = args hello test cat bench apc shm lpc thread event file gditest \
# objdir
# ping
NET_APPS = ping
#NET_APPS = ping roshttpd
NET_APPS = ping roshttpd
KERNEL_SERVICES = $(DEVICE_DRIVERS) $(INPUT_DRIVERS) $(FS_DRIVERS) $(NET_DRIVERS) $(NET_DEVICE_DRIVERS)

View file

@ -0,0 +1,7 @@
; Ancillary Function Driver - ReactOS Operating System
LIBRARY AFDTEST.SYS
EXPORTS
; EOF

View file

@ -0,0 +1,38 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "Ancillary Function Driver\0"
VALUE "FileVersion", "0.0.0\0"
VALUE "InternalName", "afd\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "afd.sys\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -0,0 +1,156 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/afd.c
* PURPOSE: MSAFD kernel mode module
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
#ifdef DBG
/* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = MAX_TRACE;
#endif /* DBG */
NTSTATUS AfdFileSystemControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
UNIMPLEMENTED
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
return STATUS_UNSUCCESSFUL;
}
NTSTATUS AfdDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: IOCTL dispatch routine
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
* RETURNS:
* Status of the operation
*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
AFD_DbgPrint(MAX_TRACE, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n",
DeviceObject, Irp));
Irp->IoStatus.Information = 0;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_AFD_BIND:
Status = AfdDispBind(Irp, IrpSp);
break;
case IOCTL_AFD_LISTEN:
Status = AfdDispListen(Irp, IrpSp);
break;
case IOCTL_AFD_SENDTO:
Status = AfdDispSendTo(Irp, IrpSp);
break;
case IOCTL_AFD_RECVFROM:
Status = AfdDispRecvFrom(Irp, IrpSp);
break;
default:
AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%X).\n",
IrpSp->Parameters.DeviceIoControl.IoControlCode));
Status = STATUS_NOT_IMPLEMENTED;
break;
}
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
AFD_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
return Status;
}
VOID AfdUnload(
PDRIVER_OBJECT DriverObject)
/*
* FUNCTION: Unloads the driver
* ARGUMENTS:
* DriverObject = Pointer to driver object created by the system
*/
{
DbgPrint("Unloading Ancillary Function Driver\n");
}
NTSTATUS
#ifndef _MSC_VER
STDCALL
#endif
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
/*
* FUNCTION: Called by the system to initialize the driver
* ARGUMENTS:
* DriverObject = object describing this driver
* RegistryPath = path to our configuration entries
* RETURNS:
* Status of operation
*/
{
PDEVICE_EXTENSION DeviceExt;
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DeviceName;
NTSTATUS Status;
DbgPrint("Ancillary Function Driver\n");
RtlInitUnicodeString(&DeviceName, L"\\Device\\Afd");
Status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_NAMED_PIPE,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("Could not create device (0x%X).\n", Status));
return Status;
}
DeviceObject->Flags |= DO_DIRECT_IO;
DeviceExt = DeviceObject->DeviceExtension;
KeInitializeSpinLock(&DeviceExt->FCBListLock);
InitializeListHead(&DeviceExt->FCBListHead);
DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdClose;
DriverObject->MajorFunction[IRP_MJ_READ] = AfdRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdWrite;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = AfdFileSystemControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdClose;
DriverObject->DriverUnload = (PDRIVER_UNLOAD)AfdUnload;
return STATUS_SUCCESS;
}
/* EOF */

View file

@ -0,0 +1,186 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/dispatch.c
* PURPOSE: File object dispatch functions
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
NTSTATUS AfdDispBind(
PIRP Irp,
PIO_STACK_LOCATION IrpSp)
/*
* FUNCTION: Binds to an address
* ARGUMENTS:
* Irp = Pointer to I/O request packet
* IrpSp = Pointer to current stack location of Irp
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status;
UINT InputBufferLength;
UINT OutputBufferLength;
PFILE_REQUEST_BIND Request;
PFILE_REPLY_BIND Reply;
PAFDFCB FCB;
InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
/* Validate parameters */
if ((InputBufferLength >= sizeof(FILE_REQUEST_BIND)) &&
(OutputBufferLength >= sizeof(FILE_REPLY_BIND))) {
FCB = IrpSp->FileObject->FsContext;
Request = (PFILE_REQUEST_BIND)Irp->AssociatedIrp.SystemBuffer;
Reply = (PFILE_REPLY_BIND)Irp->AssociatedIrp.SystemBuffer;
switch (Request->Name.sa_family) {
case AF_INET:
Status = TdiOpenAddressFileIPv4(&FCB->TdiDeviceName,
&Request->Name,
&FCB->TdiAddressObjectHandle,
&FCB->TdiAddressObject);
break;
default:
AFD_DbgPrint(MIN_TRACE, ("Bad address family (%d).\n", Request->Name.sa_family));
Status = STATUS_INVALID_PARAMETER;
}
if (NT_SUCCESS(Status)) {
AfdRegisterEventHandlers(FCB);
FCB->State = SOCKET_STATE_BOUND;
}
} else
Status = STATUS_INVALID_PARAMETER;
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
return Status;
}
NTSTATUS AfdDispListen(
PIRP Irp,
PIO_STACK_LOCATION IrpSp)
/*
* FUNCTION: Starts listening for connections
* ARGUMENTS:
* Irp = Pointer to I/O request packet
* IrpSp = Pointer to current stack location of Irp
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status;
UINT InputBufferLength;
UINT OutputBufferLength;
PFILE_REQUEST_LISTEN Request;
PFILE_REPLY_LISTEN Reply;
PAFDFCB FCB;
InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
/* Validate parameters */
if ((InputBufferLength >= sizeof(FILE_REQUEST_LISTEN)) &&
(OutputBufferLength >= sizeof(FILE_REPLY_LISTEN))) {
FCB = IrpSp->FileObject->FsContext;
Request = (PFILE_REQUEST_LISTEN)Irp->AssociatedIrp.SystemBuffer;
Reply = (PFILE_REPLY_LISTEN)Irp->AssociatedIrp.SystemBuffer;
} else
Status = STATUS_INVALID_PARAMETER;
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
return Status;
}
NTSTATUS AfdDispSendTo(
PIRP Irp,
PIO_STACK_LOCATION IrpSp)
/*
* FUNCTION: Sends data to an address
* ARGUMENTS:
* Irp = Pointer to I/O request packet
* IrpSp = Pointer to current stack location of Irp
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status;
UINT InputBufferLength;
UINT OutputBufferLength;
PFILE_REQUEST_SENDTO Request;
PFILE_REPLY_SENDTO Reply;
PAFDFCB FCB;
InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
/* Validate parameters */
if ((InputBufferLength >= sizeof(FILE_REQUEST_SENDTO)) &&
(OutputBufferLength >= sizeof(FILE_REPLY_SENDTO))) {
FCB = IrpSp->FileObject->FsContext;
Request = (PFILE_REQUEST_SENDTO)Irp->AssociatedIrp.SystemBuffer;
Reply = (PFILE_REPLY_SENDTO)Irp->AssociatedIrp.SystemBuffer;
Status = TdiSend(FCB->TdiAddressObject, Request);
Reply->NumberOfBytesSent = Request->ToLen;
Reply->Status = Status;
} else
Status = STATUS_INVALID_PARAMETER;
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
return Status;
}
NTSTATUS AfdDispRecvFrom(
PIRP Irp,
PIO_STACK_LOCATION IrpSp)
/*
* FUNCTION: Receives data from an address
* ARGUMENTS:
* Irp = Pointer to I/O request packet
* IrpSp = Pointer to current stack location of Irp
* RETURNS:
* Status of operation
*/
{
NTSTATUS Status;
UINT InputBufferLength;
UINT OutputBufferLength;
PFILE_REQUEST_RECVFROM Request;
PFILE_REPLY_RECVFROM Reply;
PAFDFCB FCB;
InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
/* Validate parameters */
if ((InputBufferLength >= sizeof(FILE_REQUEST_RECVFROM)) &&
(OutputBufferLength >= sizeof(FILE_REPLY_RECVFROM))) {
FCB = IrpSp->FileObject->FsContext;
Request = (PFILE_REQUEST_RECVFROM)Irp->AssociatedIrp.SystemBuffer;
Reply = (PFILE_REPLY_RECVFROM)Irp->AssociatedIrp.SystemBuffer;
} else
Status = STATUS_INVALID_PARAMETER;
AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
return Status;
}
/* EOF */

View file

@ -0,0 +1,203 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/event.c
* PURPOSE: TDI event handlers
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
NTSTATUS AfdEventError(
IN PVOID TdiEventContext,
IN NTSTATUS Status)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS AfdEventDisconnect(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN LONG DisconnectDataLength,
IN PVOID DisconnectData,
IN LONG DisconnectInformationLength,
IN PVOID DisconnectInformation,
IN ULONG DisconnectFlags)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS AfdEventReceive(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
TDI_STATUS ClientEventReceiveExpedited(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS ClientEventChainedReceive(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG ReceiveLength,
IN ULONG StartingOffset,
IN PMDL Tsdu,
IN PVOID TsduDescriptor)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
return STATUS_SUCCESS;
}
NTSTATUS AfdEventReceiveDatagramHandler(
IN PVOID TdiEventContext,
IN LONG SourceAddressLength,
IN PVOID SourceAddress,
IN LONG OptionsLength,
IN PVOID Options,
IN ULONG ReceiveDatagramFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *IoRequestPacket)
{
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
AFD_DbgPrint(MID_TRACE, ("Receiving (%d) bytes from (0x%X).\n",
BytesAvailable, *(PULONG)SourceAddress));
return STATUS_SUCCESS;
}
NTSTATUS AfdRegisterEventHandlers(
PAFDFCB FCB)
{
NTSTATUS Status;
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_ERROR,
(PVOID)AfdEventError,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
switch (FCB->SocketType) {
case SOCK_STREAM:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_DISCONNECT,
(PVOID)AfdEventDisconnect,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE,
(PVOID)AfdEventReceive,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_EXPEDITED,
(PVOID)ClientEventReceiveExpedited,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_CHAINED_RECEIVE,
(PVOID)ClientEventChainedReceive,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
break;
case SOCK_DGRAM:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_DATAGRAM,
(PVOID)AfdEventReceiveDatagramHandler,
(PVOID)FCB);
if (!NT_SUCCESS(Status)) { return Status; }
}
return STATUS_SUCCESS;
}
NTSTATUS AfdDeregisterEventHandlers(
PAFDFCB FCB)
{
NTSTATUS Status;
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_ERROR,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
switch (FCB->SocketType) {
case SOCK_STREAM:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_DISCONNECT,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_EXPEDITED,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_CHAINED_RECEIVE,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
break;
case SOCK_DGRAM:
Status = TdiSetEventHandler(FCB->TdiAddressObject,
TDI_EVENT_RECEIVE_DATAGRAM,
NULL,
NULL);
if (!NT_SUCCESS(Status)) { return Status; }
}
return STATUS_SUCCESS;
}
/* EOF */

View file

@ -0,0 +1,202 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/opnclose.c
* PURPOSE: File object creation and destruction
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
PAFDFCB AfdInitializeFCB(
PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject OPTIONAL)
/*
* FUNCTION: Allocates and initializes a File Control Block structure
*/
{
PAFDFCB NewFCB;
NewFCB = ExAllocatePool(NonPagedPool, sizeof(AFDFCB));
if (!NewFCB)
return NULL;
RtlZeroMemory(NewFCB, sizeof(AFDFCB));
ExInitializeResourceLite(&NewFCB->NTRequiredFCB.MainResource);
ExInitializeResourceLite(&NewFCB->NTRequiredFCB.PagingIoResource);
NewFCB->DeviceExt = DeviceExt;
NewFCB->ReferenceCount = 1;
NewFCB->OpenHandleCount = 1;
NewFCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE;
NewFCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
InitializeListHead(&NewFCB->CCBListHead);
InsertTailList(&DeviceExt->FCBListHead, &NewFCB->ListEntry);
if (FileObject)
FileObject->FsContext = (PVOID)&NewFCB->NTRequiredFCB;
return NewFCB;
}
PAFDCCB AfdInitializeCCB(
PAFDFCB FCB,
PFILE_OBJECT FileObject)
/*
* FUNCTION: Allocates and initializes a Context Control Block structure
*/
{
PAFDCCB NewCCB;
NewCCB = ExAllocatePool(NonPagedPool, sizeof(AFDCCB));
if (!NewCCB)
return NULL;
RtlZeroMemory(NewCCB, sizeof(AFDCCB));
NewCCB->FileObject = FileObject;
FileObject->FsContext2 = (PVOID)NewCCB;
InsertTailList(&FCB->CCBListHead, &NewCCB->ListEntry);
return NewCCB;
}
NTSTATUS AfdCreate(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PAFD_SOCKET_INFORMATION SocketInfo;
PFILE_FULL_EA_INFORMATION EaInfo;
PDEVICE_EXTENSION DeviceExt;
PTA_ADDRESS Address;
NTSTATUS Status;
ULONG EaLength;
PAFDFCB FCB;
PAFDCCB CCB;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
AFD_DbgPrint(MIN_TRACE, ("Called.\n"));
DeviceExt = DeviceObject->DeviceExtension;
EaInfo = Irp->AssociatedIrp.SystemBuffer;
/* Parameter check */
if (!EaInfo) {
AFD_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
return STATUS_INVALID_PARAMETER;
}
SocketInfo = (PAFD_SOCKET_INFORMATION)(EaInfo->EaName + EaInfo->EaNameLength);
EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
EaInfo->EaNameLength +
EaInfo->EaValueLength;
if (EaLength < sizeof(FILE_FULL_EA_INFORMATION) +
AFD_SOCKET_LENGTH + sizeof(AFD_SOCKET_INFORMATION)) {
AFD_DbgPrint(MIN_TRACE, ("EA information has invalid length.\n"));
return STATUS_INVALID_PARAMETER;
}
AFD_DbgPrint(MAX_TRACE, ("EaInfo at (0x%X) length is (%d).\n", EaInfo, EaLength));
/* FIXME: File/socket could already be open, do a search for it */
FCB = AfdInitializeFCB(DeviceExt, FileObject);
CCB = AfdInitializeCCB(FCB, FileObject);
if (CCB && FCB) {
FCB->AddressFamily = SocketInfo->AddressFamily;
FCB->SocketType = SocketInfo->SocketType;
FCB->Protocol = SocketInfo->Protocol;
FCB->HelperContext = SocketInfo->HelperContext;
FCB->NotificationEvents = SocketInfo->NotificationEvents;
RtlCopyUnicodeString(&FCB->TdiDeviceName, &SocketInfo->TdiDeviceName);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (!NT_SUCCESS(Status)) {
/* FIXME: Cleanup */
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
AFD_DbgPrint(MIN_TRACE, ("Leaving. Status (0x%X).\n", Status));
return Status;
}
NTSTATUS AfdClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
NTSTATUS Status;
PAFDFCB FCB;
PAFDCCB CCB;
FCB = FileObject->FsContext;
CCB = FileObject->FsContext2;
AFD_DbgPrint(MIN_TRACE, ("Called.\n"));
switch (IrpSp->MajorFunction) {
/* Close a file object */
case IRP_MJ_CLOSE:
FCB->ReferenceCount--;
if (FCB->ReferenceCount < 1) {
/* Close TDI connection file object */
if (FCB->TdiConnectionObjectHandle != INVALID_HANDLE_VALUE) {
TdiCloseDevice(FCB->TdiConnectionObjectHandle, FCB->TdiConnectionObject);
FCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
}
/* Close TDI address file object */
if (FCB->TdiAddressObjectHandle != INVALID_HANDLE_VALUE) {
AfdDeregisterEventHandlers(FCB);
TdiCloseDevice(FCB->TdiAddressObjectHandle, FCB->TdiAddressObject);
FCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE;
}
ExFreePool(FCB);
}
Status = STATUS_SUCCESS;
break;
/* Release resources bound to a file object */
case IRP_MJ_CLEANUP:
FCB->OpenHandleCount--;
Status = STATUS_SUCCESS;
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}
ExFreePool(CCB);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* EOF */

View file

@ -0,0 +1,99 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/rdwr.c
* PURPOSE: File object read/write functions
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
NTSTATUS AfdReadFile(
PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PVOID Buffer,
ULONG Length,
ULONG Offset)
/*
* FUNCTION: Reads data from a file
*/
{
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
}
NTSTATUS AfdRead(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
#if 1
UNIMPLEMENTED
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
return STATUS_UNSUCCESSFUL;
#else
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IoSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IoSp->FileObject;
NTSTATUS Status;
ULONG Length;
PVOID Buffer;
ULONG Offset;
Length = IoSp->Parameters.Read.Length;
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Offset = IoSp->Parameters.Read.ByteOffset.u.LowPart;
Status = AfdReadFile(DeviceExt, FileObject, Buffer, Length, Offset);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
#endif
}
NTSTATUS AfdWrite(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IoSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IoSp->FileObject;
NTSTATUS Status;
ULONG Length;
PVOID Buffer;
ULONG Offset;
PAFDFCB FCB;
PAFDCCB CCB;
FCB = FileObject->FsContext;
CCB = FileObject->FsContext2;
Length = IoSp->Parameters.Write.Length;
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Offset = IoSp->Parameters.Write.ByteOffset.u.LowPart;
AFD_DbgPrint(MIN_TRACE, ("Called. Length (%d) Buffer (0x%X) Offset (0x%X)\n",
Length, Buffer, Offset));
/* FIXME: Connectionless communication only */
//Status = TdiSendDatagram(FCB->TdiAddressObject, WH2N(2000), 0x7F000001, Buffer, Length);
//if (!NT_SUCCESS(Status))
Length = 0;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
AFD_DbgPrint(MIN_TRACE, ("Leaving.\n"));
return Status;
}
/* EOF */

View file

@ -0,0 +1,903 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: afd/tdi.c
* PURPOSE: Transport Driver Interface functions
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <afd.h>
inline DWORD TdiAddressSizeFromName(
LPSOCKADDR Name)
/*
* FUNCTION: Returns the size of a TDI style address equivalent to a
* WinSock style name
* ARGUMENTS:
* Name = WinSock style name
* RETURNS:
* Size of TDI style address, 0 if Name is not valid
*/
{
switch (Name->sa_family) {
case AF_INET:
return sizeof(TA_ADDRESS_IP);
/* FIXME: More to come */
}
AFD_DbgPrint(MIN_TRACE, ("Unknown address family (%d).\n", Name->sa_family));
return 0;
}
VOID TdiBuildAddressIPv4(
PTA_ADDRESS_IP Address,
LPSOCKADDR Name)
/*
* FUNCTION: Builds an IPv4 TDI style address
* ARGUMENTS:
* Address = Address of buffer to place TDI style IPv4 address
* Name = Pointer to WinSock style IPv4 name
*/
{
Address->TAAddressCount = 1;
Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
Address->Address[0].Address[0].sin_port = ((LPSOCKADDR_IN)Name)->sin_port;
Address->Address[0].Address[0].in_addr = ((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr;
}
VOID TdiBuildAddress(
PTA_ADDRESS Address,
LPSOCKADDR Name)
/*
* FUNCTION: Builds a TDI style address
* ARGUMENTS:
* Address = Address of buffer to place TDI style address
* Name = Pointer to WinSock style name
*/
{
switch (Name->sa_family) {
case AF_INET:
TdiBuildAddressIPv4((PTA_ADDRESS_IP)Address, Name);
break;
/* FIXME: More to come */
default:
AFD_DbgPrint(MIN_TRACE, ("Unknown address family (%d).\n", Name->sa_family));
}
}
VOID TdiBuildName(
LPSOCKADDR Name,
PTA_ADDRESS Address)
/*
* FUNCTION: Builds a WinSock style address
* ARGUMENTS:
* Name = Address of buffer to place WinSock style name
* Address = Pointer to TDI style address
*/
{
switch (Address->AddressType) {
case TDI_ADDRESS_TYPE_IP:
Name->sa_family = AF_INET;
((LPSOCKADDR_IN)Name)->sin_port =
((PTDI_ADDRESS_IP)&Address->Address[0])->sin_port;
((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr =
((PTDI_ADDRESS_IP)&Address->Address[0])->in_addr;
return;
/* FIXME: More to come */
}
AFD_DbgPrint(MIN_TRACE, ("Unknown TDI address type (%d).\n", Address->AddressType));
}
NTSTATUS TdiCall(
PIRP Irp,
PDEVICE_OBJECT DeviceObject,
PIO_STATUS_BLOCK IoStatusBlock,
BOOLEAN CanCancel,
PKEVENT StopEvent)
/*
* FUNCTION: Calls a transport driver device
* ARGUMENTS:
* Irp = Pointer to I/O Request Packet
* DeviceObject = Pointer to device object to call
* IoStatusBlock = Address of buffer with I/O status block
* CanCancel = TRUE if the IRP can be cancelled, FALSE if not
* StopEvent = If CanCancel is TRUE, a pointer to an event handle
* that, when signalled will cause the request to abort
* RETURNS:
* Status of operation
* NOTES:
* All requests are completed synchronously. A request can be cancelled
*/
{
KEVENT Event;
PKEVENT Events[2];
NTSTATUS Status;
Events[0] = StopEvent;
Events[1] = &Event;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp->UserEvent = &Event;
Irp->UserIosb = IoStatusBlock;
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING) {
if (CanCancel) {
Status = KeWaitForMultipleObjects(2,
(PVOID)&Events,
WaitAny,
Executive,
KernelMode,
FALSE,
NULL,
NULL);
if (KeReadStateEvent(StopEvent) != 0) {
if (IoCancelIrp(Irp)) {
AFD_DbgPrint(MAX_TRACE, ("Cancelled IRP.\n"));
} else {
AFD_DbgPrint(MIN_TRACE, ("Could not cancel IRP.\n"));
}
return STATUS_CANCELLED;
}
} else
Status = KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
}
AFD_DbgPrint(MIN_TRACE, ("Status (0x%X) Iosb.Status (0x%X).\n", Status, IoStatusBlock->Status));
return IoStatusBlock->Status;
}
NTSTATUS TdiOpenDevice(
PUNICODE_STRING DeviceName,
ULONG EaLength,
PFILE_FULL_EA_INFORMATION EaInfo,
PHANDLE Handle,
PFILE_OBJECT *Object)
/*
* FUNCTION: Opens a device
* ARGUMENTS:
* DeviceName = Pointer to counted string with name of device
* EaLength = Length of EA information
* EaInfo = Pointer to buffer with EA information
* Handle = Address of buffer to place device handle
* Object = Address of buffer to place device object
* RETURNS:
* Status of operation
*/
{
OBJECT_ATTRIBUTES Attr;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
InitializeObjectAttributes(&Attr, /* Attribute buffer */
DeviceName, /* Device name */
OBJ_CASE_INSENSITIVE, /* Attributes */
NULL, /* Root directory */
NULL); /* Security descriptor */
Status = ZwCreateFile(Handle, /* Return file handle */
GENERIC_READ | GENERIC_WRITE, /* Desired access */
&Attr, /* Object attributes */
&Iosb, /* IO status */
0, /* Initial allocation size */
FILE_ATTRIBUTE_NORMAL, /* File attributes */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* Share access */
FILE_OPEN_IF, /* Create disposition */
0, /* Create options */
EaInfo, /* EA buffer */
EaLength); /* EA length */
if (NT_SUCCESS(Status)) {
Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */
GENERIC_READ | GENERIC_WRITE, /* Access mode */
NULL, /* Object type */
KernelMode, /* Access mode */
(PVOID*)Object, /* Pointer to object */
NULL); /* Handle information */
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status));
ZwClose(*Handle);
}
} else {
AFD_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status));
}
return Status;
}
NTSTATUS TdiCloseDevice(
HANDLE Handle,
PFILE_OBJECT FileObject)
{
if (FileObject)
ObDereferenceObject(FileObject);
if (Handle)
ZwClose(Handle);
return STATUS_SUCCESS;
}
NTSTATUS TdiOpenAddressFileIPv4(
PUNICODE_STRING DeviceName,
LPSOCKADDR Name,
PHANDLE AddressHandle,
PFILE_OBJECT *AddressObject)
/*
* FUNCTION: Opens an IPv4 address file object
* ARGUMENTS:
* DeviceName = Pointer to counted string with name of device
* Name = Pointer to socket name (IPv4 address family)
* AddressHandle = Address of buffer to place address file handle
* AddressObject = Address of buffer to place address file object
* RETURNS:
* Status of operation
*/
{
PFILE_FULL_EA_INFORMATION EaInfo;
PTA_ADDRESS_IP Address;
NTSTATUS Status;
ULONG EaLength;
EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
TDI_TRANSPORT_ADDRESS_LENGTH +
sizeof(TA_ADDRESS_IP);
EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
if (!EaInfo) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(EaInfo, EaLength);
EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
RtlCopyMemory(EaInfo->EaName,
TdiTransportAddress,
TDI_TRANSPORT_ADDRESS_LENGTH);
EaInfo->EaValueLength = sizeof(TA_ADDRESS_IP);
Address = (PTA_ADDRESS_IP)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH);
TdiBuildAddressIPv4(Address, Name);
Status = TdiOpenDevice(DeviceName,
EaLength,
EaInfo,
AddressHandle,
AddressObject);
ExFreePool(EaInfo);
return Status;
}
NTSTATUS TdiSetEventHandler(
PFILE_OBJECT FileObject,
LONG EventType,
PVOID Handler,
PVOID Context)
/*
* FUNCTION: Sets or resets an event handler
* ARGUMENTS:
* FileObject = Pointer to file object
* EventType = Event code
* Handler = Event handler to be called when the event occurs
* Context = Context input to handler when the event occurs
* RETURNS:
* Status of operation
* NOTES:
* Specify NULL for Handler to stop calling event handler
*/
{
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
PIRP Irp;
DeviceObject = IoGetRelatedDeviceObject(FileObject);
Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, /* Sub function */
DeviceObject, /* Device object */
FileObject, /* File object */
NULL, /* Event */
NULL); /* Status */
if (!Irp) {
AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildSetEventHandler(Irp,
DeviceObject,
FileObject,
NULL,
NULL,
EventType,
Handler,
Context);
Status = TdiCall(Irp, DeviceObject, &Iosb, FALSE, NULL);
return Status;
}
NTSTATUS TdiQueryDeviceControl(
PFILE_OBJECT FileObject,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG Return)
/*
* FUNCTION: Queries a device for information
* ARGUMENTS:
* FileObject = Pointer to file object
* IoControlCode = I/O control code
* InputBuffer = Pointer to buffer with input data
* InputBufferLength = Length of InputBuffer
* OutputBuffer = Address of buffer to place output data
* OutputBufferLength = Length of OutputBuffer
* RETURNS:
* Status of operation
*/
{
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
PIRP Irp;
DeviceObject = IoGetRelatedDeviceObject(FileObject);
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
DeviceObject,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
FALSE,
NULL,
NULL);
if (!Irp) {
AFD_DbgPrint(MIN_TRACE, ("IoBuildDeviceIoControlRequest() failed.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = TdiCall(Irp, DeviceObject, &Iosb, FALSE, NULL);
if (Return)
*Return = Iosb.Information;
return Status;
}
NTSTATUS TdiQueryInformationEx(
PFILE_OBJECT FileObject,
ULONG Entity,
ULONG Instance,
ULONG Class,
ULONG Type,
ULONG Id,
PVOID OutputBuffer,
PULONG OutputLength)
/*
* FUNCTION: Extended query for information
* ARGUMENTS:
* FileObject = Pointer to file object
* Entity = Entity
* Instance = Instance
* Class = Entity class
* Type = Entity type
* Id = Entity id
* OutputBuffer = Address of buffer to place data
* OutputLength = Address of buffer with length of OutputBuffer (updated)
* RETURNS:
* Status of operation
*/
{
TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo;
RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
QueryInfo.ID.toi_entity.tei_entity = Entity;
QueryInfo.ID.toi_entity.tei_instance = Instance;
QueryInfo.ID.toi_class = Class;
QueryInfo.ID.toi_type = Type;
QueryInfo.ID.toi_id = Id;
return TdiQueryDeviceControl(FileObject, /* Transport/connection object */
IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */
&QueryInfo, /* Input buffer */
sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */
OutputBuffer, /* Output buffer */
*OutputLength, /* Output buffer length */
OutputLength); /* Return information */
}
NTSTATUS TdiQueryAddress(
PFILE_OBJECT FileObject,
PULONG Address)
/*
* FUNCTION: Queries for a local IP address
* ARGUMENTS:
* FileObject = Pointer to file object
* Address = Address of buffer to place local address
* RETURNS:
* Status of operation
*/
{
UINT i;
TDIEntityID *Entities;
ULONG EntityCount;
ULONG EntityType;
IPSNMP_INFO SnmpInfo;
PIPADDR_ENTRY IpAddress;
ULONG BufferSize;
NTSTATUS Status = STATUS_SUCCESS;
AFD_DbgPrint(MAX_TRACE, ("Called\n"));
BufferSize = sizeof(TDIEntityID) * 20;
Entities = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize);
if (!Entities) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Query device for supported entities */
Status = TdiQueryInformationEx(FileObject, /* File object */
GENERIC_ENTITY, /* Entity */
TL_INSTANCE, /* Instance */
INFO_CLASS_GENERIC, /* Entity class */
INFO_TYPE_PROVIDER, /* Entity type */
ENTITY_LIST_ID, /* Entity id */
Entities, /* Output buffer */
&BufferSize); /* Output buffer size */
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status));
ExFreePool(Entities);
return Status;
}
/* Locate an IP entity */
EntityCount = BufferSize / sizeof(TDIEntityID);
AFD_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount));
for (i = 0; i < EntityCount; i++) {
if (Entities[i].tei_entity == CL_NL_ENTITY) {
/* Query device for entity type */
BufferSize = sizeof(EntityType);
Status = TdiQueryInformationEx(FileObject, /* File object */
CL_NL_ENTITY, /* Entity */
Entities[i].tei_instance, /* Instance */
INFO_CLASS_GENERIC, /* Entity class */
INFO_TYPE_PROVIDER, /* Entity type */
ENTITY_TYPE_ID, /* Entity id */
&EntityType, /* Output buffer */
&BufferSize); /* Output buffer size */
if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP)) {
AFD_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status));
break;
}
/* Query device for SNMP information */
BufferSize = sizeof(SnmpInfo);
Status = TdiQueryInformationEx(FileObject, /* File object */
CL_NL_ENTITY, /* Entity */
Entities[i].tei_instance, /* Instance */
INFO_CLASS_PROTOCOL, /* Entity class */
INFO_TYPE_PROVIDER, /* Entity type */
IP_MIB_STATS_ID, /* Entity id */
&SnmpInfo, /* Output buffer */
&BufferSize); /* Output buffer size */
if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0)) {
AFD_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status));
break;
}
/* Query device for all IP addresses */
if (SnmpInfo.NumAddr != 0) {
BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY);
IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize);
if (!IpAddress) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
break;
}
Status = TdiQueryInformationEx(FileObject, /* File object */
CL_NL_ENTITY, /* Entity */
Entities[i].tei_instance, /* Instance */
INFO_CLASS_PROTOCOL, /* Entity class */
INFO_TYPE_PROVIDER, /* Entity type */
IP_MIB_ADDRTABLE_ENTRY_ID, /* Entity id */
IpAddress, /* Output buffer */
&BufferSize); /* Output buffer size */
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status));
ExFreePool(IpAddress);
break;
}
if (SnmpInfo.NumAddr != 1) {
/* Skip loopback address */
*Address = DN2H(((PIPADDR_ENTRY)((ULONG)IpAddress + sizeof(IPADDR_ENTRY)))->Addr);
} else {
/* Select the first address returned */
*Address = DN2H(IpAddress->Addr);
}
ExFreePool(IpAddress);
} else {
Status = STATUS_UNSUCCESSFUL;
break;
}
}
}
ExFreePool(Entities);
AFD_DbgPrint(MAX_TRACE, ("Leaving\n"));
return Status;
}
NTSTATUS TdiSend(
PFILE_OBJECT TransportObject,
PFILE_REQUEST_SENDTO Request)
/*
* FUNCTION: Sends a block of data
* ARGUMENTS:
* TransportObject = Pointer to transport object
* Request = Pointer to request
* RETURNS:
* Status of operation
*/
{
PTDI_CONNECTION_INFORMATION ConnectInfo;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
DWORD TdiAddressSize;
ULONG BufferSize;
NTSTATUS Status;
PIRP Irp;
PMDL Mdl;
/* FIXME: Connectionless only */
DeviceObject = IoGetRelatedDeviceObject(TransportObject);
if (!DeviceObject) {
AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
return STATUS_INVALID_PARAMETER;
}
TdiAddressSize = TdiAddressSizeFromName(&Request->To);
ConnectInfo = (PTDI_CONNECTION_INFORMATION)
ExAllocatePool(NonPagedPool,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
if (!ConnectInfo) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(ConnectInfo,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
ConnectInfo->RemoteAddressLength = TdiAddressSize;
ConnectInfo->RemoteAddress = (PVOID)
(ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION));
TdiBuildAddress(ConnectInfo->RemoteAddress, &Request->To);
Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
NULL); /* Return buffer */
if (!Irp) {
AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
ExFreePool(ConnectInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* FIXME: There may be more than one buffer */
BufferSize = Request->Buffers->len;
Mdl = IoAllocateMdl(
Request->Buffers->buf, /* Virtual address of buffer */
Request->Buffers->len, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
NULL); /* Don't use IRP */
if (!Mdl) {
AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n"));
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
#ifdef _MSC_VER
try {
#endif
MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
#ifdef _MSC_VER
} except(EXCEPTION_EXECUTE_HANDLER) {
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
IoFreeMdl(Mdl);
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
return STATUS_UNSUCCESSFUL;
}
#endif
TdiBuildSendDatagram(Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Completion routine */
NULL, /* Completion context */
Mdl, /* Descriptor for data buffer */
BufferSize, /* Size of data to send */
ConnectInfo); /* Connection information */
Status = TdiCall(Irp, DeviceObject, &Iosb, FALSE, NULL);
ExFreePool(ConnectInfo);
return Status;
}
NTSTATUS TdiSendDatagram(
PFILE_OBJECT TransportObject,
LPSOCKADDR Address,
PVOID Buffer,
ULONG BufferSize)
/*
* FUNCTION: Sends a datagram
* ARGUMENTS:
* TransportObject = Pointer to transport object
* Address = Remote address
* Buffer = Pointer to buffer with data to send
* BufferSize = Length of Buffer
* RETURNS:
* Status of operation
*/
{
PTDI_CONNECTION_INFORMATION ConnectInfo;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
DWORD TdiAddressSize;
NTSTATUS Status;
PIRP Irp;
PMDL Mdl;
DeviceObject = IoGetRelatedDeviceObject(TransportObject);
if (!DeviceObject) {
AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
return STATUS_INVALID_PARAMETER;
}
TdiAddressSize = TdiAddressSizeFromName(Address);
ConnectInfo = (PTDI_CONNECTION_INFORMATION)
ExAllocatePool(NonPagedPool,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
if (!ConnectInfo) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(ConnectInfo,
sizeof(TDI_CONNECTION_INFORMATION) +
TdiAddressSize);
ConnectInfo->RemoteAddressLength = TdiAddressSize;
ConnectInfo->RemoteAddress = (PVOID)
(ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION));
TdiBuildAddress(ConnectInfo->RemoteAddress, Address);
Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
NULL); /* Return buffer */
if (!Irp) {
AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
ExFreePool(ConnectInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
Mdl = IoAllocateMdl(Buffer, /* Virtual address of buffer */
BufferSize, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
NULL); /* Don't use IRP */
if (!Mdl) {
AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n"));
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
#ifdef _MSC_VER
try {
#endif
MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
#ifdef _MSC_VER
} except(EXCEPTION_EXECUTE_HANDLER) {
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
IoFreeMdl(Mdl);
IoFreeIrp(Irp);
ExFreePool(ConnectInfo);
return STATUS_UNSUCCESSFUL;
}
#endif
TdiBuildSendDatagram(Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Completion routine */
NULL, /* Completion context */
Mdl, /* Descriptor for data buffer */
BufferSize, /* Size of data to send */
ConnectInfo); /* Connection information */
Status = TdiCall(Irp, DeviceObject, &Iosb, FALSE, NULL);
ExFreePool(ConnectInfo);
return Status;
}
NTSTATUS TdiReceiveDatagram(
PFILE_OBJECT TransportObject,
LPSOCKADDR From,
LPSOCKADDR Address,
PUCHAR Buffer,
PULONG BufferSize)
/*
* FUNCTION: Receives a datagram
* ARGUMENTS:
* TransportObject = Pointer to transport object
* From = Receive filter (NULL if none)
* Address = Address of buffer to place remote address
* Buffer = Address of buffer to place received data
* BufferSize = Address of buffer with length of Buffer (updated)
* RETURNS:
* Status of operation
*/
{
PTDI_CONNECTION_INFORMATION ReceiveInfo;
PTDI_CONNECTION_INFORMATION ReturnInfo;
PTA_ADDRESS_IP ReturnAddress;
PDEVICE_OBJECT DeviceObject;
IO_STATUS_BLOCK Iosb;
DWORD TdiAddressSize;
NTSTATUS Status;
PIRP Irp;
PMDL Mdl;
if (From != NULL) {
/* FIXME: Check that the socket type match the socket */
}
DeviceObject = IoGetRelatedDeviceObject(TransportObject);
if (!DeviceObject) {
AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
return STATUS_INVALID_PARAMETER;
}
/* FIXME: Get from socket information */
TdiAddressSize = sizeof(TA_ADDRESS_IP);
ReceiveInfo = (PTDI_CONNECTION_INFORMATION)
ExAllocatePool(NonPagedPool,
sizeof(TDI_CONNECTION_INFORMATION) +
sizeof(TDI_CONNECTION_INFORMATION) +
2 * TdiAddressSize);
if (!ReceiveInfo) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(ReceiveInfo,
sizeof(TDI_CONNECTION_INFORMATION) +
sizeof(TDI_CONNECTION_INFORMATION) +
2 * TdiAddressSize);
if (From != NULL) {
ReceiveInfo->RemoteAddressLength = TdiAddressSize;
ReceiveInfo->RemoteAddress = (PVOID)
(ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION));
/* Filter datagrams */
TdiBuildAddress(ReceiveInfo->RemoteAddress, From);
} else {
/* Receive from any address */
ReceiveInfo->RemoteAddressLength = 0;
ReceiveInfo->RemoteAddress = NULL;
}
ReturnInfo = (PTDI_CONNECTION_INFORMATION)
(ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION) + TdiAddressSize);
ReturnInfo->RemoteAddressLength = TdiAddressSize;
ReturnInfo->RemoteAddress = (PVOID)
(ReturnInfo + sizeof(TDI_CONNECTION_INFORMATION));
Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, /* Sub function */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Event */
NULL); /* Return buffer */
if (!Irp) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
ExFreePool(ReceiveInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
Mdl = IoAllocateMdl(Buffer, /* Virtual address */
*BufferSize, /* Length of buffer */
FALSE, /* Not secondary */
FALSE, /* Don't charge quota */
NULL); /* Don't use IRP */
if (!Mdl) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
IoFreeIrp(Irp);
ExFreePool(ReceiveInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
#ifdef _MSC_VER
try {
#endif
MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
#ifdef _MSC_VER
} except (EXCEPTION_EXECUTE_HANDLER) {
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
IoFreeMdl(Mdl);
IoFreeIrp(Irp);
ExFreePool(ReceiveInfo);
return STATUS_INSUFFICIENT_RESOURCES;
}
#endif
TdiBuildReceiveDatagram(Irp, /* I/O Request Packet */
DeviceObject, /* Device object */
TransportObject, /* File object */
NULL, /* Completion routine */
NULL, /* Completion context */
Mdl, /* Data buffer */
*BufferSize, /* Size of data buffer */
ReceiveInfo, /* Connection information */
ReturnInfo, /* Connection information */
TDI_RECEIVE_NORMAL); /* Flags */
Status = TdiCall(Irp, DeviceObject, &Iosb, TRUE, NULL);
if (NT_SUCCESS(Status)) {
*BufferSize = Iosb.Information;
TdiBuildName(Address, ReturnInfo->RemoteAddress);
}
IoFreeMdl(Mdl);
ExFreePool(ReceiveInfo);
return Status;
}
/* EOF */

View file

@ -0,0 +1,301 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: include/afd.h
* PURPOSE: Main driver header
*/
#ifndef __AFD_H
#define __AFD_H
#include <winsock2.h>
#include <ddk/ntddk.h>
#include <net/tdikrnl.h>
#include <net/tdiinfo.h>
#include <afd/shared.h>
#include <debug.h>
/* Forward declarations */
struct _AFDFCB;
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT StorageDevice;
KSPIN_LOCK FCBListLock;
LIST_ENTRY FCBListHead;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
/* Context Control Block structure */
typedef struct _AFDCCB {
struct _AFDFCB *FCB;
LIST_ENTRY ListEntry;
PFILE_OBJECT FileObject;
ULONG Flags;
LARGE_INTEGER CurrentByteOffset;
} AFDCCB, *PAFDCCB;
/* Flags for CCB structure */
#define CCB_CLEANED 0x00000001
/* Borrowed from http://www.acc.umu.se/~bosse/ntifs.h by Bo Branten */
typedef struct _FSRTL_COMMON_FCB_HEADER {
CSHORT NodeTypeCode;
CSHORT NodeByteSize;
UCHAR Flags;
UCHAR IsFastIoPossible;
UCHAR Flags2;
UCHAR Reserved;
PERESOURCE Resource;
PERESOURCE PagingIoResource;
LARGE_INTEGER AllocationSize;
LARGE_INTEGER FileSize;
LARGE_INTEGER ValidDataLength;
} FSRTL_COMMON_FCB_HEADER, *PFSRTL_COMMON_FCB_HEADER;
typedef struct _FsdNTRequiredFCB {
FSRTL_COMMON_FCB_HEADER CommonFCBHeader;
SECTION_OBJECT_POINTERS SectionObject;
ERESOURCE MainResource;
ERESOURCE PagingIoResource;
} FsdNTRequiredFCB, *PFsdNTRequiredFCB;
typedef struct _AFDFCB {
FsdNTRequiredFCB NTRequiredFCB;
LIST_ENTRY ListEntry;
PDEVICE_EXTENSION DeviceExt;
SHARE_ACCESS ShareAccess;
ULONG ReferenceCount;
ULONG OpenHandleCount;
HANDLE TdiAddressObjectHandle;
PFILE_OBJECT TdiAddressObject;
HANDLE TdiConnectionObjectHandle;
PFILE_OBJECT TdiConnectionObject;
LIST_ENTRY CCBListHead;
INT AddressFamily;
INT SocketType;
INT Protocol;
PVOID HelperContext;
DWORD NotificationEvents;
UNICODE_STRING TdiDeviceName;
DWORD State;
} AFDFCB, *PAFDFCB;
/* Socket states */
#define SOCKET_STATE_CREATED 0
#define SOCKET_STATE_BOUND 1
#define SOCKET_STATE_LISTENING 2
typedef struct IPSNMP_INFO {
ULONG Forwarding;
ULONG DefaultTTL;
ULONG InReceives;
ULONG InHdrErrors;
ULONG InAddrErrors;
ULONG ForwDatagrams;
ULONG InUnknownProtos;
ULONG InDiscards;
ULONG InDelivers;
ULONG OutRequests;
ULONG RoutingDiscards;
ULONG OutDiscards;
ULONG OutNoRoutes;
ULONG ReasmTimeout;
ULONG ReasmReqds;
ULONG ReasmOks;
ULONG ReasmFails;
ULONG FragOks;
ULONG FragFails;
ULONG FragCreates;
ULONG NumIf;
ULONG NumAddr;
ULONG NumRoutes;
} IPSNMP_INFO, *PIPSNMP_INFO;
typedef struct IPADDR_ENTRY {
ULONG Addr;
ULONG Index;
ULONG Mask;
ULONG BcastAddr;
ULONG ReasmSize;
USHORT Context;
USHORT Pad;
} IPADDR_ENTRY, *PIPADDR_ENTRY;
#define TL_INSTANCE 0
#define IP_MIB_STATS_ID 0x1
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
/* IOCTL codes */
#define IOCTL_TCP_QUERY_INFORMATION_EX \
CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_TCP_SET_INFORMATION_EX \
CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#ifdef i386
/* DWORD network to host byte order conversion for i386 */
#define DN2H(dw) \
((((dw) & 0xFF000000L) >> 24) | \
(((dw) & 0x00FF0000L) >> 8) | \
(((dw) & 0x0000FF00L) << 8) | \
(((dw) & 0x000000FFL) << 24))
/* DWORD host to network byte order conversion for i386 */
#define DH2N(dw) \
((((dw) & 0xFF000000L) >> 24) | \
(((dw) & 0x00FF0000L) >> 8) | \
(((dw) & 0x0000FF00L) << 8) | \
(((dw) & 0x000000FFL) << 24))
/* WORD network to host order conversion for i386 */
#define WN2H(w) \
((((w) & 0xFF00) >> 8) | \
(((w) & 0x00FF) << 8))
/* WORD host to network byte order conversion for i386 */
#define WH2N(w) \
((((w) & 0xFF00) >> 8) | \
(((w) & 0x00FF) << 8))
#else /* i386 */
/* DWORD network to host byte order conversion for other architectures */
#define DN2H(dw) \
(dw)
/* DWORD host to network byte order conversion for other architectures */
#define DH2N(dw) \
(dw)
/* WORD network to host order conversion for other architectures */
#define WN2H(w) \
(w)
/* WORD host to network byte order conversion for other architectures */
#define WH2N(w) \
(w)
#endif /* i386 */
/* Prototypes from dispatch.c */
NTSTATUS AfdDispBind(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispListen(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispSendTo(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
NTSTATUS AfdDispRecvFrom(
PIRP Irp,
PIO_STACK_LOCATION IrpSp);
/* Prototypes from event.c */
NTSTATUS AfdRegisterEventHandlers(
PAFDFCB FCB);
NTSTATUS AfdDeregisterEventHandlers(
PAFDFCB FCB);
/* Prototypes from opnclose.c */
NTSTATUS AfdCreate(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS AfdCreateNamedPipe(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS AfdClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* Prototypes from rdwr.c */
NTSTATUS AfdEventReceiveDatagramHandler(
IN PVOID TdiEventContext,
IN LONG SourceAddressLength,
IN PVOID SourceAddress,
IN LONG OptionsLength,
IN PVOID Options,
IN ULONG ReceiveDatagramFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG * BytesTaken,
IN PVOID Tsdu,
OUT PIRP * IoRequestPacket);
NTSTATUS AfdRead(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS AfdWrite(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* Prototypes from tdi.c */
NTSTATUS TdiCloseDevice(
HANDLE Handle,
PFILE_OBJECT FileObject);
NTSTATUS TdiOpenAddressFileIPv4(
PUNICODE_STRING DeviceName,
LPSOCKADDR Name,
PHANDLE AddressHandle,
PFILE_OBJECT *AddressObject);
NTSTATUS TdiSetEventHandler(
PFILE_OBJECT FileObject,
LONG EventType,
PVOID Handler,
PVOID Context);
NTSTATUS TdiQueryDeviceControl(
PFILE_OBJECT FileObject,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG Return);
NTSTATUS TdiQueryInformationEx(
PFILE_OBJECT FileObject,
ULONG Entity,
ULONG Instance,
ULONG Class,
ULONG Type,
ULONG Id,
PVOID OutputBuffer,
PULONG OutputLength);
NTSTATUS TdiQueryAddress(
PFILE_OBJECT FileObject,
PULONG Address);
NTSTATUS TdiSend(
PFILE_OBJECT TransportObject,
PFILE_REQUEST_SENDTO Request);
NTSTATUS TdiSendDatagram(
PFILE_OBJECT TransportObject,
LPSOCKADDR Address,
PVOID Buffer,
ULONG BufferSize);
#endif /*__AFD_H */
/* EOF */

View file

@ -0,0 +1,92 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: include/debug.h
* PURPOSE: Debugging support macros
* DEFINES: DBG - Enable debug output
* NASSERT - Disable assertions
*/
#ifndef __DEBUG_H
#define __DEBUG_H
#define NORMAL_MASK 0x000000FF
#define SPECIAL_MASK 0xFFFFFF00
#define MIN_TRACE 0x00000001
#define MID_TRACE 0x00000002
#define MAX_TRACE 0x00000003
#define DEBUG_IRP 0x00000100
#define DEBUG_ULTRA 0xFFFFFFFF
#ifdef DBG
extern DWORD DebugTraceLevel;
#ifdef _MSC_VER
#define AFD_DbgPrint(_t_, _x_) \
if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
DbgPrint("(%s:%d) ", __FILE__, __LINE__); \
DbgPrint _x_ ; \
}
#else /* _MSC_VER */
#define AFD_DbgPrint(_t_, _x_) \
if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
DbgPrint _x_ ; \
}
#endif /* _MSC_VER */
#ifdef ASSERT
#undef ASSERT
#endif
#ifdef NASSERT
#define ASSERT(x)
#else /* NASSERT */
#define ASSERT(x) if (!(x)) { AFD_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); }
#endif /* NASSERT */
#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x))
#else /* DBG */
#define AFD_DbgPrint(_t_, _x_)
#define ASSERT_IRQL(x)
#define ASSERT(x)
#endif /* DBG */
#define assert(x) ASSERT(x)
#define assert_irql(x) ASSERT_IRQL(x)
#ifdef _MSC_VER
#define UNIMPLEMENTED \
AFD_DbgPrint(MIN_TRACE, ("The function at %s:%d is unimplemented, \
but come back another day.\n", __FILE__, __LINE__));
#else /* _MSC_VER */
#define UNIMPLEMENTED \
AFD_DbgPrint(MIN_TRACE, ("%s at %s:%d is unimplemented, " \
"but come back another day.\n", __FUNCTION__, __FILE__, __LINE__));
#endif /* _MSC_VER */
#define CHECKPOINT \
do { AFD_DbgPrint(MIN_TRACE, ("%s:%d\n", __FILE__, __LINE__)); } while(0);
#endif /* __DEBUG_H */
/* EOF */

View file

@ -0,0 +1,87 @@
# AFD.SYS - Ancillary Function Driver
PATH_TO_TOP = ../../..
TARGETNAME=afd
CFLAGS = -I./include
RESOURCE_OBJECT = $(TARGETNAME).coff
AFD_OBJECTS = afd/afd.o afd/dispatch.o afd/event.o afd/opnclose.o afd/rdwr.o afd/tdi.o
all: $(TARGETNAME).sys
$(TARGETNAME).coff: $(TARGETNAME).rc ../../../include/reactos/resource.h
OBJECTS = $(AFD_OBJECTS) $(RESOURCE_OBJECT) ../../../ntoskrnl/ntoskrnl.a
ifeq ($(DOSCLI),yes)
CLEAN_FILES = *.o afd\*.o $(TARGETNAME).coff $(TARGETNAME).o \
junk.tmp base.tmp temp.exp $(TARGETNAME).sys $(TARGETNAME).sym
else
CLEAN_FILES = *.o afd/*.o $(TARGETNAME).coff $(TARGETNAME).o \
junk.tmp base.tmp temp.exp $(TARGETNAME).sys $(TARGETNAME).sym
endif
$(TARGETNAME).sys: $(OBJECTS)
$(CC) \
-nostartfiles -nostdlib \
--subsystem=native \
-mdll \
--dll \
-Wl,-e,_DriverEntry@8 \
-Wl,--base-file,base.tmp \
-Wl,--defsym,_end=end \
-Wl,--defsym,_edata=__data_end__ \
-Wl,--defsym,_etext=etext \
$(OBJECTS) \
-o junk.tmp
- $(RM) junk.tmp
$(DLLTOOL) \
--dllname $(TARGETNAME).sys \
--base-file base.tmp \
--output-exp temp.exp
- $(RM) base.tmp
$(CC) \
-nostartfiles -nostdlib \
--subsystem=native \
-mdll \
--dll \
-Wl,--image-base,0x10000 \
-Wl,-e,_DriverEntry@8 \
-Wl,temp.exp \
$(OBJECTS) \
-o $(TARGETNAME).sys
- $(RM) temp.exp
$(NM) --numeric-sort $(TARGETNAME).sys > $(TARGETNAME).sym
clean: $(CLEAN_FILES:%=%_clean)
$(CLEAN_FILES:%=%_clean): %_clean:
- $(RM) $*
.PHONY: clean $(CLEAN_FILES:%=%_clean)
install: $(FLOPPY_DIR)/drivers/$(TARGETNAME).sys
$(FLOPPY_DIR)/drivers/$(TARGETNAME).sys: $(TARGETNAME).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGETNAME).sys $(FLOPPY_DIR)\drivers\$(TARGETNAME).sys
else
$(CP) $(TARGETNAME).sys $(FLOPPY_DIR)/drivers/$(TARGETNAME).sys
endif
dist: $(DIST_DIR)/drivers/$(TARGETNAME).sys
$(DIST_DIR)/drivers/$(TARGETNAME).sys: $(TARGETNAME).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGETNAME).sys ..\..\..\$(DIST_DIR)\drivers\$(TARGETNAME).sys
else
$(CP) $(TARGETNAME).sys ../../../$(DIST_DIR)/drivers/$(TARGETNAME).sys
endif
#WITH_DEBUGGING = yes
#WIN32_LEAN_AND_MEAN = yes
#WARNINGS_ARE_ERRORS = yes
include ../../../rules.mak

View file

@ -21,16 +21,11 @@
extern DWORD DebugTraceLevel;
#define Get_DbgPrint(quote...) L##quote
#define WSH_DbgPrint(_t_, _x_) \
if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
WCHAR _buffer[256]; \
swprintf(_buffer, L"(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
OutputDebugStringW(_buffer); \
swprintf(_buffer, Get_DbgPrint _x_); \
OutputDebugStringW(_buffer); \
DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \
DbgPrint _x_; \
}
#ifdef ASSERT
@ -64,7 +59,9 @@ extern DWORD DebugTraceLevel;
please try again later.\n", __FILE__, __LINE__, __FUNCTION__));
#define CHECKPOINT \
do { WSH_DbgPrint(MIN_TRACE, ("(%s:%d)\n", __FILE__, __LINE__)); } while(0);
WSH_DbgPrint(MIN_TRACE, ("\n"));
#define CP CHECKPOINT
#endif /* __DEBUG_H */

View file

@ -37,7 +37,6 @@ $(TARGETNAME).dll: $(LIBS) $(OBJECTS) $(TARGETNAME).def
$(CC) \
$(TARGETNAME).o \
$(LIBS) \
-specs=$(TARGETNAME)_specs \
-mdll \
-o junk.tmp \
-Wl,--base-file,base.tmp
@ -50,10 +49,9 @@ $(TARGETNAME).dll: $(LIBS) $(OBJECTS) $(TARGETNAME).def
- $(RM) base.tmp
$(CC) \
$(OBJECTS) $(LIBS) \
-specs=$(TARGETNAME)_specs \
-mdll \
-o $(TARGETNAME).dll \
-Wl,--image-base,0x10000 \
-Wl,--image-base,0x777C0000 \
-Wl,--file-alignment,0x1000 \
-Wl,--section-alignment,0x1000 \
-Wl,temp.exp

View file

@ -12,7 +12,7 @@
#ifdef DBG
/* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = MIN_TRACE;
DWORD DebugTraceLevel = MAX_TRACE;
#endif /* DBG */
@ -22,11 +22,10 @@ VOID STDCALL KeBugCheck (ULONG BugCheckCode) {}
BOOL
EXPORT
DllMain(PVOID hInstDll,
DllMain(HANDLE hInstDll,
ULONG dwReason,
PVOID Reserved)
{
OutputDebugString(_T("Hello from wshtcpip.dll\n"));
WSH_DbgPrint(MIN_TRACE, ("DllMain of wshtcpip.dll\n"));
switch (dwReason) {
@ -289,6 +288,8 @@ WSHOpenSocket2(
UNICODE_STRING String;
NTSTATUS Status;
WSH_DbgPrint(MAX_TRACE, ("\n"));
/* FIXME: Raw IP only. Support UDP and TCP */
ASSERT(*SocketType == SOCK_RAW);

View file

@ -0,0 +1,90 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver
* FILE: include/afd/shared.h
* PURPOSE: Shared definitions for AFD.SYS and MSAFD.DLL
*/
#ifndef __AFD_SHARED_H
#define __AFD_SHARED_H
#define AfdSocket "AfdSocket"
#define AFD_SOCKET_LENGTH (sizeof(AfdSocket) - 1)
typedef struct _AFD_SOCKET_INFORMATION {
INT AddressFamily;
INT SocketType;
INT Protocol;
PVOID HelperContext;
DWORD NotificationEvents;
UNICODE_STRING TdiDeviceName;
} AFD_SOCKET_INFORMATION, *PAFD_SOCKET_INFORMATION;
/* AFD IOCTL code definitions */
#define FSCTL_AFD_BASE FILE_DEVICE_NAMED_PIPE // ???
#define AFD_CTL_CODE(Function, Method, Access) \
CTL_CODE(FSCTL_AFD_BASE, Function, Method, Access)
#define IOCTL_AFD_BIND \
AFD_CTL_CODE(0, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_LISTEN \
AFD_CTL_CODE(1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_SENDTO \
AFD_CTL_CODE(2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_RECVFROM \
AFD_CTL_CODE(3, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _FILE_REQUEST_BIND {
SOCKADDR Name;
} FILE_REQUEST_BIND, *PFILE_REQUEST_BIND;
typedef struct _FILE_REPLY_BIND {
INT Status;
HANDLE TdiAddressObjectHandle;
HANDLE TdiConnectionObjectHandle;
} FILE_REPLY_BIND, *PFILE_REPLY_BIND;
typedef struct _FILE_REQUEST_LISTEN {
INT Backlog;
} FILE_REQUEST_LISTEN, *PFILE_REQUEST_LISTEN;
typedef struct _FILE_REPLY_LISTEN {
INT Status;
} FILE_REPLY_LISTEN, *PFILE_REPLY_LISTEN;
typedef struct _FILE_REQUEST_SENDTO {
LPWSABUF Buffers;
DWORD BufferCount;
DWORD Flags;
SOCKADDR To;
INT ToLen;
} FILE_REQUEST_SENDTO, *PFILE_REQUEST_SENDTO;
typedef struct _FILE_REPLY_SENDTO {
INT Status;
DWORD NumberOfBytesSent;
} FILE_REPLY_SENDTO, *PFILE_REPLY_SENDTO;
typedef struct _FILE_REQUEST_RECVFROM {
LPWSABUF Buffers;
DWORD BufferCount;
LPDWORD Flags;
LPSOCKADDR From;
LPINT FromLen;
} FILE_REQUEST_RECVFROM, *PFILE_REQUEST_RECVFROM;
typedef struct _FILE_REPLY_RECVFROM {
INT Status;
DWORD NumberOfBytesRecvd;
} FILE_REPLY_RECVFROM, *PFILE_REPLY_RECVFROM;
#endif /*__AFD_SHARED_H */
/* EOF */

View file

@ -9,10 +9,10 @@
/* FIXME: Missed some definitions in ntddk.h */
/* Could be defined in ndis.h */
#ifndef __NDIS_H
typedef signed int INT, *PINT;
#endif
/* Could be defined elsewhere */
//#ifndef INT
//typedef signed int INT, *PINT;
//#endif

View file

@ -0,0 +1,6 @@
msafd.a
msafd.dll
msafd.coff
base.tmp
junk.tmp
temp.exp

View file

@ -0,0 +1,67 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver DLL
* FILE: include/debug.h
* PURPOSE: Debugging support macros
* DEFINES: DBG - Enable debug output
* NASSERT - Disable assertions
*/
#ifndef __DEBUG_H
#define __DEBUG_H
#define NORMAL_MASK 0x000000FF
#define SPECIAL_MASK 0xFFFFFF00
#define MIN_TRACE 0x00000001
#define MID_TRACE 0x00000002
#define MAX_TRACE 0x00000003
#define DEBUG_ULTRA 0xFFFFFFFF
#ifdef DBG
extern DWORD DebugTraceLevel;
#define AFD_DbgPrint(_t_, _x_) \
if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \
DbgPrint _x_; \
}
#ifdef ASSERT
#undef ASSERT
#endif
#ifdef NASSERT
#define ASSERT(x)
#else /* NASSERT */
#define ASSERT(x) if (!(x)) { AFD_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); }
#endif /* NASSERT */
#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x))
#else /* DBG */
#define AFD_DbgPrint(_t_, _x_)
#define ASSERT_IRQL(x)
#define ASSERT(x)
#endif /* DBG */
#define assert(x) ASSERT(x)
#define assert_irql(x) ASSERT_IRQL(x)
#define UNIMPLEMENTED \
AFD_DbgPrint(MIN_TRACE, ("is unimplemented, please try again later.\n"));
#define CHECKPOINT \
AFD_DbgPrint(MIN_TRACE, ("\n"));
#define CP CHECKPOINT
#endif /* __DEBUG_H */
/* EOF */

View file

@ -0,0 +1,62 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver DLL
* FILE: include/helpers.h
* PURPOSE: Definitions for helper DLL management
*/
#ifndef __HELPERS_H
#define __HELPERS_H
#include <msafd.h>
typedef struct _WSHELPER_DLL_ENTRIES {
PWSH_ADDRESS_TO_STRING lpWSHAddressToString;
PWSH_ENUM_PROTOCOLS lpWSHEnumProtocols;
PWSH_GET_BROADCAST_SOCKADDR lpWSHGetBroadcastSockaddr;
PWSH_GET_PROVIDER_GUID lpWSHGetProviderGuid;
PWSH_GET_SOCKADDR_TYPE lpWSHGetSockaddrType;
PWSH_GET_SOCKET_INFORMATION lpWSHGetSocketInformation;
PWSH_GET_WILDCARD_SOCKEADDR lpWSHGetWildcardSockaddr;
PWSH_GET_WINSOCK_MAPPING lpWSHGetWinsockMapping;
PWSH_GET_WSAPROTOCOL_INFO lpWSHGetWSAProtocolInfo;
PWSH_IOCTL lpWSHIoctl;
PWSH_JOIN_LEAF lpWSHJoinLeaf;
PWSH_NOTIFY lpWSHNotify;
PWSH_OPEN_SOCKET lpWSHOpenSocket;
PWSH_OPEN_SOCKET2 lpWSHOpenSocket2;
PWSH_SET_SOCKET_INFORMATION lpWSHSetSocketInformation;
PWSH_STRING_TO_ADDRESS lpWSHStringToAddress;
} WSHELPER_DLL_ENTRIES, *PWSHELPER_DLL_ENTRIES;
typedef struct _WSHELPER_DLL {
LIST_ENTRY ListEntry;
CRITICAL_SECTION Lock;
WCHAR LibraryName[MAX_PATH];
HMODULE hModule;
WSHELPER_DLL_ENTRIES EntryTable;
PWINSOCK_MAPPING Mapping;
} WSHELPER_DLL, *PWSHELPER_DLL;
PWSHELPER_DLL CreateHelperDLL(
LPWSTR LibraryName);
INT DestroyHelperDLL(
PWSHELPER_DLL HelperDLL);
PWSHELPER_DLL LocateHelperDLL(
LPWSAPROTOCOL_INFOW lpProtocolInfo);
INT LoadHelperDLL(
PWSHELPER_DLL HelperDLL);
INT UnloadHelperDLL(
PWSHELPER_DLL HelperDLL);
VOID CreateHelperDLLDatabase(VOID);
VOID DestroyHelperDLLDatabase(VOID);
#endif /* __HELPERS_H */
/* EOF */

View file

@ -0,0 +1,310 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver DLL
* FILE: include/msafd.h
* PURPOSE: Ancillary Function Driver DLL header
*/
#ifndef __MSAFD_H
#define __MSAFD_H
#include <wsahelp.h>
#include <winsock2.h>
#include <ws2spi.h>
#include <ddk/ntddk.h>
#include <windows.h>
#include <net/tdi.h>
#include <afd/shared.h>
#include <debug.h>
extern HANDLE GlobalHeap;
extern WSPUPCALLTABLE Upcalls;
extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
SOCKET
WSPAPI
WSPAccept(
IN SOCKET s,
OUT LPSOCKADDR addr,
IN OUT LPINT addrlen,
IN LPCONDITIONPROC lpfnCondition,
IN DWORD dwCallbackData,
OUT LPINT lpErrno);
INT
WSPAPI
WSPAddressToString(
IN LPSOCKADDR lpsaAddress,
IN DWORD dwAddressLength,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
OUT LPWSTR lpszAddressString,
IN OUT LPDWORD lpdwAddressStringLength,
OUT LPINT lpErrno);
INT
WSPAPI
WSPAsyncSelect(
IN SOCKET s,
IN HWND hWnd,
IN UINT wMsg,
IN LONG lEvent,
OUT LPINT lpErrno);
INT
WSPAPI WSPBind(
IN SOCKET s,
IN CONST LPSOCKADDR name,
IN INT namelen,
OUT LPINT lpErrno);
INT
WSPAPI
WSPCancelBlockingCall(
OUT LPINT lpErrno);
INT
WSPAPI
WSPCleanup(
OUT LPINT lpErrno);
INT
WSPAPI
WSPCloseSocket(
IN SOCKET s,
OUT LPINT lpErrno);
INT
WSPAPI
WSPConnect(
IN SOCKET s,
IN CONST LPSOCKADDR name,
IN INT namelen,
IN LPWSABUF lpCallerData,
OUT LPWSABUF lpCalleeData,
IN LPQOS lpSQOS,
IN LPQOS lpGQOS,
OUT LPINT lpErrno);
INT
WSPAPI
WSPDuplicateSocket(
IN SOCKET s,
IN DWORD dwProcessId,
OUT LPWSAPROTOCOL_INFOW lpProtocolInfo,
OUT LPINT lpErrno);
INT
WSPAPI
WSPEnumNetworkEvents(
IN SOCKET s,
IN WSAEVENT hEventObject,
OUT LPWSANETWORKEVENTS lpNetworkEvents,
OUT LPINT lpErrno);
INT
WSPAPI
WSPEventSelect(
IN SOCKET s,
IN WSAEVENT hEventObject,
IN LONG lNetworkEvents,
OUT LPINT lpErrno);
BOOL
WSPAPI
WSPGetOverlappedResult(
IN SOCKET s,
IN LPWSAOVERLAPPED lpOverlapped,
OUT LPDWORD lpcbTransfer,
IN BOOL fWait,
OUT LPDWORD lpdwFlags,
OUT LPINT lpErrno);
INT
WSPAPI
WSPGetPeerName(
IN SOCKET s,
OUT LPSOCKADDR name,
IN OUT LPINT namelen,
OUT LPINT lpErrno);
BOOL
WSPAPI
WSPGetQOSByName(
IN SOCKET s,
IN OUT LPWSABUF lpQOSName,
OUT LPQOS lpQOS,
OUT LPINT lpErrno);
INT
WSPAPI
WSPGetSockName(
IN SOCKET s,
OUT LPSOCKADDR name,
IN OUT LPINT namelen,
OUT LPINT lpErrno);
INT
WSPAPI
WSPGetSockOpt(
IN SOCKET s,
IN INT level,
IN INT optname,
OUT CHAR FAR* optval,
IN OUT LPINT optlen,
OUT LPINT lpErrno);
INT
WSPAPI
WSPIoctl(
IN SOCKET s,
IN DWORD dwIoControlCode,
IN LPVOID lpvInBuffer,
IN DWORD cbInBuffer,
OUT LPVOID lpvOutBuffer,
IN DWORD cbOutBuffer,
OUT LPDWORD lpcbBytesReturned,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno);
SOCKET
WSPAPI
WSPJoinLeaf(
IN SOCKET s,
IN CONST LPSOCKADDR name,
IN INT namelen,
IN LPWSABUF lpCallerData,
OUT LPWSABUF lpCalleeData,
IN LPQOS lpSQOS,
IN LPQOS lpGQOS,
IN DWORD dwFlags,
OUT LPINT lpErrno);
INT
WSPAPI
WSPListen(
IN SOCKET s,
IN INT backlog,
OUT LPINT lpErrno);
INT
WSPAPI
WSPRecv(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno);
INT
WSPAPI
WSPRecvDisconnect(
IN SOCKET s,
OUT LPWSABUF lpInboundDisconnectData,
OUT LPINT lpErrno);
INT
WSPAPI
WSPRecvFrom(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
OUT LPSOCKADDR lpFrom,
IN OUT LPINT lpFromlen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno);
INT
WSPAPI
WSPSelect(
IN INT nfds,
IN OUT LPFD_SET readfds,
IN OUT LPFD_SET writefds,
IN OUT LPFD_SET exceptfds,
IN CONST LPTIMEVAL timeout,
OUT LPINT lpErrno);
INT
WSPAPI
WSPSend(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno);
INT
WSPAPI
WSPSendDisconnect(
IN SOCKET s,
IN LPWSABUF lpOutboundDisconnectData,
OUT LPINT lpErrno);
INT
WSPAPI
WSPSendTo(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN CONST LPSOCKADDR lpTo,
IN INT iTolen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno);
INT
WSPAPI
WSPSetSockOpt(
IN SOCKET s,
IN INT level,
IN INT optname,
IN CONST CHAR FAR* optval,
IN INT optlen,
OUT LPINT lpErrno);
INT
WSPAPI
WSPShutdown(
IN SOCKET s,
IN INT how,
OUT LPINT lpErrno);
SOCKET
WSPAPI
WSPSocket(
IN INT af,
IN INT type,
IN INT protocol,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
IN GROUP g,
IN DWORD dwFlags,
OUT LPINT lpErrno);
INT
WSPAPI
WSPStringToAddress(
IN LPWSTR AddressString,
IN INT AddressFamily,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
OUT LPSOCKADDR lpAddress,
IN OUT LPINT lpAddressLength,
OUT LPINT lpErrno);
#endif /* __MSAFD_H */
/* EOF */

View file

@ -0,0 +1,94 @@
# Makefile for ReactOS Ancillary Function Driver DLL
PATH_TO_TOP = ../..
CFLAGS = -I./include -DUNICODE
TARGETNAME=msafd
MISC_OBJECTS = misc/dllmain.o misc/helpers.o misc/sndrcv.o misc/stubs.o
RESOURCE_OBJECT = $(TARGETNAME).coff
OBJECTS = $(MISC_OBJECTS) $(RESOURCE_OBJECT)
LIBS = ../ntdll/ntdll.a \
../kernel32/kernel32.a
ifeq ($(DOSCLI),yes)
CLEAN_FILES = misc\*.o \
$(TARGETNAME).o $(TARGETNAME).a junk.tmp base.tmp temp.exp \
$(TARGETNAME).dll $(TARGETNAME).sym $(TARGETNAME).coff
else
CLEAN_FILES = misc/*.o \
$(TARGETNAME).o $(TARGETNAME).a junk.tmp base.tmp temp.exp \
$(TARGETNAME).dll $(TARGETNAME).sym $(TARGETNAME).coff
endif
all: $(TARGETNAME).dll
$(TARGETNAME).coff: $(TARGETNAME).rc ../../include/reactos/resource.h
$(TARGETNAME).a: $(OBJECTS)
$(LD) -r $(OBJECTS) -o $(TARGETNAME).a
$(TARGETNAME).dll: $(LIBS) $(OBJECTS) $(TARGETNAME).def
$(LD) -r $(OBJECTS) -o $(TARGETNAME).o
$(DLLTOOL) \
--dllname $(TARGETNAME).dll \
--def $(TARGETNAME).def \
--kill-at \
--output-lib $(TARGETNAME).a
$(CC) \
$(TARGETNAME).o \
$(LIBS) \
-mdll \
-o junk.tmp \
-Wl,--base-file,base.tmp
- $(RM) junk.tmp
$(DLLTOOL) \
--dllname $(TARGETNAME).dll \
--base-file base.tmp \
--output-exp temp.exp \
--def $(TARGETNAME).edf
- $(RM) base.tmp
$(CC) \
$(TARGETNAME).o \
$(LIBS) \
-mdll \
-o $(TARGETNAME).dll \
-Wl,--image-base,0x777A0000 \
-Wl,--file-alignment,0x1000 \
-Wl,--section-alignment,0x1000 \
-Wl,temp.exp
- $(RM) temp.exp
$(NM) --numeric-sort $(TARGETNAME).dll > $(TARGETNAME).sym
clean: $(CLEAN_FILES:%=%_clean)
$(CLEAN_FILES:%=%_clean): %_clean:
- $(RM) $*
.PHONY: clean $(CLEAN_FILES:%=%_clean)
install: $(FLOPPY_DIR)/dlls/$(TARGETNAME).dll
$(FLOPPY_DIR)/dlls/$(TARGETNAME).dll: $(TARGETNAME).dll
ifeq ($(DOSCLI),yes)
$(CP) $(TARGETNAME).dll $(FLOPPY_DIR)\dlls\$(TARGETNAME).dll
else
$(CP) $(TARGETNAME).dll $(FLOPPY_DIR)/dlls/$(TARGETNAME).dll
endif
dist: $(DIST_DIR)/dlls/$(TARGETNAME).dll
$(DIST_DIR)/dlls/$(TARGETNAME).dll: $(TARGETNAME).dll
ifeq ($(DOSCLI),yes)
$(CP) $(TARGETNAME).dll ..\..\$(DIST_DIR)\dlls\$(TARGETNAME).dll
else
$(CP) $(TARGETNAME).dll ../../$(DIST_DIR)/dlls/$(TARGETNAME).dll
endif
include ../../rules.mak

View file

@ -0,0 +1,561 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver DLL
* FILE: misc/dllmain.c
* PURPOSE: DLL entry point
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <msafd.h>
#include <helpers.h>
#ifdef DBG
/* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = MAX_TRACE;
#endif /* DBG */
/* To make the linker happy */
VOID STDCALL KeBugCheck (ULONG BugCheckCode) {}
HANDLE GlobalHeap;
WSPUPCALLTABLE Upcalls;
LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
CRITICAL_SECTION InitCriticalSection;
DWORD StartupCount = 0;
NTSTATUS OpenSocket(
SOCKET *Socket,
INT AddressFamily,
INT SocketType,
INT Protocol,
PVOID HelperContext,
DWORD NotificationEvents,
PUNICODE_STRING TdiDeviceName)
/*
* FUNCTION: Opens a socket
* ARGUMENTS:
* Socket = Address of buffer to place socket descriptor
* AddressFamily = Address family
* SocketType = Type of socket
* Protocol = Protocol type
* HelperContext = Pointer to context information for helper DLL
* NotificationEvents = Events for which helper DLL is to be notified
* TdiDeviceName = Pointer to name of TDI device to use
* RETURNS:
* Status of operation
*/
{
OBJECT_ATTRIBUTES ObjectAttributes;
PAFD_SOCKET_INFORMATION SocketInfo;
PFILE_FULL_EA_INFORMATION EaInfo;
UNICODE_STRING DeviceName;
IO_STATUS_BLOCK Iosb;
HANDLE FileHandle;
NTSTATUS Status;
ULONG EaLength;
CP
EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
AFD_SOCKET_LENGTH +
sizeof(AFD_SOCKET_INFORMATION) +
TdiDeviceName->Length + 1;
EaInfo = (PFILE_FULL_EA_INFORMATION)HeapAlloc(GlobalHeap, 0, EaLength);
if (!EaInfo) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
CP
RtlZeroMemory(EaInfo, EaLength);
EaInfo->EaNameLength = AFD_SOCKET_LENGTH;
RtlCopyMemory(EaInfo->EaName,
AfdSocket,
AFD_SOCKET_LENGTH);
EaInfo->EaValueLength = sizeof(AFD_SOCKET_INFORMATION);
CP
SocketInfo = (PAFD_SOCKET_INFORMATION)(EaInfo->EaName + AFD_SOCKET_LENGTH);
SocketInfo->AddressFamily = AddressFamily;
SocketInfo->SocketType = SocketType;
SocketInfo->Protocol = Protocol;
SocketInfo->HelperContext = HelperContext;
SocketInfo->NotificationEvents = NotificationEvents;
/* Store TDI device name last in buffer */
SocketInfo->TdiDeviceName.Buffer = (PWCHAR)(EaInfo + EaLength);
//SocketInfo->TdiDeviceName.Length = TdiDeviceName.Length;
SocketInfo->TdiDeviceName.MaximumLength = TdiDeviceName->Length;
RtlCopyUnicodeString(&SocketInfo->TdiDeviceName, TdiDeviceName);
/*RtlCopyMemory(SocketInfo->TdiDeviceName.Buffer,
TdiDeviceName.Buffer,
TdiDeviceName.Length + 1);*/
AFD_DbgPrint(MAX_TRACE, ("EaInfo at (0x%X) EaLength is (%d).\n", (UINT)EaInfo, (INT)EaLength));
RtlInitUnicodeString(&DeviceName, L"\\Device\\Afd");
InitializeObjectAttributes(&ObjectAttributes,
&DeviceName,
0,
NULL,
NULL);
CP
Status = NtCreateFile(&FileHandle,
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
&ObjectAttributes,
&Iosb,
NULL,
0,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_ALERT,
EaInfo,
EaLength);
CP
HeapFree(GlobalHeap, 0, EaInfo);
CP
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("Error opening device (Status 0x%X).\n", (UINT)Status));
return STATUS_INSUFFICIENT_RESOURCES;
}
CP
*Socket = (SOCKET)FileHandle;
return STATUS_SUCCESS;
}
SOCKET
WSPAPI
WSPSocket(
IN INT af,
IN INT type,
IN INT protocol,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
IN GROUP g,
IN DWORD dwFlags,
OUT LPINT lpErrno)
/*
* FUNCTION: Creates a new socket
* ARGUMENTS:
* af = Address family
* type = Socket type
* protocol = Protocol type
* lpProtocolInfo = Pointer to protocol information
* g = Reserved
* dwFlags = Socket flags
* lpErrno = Address of buffer for error information
* RETURNS:
* Created socket, or INVALID_SOCKET if it could not be created
*/
{
WSAPROTOCOL_INFOW ProtocolInfo;
UNICODE_STRING TdiDeviceName;
DWORD NotificationEvents;
PWSHELPER_DLL HelperDLL;
PVOID HelperContext;
INT AddressFamily;
NTSTATUS NtStatus;
INT SocketType;
SOCKET Socket2;
SOCKET Socket;
INT Protocol;
INT Status;
AFD_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
af, type, protocol));
if (!lpProtocolInfo) {
CP
lpProtocolInfo = &ProtocolInfo;
ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
ProtocolInfo.iAddressFamily = af;
ProtocolInfo.iSocketType = type;
ProtocolInfo.iProtocol = protocol;
}
CP
HelperDLL = LocateHelperDLL(lpProtocolInfo);
if (!HelperDLL) {
*lpErrno = WSAEAFNOSUPPORT;
return INVALID_SOCKET;
}
CP
AddressFamily = lpProtocolInfo->iAddressFamily;
SocketType = lpProtocolInfo->iSocketType;
Protocol = lpProtocolInfo->iProtocol;
CP
Status = HelperDLL->EntryTable.lpWSHOpenSocket2(&AddressFamily,
&SocketType,
&Protocol,
0,
0,
&TdiDeviceName,
&HelperContext,
&NotificationEvents);
if (Status != NO_ERROR) {
*lpErrno = Status;
return INVALID_SOCKET;
}
CP
NtStatus = OpenSocket(&Socket,
AddressFamily,
SocketType,
Protocol,
HelperContext,
NotificationEvents,
&TdiDeviceName);
CP
RtlFreeUnicodeString(&TdiDeviceName);
if (!NT_SUCCESS(NtStatus)) {
CP
*lpErrno = RtlNtStatusToDosError(Status);
return INVALID_SOCKET;
}
CP
/* FIXME: Assumes catalog entry id to be 1 */
Socket2 = Upcalls.lpWPUModifyIFSHandle(1, Socket, lpErrno);
CP
if (Socket2 == INVALID_SOCKET) {
/* FIXME: Cleanup */
AFD_DbgPrint(MIN_TRACE, ("FIXME: Cleanup.\n"));
return INVALID_SOCKET;
}
*lpErrno = NO_ERROR;
AFD_DbgPrint(MID_TRACE, ("Returning socket descriptor (0x%X).\n", Socket2));
return Socket2;
}
INT
WSPAPI
WSPCloseSocket(
IN SOCKET s,
OUT LPINT lpErrno)
/*
* FUNCTION: Closes an open socket
* ARGUMENTS:
* s = Socket descriptor
* lpErrno = Address of buffer for error information
* RETURNS:
* NO_ERROR, or SOCKET_ERROR if the socket could not be closed
*/
{
NTSTATUS Status;
AFD_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
Status = NtClose((HANDLE)s);
CP
if (NT_SUCCESS(Status)) {
*lpErrno = NO_ERROR;
return NO_ERROR;
}
*lpErrno = WSAENOTSOCK;
return SOCKET_ERROR;
}
INT
WSPAPI
WSPBind(
IN SOCKET s,
IN CONST LPSOCKADDR name,
IN INT namelen,
OUT LPINT lpErrno)
/*
* FUNCTION: Associates a local address with a socket
* ARGUMENTS:
* s = Socket descriptor
* name = Pointer to local address
* namelen = Length of name
* lpErrno = Address of buffer for error information
* RETURNS:
* 0, or SOCKET_ERROR if the socket could not be bound
*/
{
AFD_DbgPrint(MAX_TRACE, ("s (0x%X) name (0x%X) namelen (%d).\n", s, name, namelen));
#if 0
FILE_REQUEST_BIND Request;
FILE_REPLY_BIND Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
RtlCopyMemory(&Request.Name, name, sizeof(SOCKADDR));
Status = NtDeviceIoControlFile((HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_BIND,
&Request,
sizeof(FILE_REQUEST_BIND),
&Reply,
sizeof(FILE_REPLY_BIND));
if (Status == STATUS_PENDING) {
if (!NT_SUCCESS(NtWaitForSingleObject((HANDLE)s, FALSE, NULL))) {
/* FIXME: What error code should be returned? */
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
}
if (!NT_SUCCESS(Status)) {
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
#endif
return 0;
}
INT
WSPAPI
WSPSelect(
IN INT nfds,
IN OUT LPFD_SET readfds,
IN OUT LPFD_SET writefds,
IN OUT LPFD_SET exceptfds,
IN CONST LPTIMEVAL timeout,
OUT LPINT lpErrno)
/*
* FUNCTION: Returns status of one or more sockets
* ARGUMENTS:
* nfds = Always ignored
* readfds = Pointer to socket set to be checked for readability (optional)
* writefds = Pointer to socket set to be checked for writability (optional)
* exceptfds = Pointer to socket set to be checked for errors (optional)
* timeout = Pointer to a TIMEVAL structure indicating maximum wait time
* (NULL means wait forever)
* lpErrno = Address of buffer for error information
* RETURNS:
* Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
*/
{
AFD_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
readfds, writefds, exceptfds));
/* FIXME: For now, always allow write */
if (writefds != NULL) {
AFD_DbgPrint(MAX_TRACE, ("Setting one socket writeable.\n"));
return 1;
}
return 0;
}
INT
WSPAPI
WSPStartup(
IN WORD wVersionRequested,
OUT LPWSPDATA lpWSPData,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
IN WSPUPCALLTABLE UpcallTable,
OUT LPWSPPROC_TABLE lpProcTable)
/*
* FUNCTION: Initialize service provider for a client
* ARGUMENTS:
* wVersionRequested = Highest WinSock SPI version that the caller can use
* lpWSPData = Address of WSPDATA structure to initialize
* lpProtocolInfo = Pointer to structure that defines the desired protocol
* UpcallTable = Pointer to upcall table of the WinSock DLL
* lpProcTable = Address of procedure table to initialize
* RETURNS:
* Status of operation
*/
{
HMODULE hWS2_32;
INT Status;
AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested));
//EnterCriticalSection(&InitCriticalSection);
Upcalls = UpcallTable;
if (StartupCount == 0) {
/* First time called */
Status = WSAVERNOTSUPPORTED;
CP
hWS2_32 = GetModuleHandle(L"ws2_32.dll");
CP
if (hWS2_32) {
CP
lpWPUCompleteOverlappedRequest = (LPWPUCOMPLETEOVERLAPPEDREQUEST)
GetProcAddress(hWS2_32, "WPUCompleteOverlappedRequest");
CP
if (lpWPUCompleteOverlappedRequest) {
Status = NO_ERROR;
StartupCount++;
}
CP
}
} else {
Status = NO_ERROR;
StartupCount++;
}
//LeaveCriticalSection(&InitCriticalSection);
if (Status == NO_ERROR) {
CP
lpProcTable->lpWSPAccept = WSPAccept;
lpProcTable->lpWSPAddressToString = WSPAddressToString;
lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
lpProcTable->lpWSPBind = WSPBind;
lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
lpProcTable->lpWSPCleanup = WSPCleanup;
lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
lpProcTable->lpWSPConnect = WSPConnect;
lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
lpProcTable->lpWSPEventSelect = WSPEventSelect;
lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
lpProcTable->lpWSPGetSockName = WSPGetSockName;
lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
lpProcTable->lpWSPIoctl = WSPIoctl;
lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
lpProcTable->lpWSPListen = WSPListen;
lpProcTable->lpWSPRecv = WSPRecv;
lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
lpProcTable->lpWSPSelect = WSPSelect;
lpProcTable->lpWSPSend = WSPSend;
lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
lpProcTable->lpWSPSendTo = WSPSendTo;
lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
lpProcTable->lpWSPShutdown = WSPShutdown;
lpProcTable->lpWSPSocket = WSPSocket;
lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
lpWSPData->wVersion = MAKEWORD(2, 2);
lpWSPData->wHighVersion = MAKEWORD(2, 2);
CP
}
AFD_DbgPrint(MIN_TRACE, ("Status (%d).\n", Status));
return Status;
}
INT
WSPAPI
WSPCleanup(
OUT LPINT lpErrno)
/*
* FUNCTION: Cleans up service provider for a client
* ARGUMENTS:
* lpErrno = Address of buffer for error information
* RETURNS:
* 0 if successful, or SOCKET_ERROR if not
*/
{
AFD_DbgPrint(MAX_TRACE, ("\n"));
//EnterCriticalSection(&InitCriticalSection);
if (StartupCount > 0) {
StartupCount--;
if (StartupCount == 0) {
AFD_DbgPrint(MAX_TRACE, ("Cleaning up msafd.dll.\n"));
}
}
//LeaveCriticalSection(&InitCriticalSection);
*lpErrno = NO_ERROR;
CP
return 0;
}
BOOL
STDCALL
DllMain(HANDLE hInstDll,
ULONG dwReason,
PVOID Reserved)
{
AFD_DbgPrint(MIN_TRACE, ("DllMain of msafd.dll\n"));
switch (dwReason) {
case DLL_PROCESS_ATTACH:
CP
/* Don't need thread attach notifications
so disable them to improve performance */
DisableThreadLibraryCalls(hInstDll);
CP
//InitializeCriticalSection(&InitCriticalSection);
GlobalHeap = GetProcessHeap();
//GlobalHeap = HeapCreate(0, 0, 0);
if (!GlobalHeap) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return FALSE;
}
CP
CreateHelperDLLDatabase();
CP
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
CP
DestroyHelperDLLDatabase();
//HeapDestroy(GlobalHeap);
//DeleteCriticalSection(&InitCriticalSection);
break;
}
CP
return TRUE;
}
/* EOF */

View file

@ -0,0 +1,251 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver DLL
* FILE: misc/helpers.c
* PURPOSE: Helper DLL management
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <msafd.h>
#include <helpers.h>
//CRITICAL_SECTION HelperDLLDatabaseLock;
LIST_ENTRY HelperDLLDatabaseListHead;
PWSHELPER_DLL CreateHelperDLL(
LPWSTR LibraryName)
{
PWSHELPER_DLL HelperDLL;
HelperDLL = HeapAlloc(GlobalHeap, 0, sizeof(WSHELPER_DLL));
if (!HelperDLL) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return NULL;
}
//InitializeCriticalSection(&HelperDLL->Lock);
HelperDLL->hModule = NULL;
lstrcpyW(HelperDLL->LibraryName, LibraryName);
HelperDLL->Mapping = NULL;
//EnterCriticalSection(&HelperDLLDatabaseLock);
InsertTailList(&HelperDLLDatabaseListHead, &HelperDLL->ListEntry);
//LeaveCriticalSection(&HelperDLLDatabaseLock);
AFD_DbgPrint(MAX_TRACE, ("Returning helper at (0x%X).\n", HelperDLL));
return HelperDLL;
}
INT DestroyHelperDLL(
PWSHELPER_DLL HelperDLL)
{
INT Status;
AFD_DbgPrint(MAX_TRACE, ("HelperDLL (0x%X).\n", HelperDLL));
//EnterCriticalSection(&HelperDLLDatabaseLock);
RemoveEntryList(&HelperDLL->ListEntry);
//LeaveCriticalSection(&HelperDLLDatabaseLock);
CP
if (HelperDLL->hModule) {
Status = UnloadHelperDLL(HelperDLL);
} else {
Status = NO_ERROR;
}
CP
if (HelperDLL->Mapping)
HeapFree(GlobalHeap, 0, HelperDLL->Mapping);
//DeleteCriticalSection(&HelperDLL->Lock);
HeapFree(GlobalHeap, 0, HelperDLL);
CP
return Status;
}
PWSHELPER_DLL LocateHelperDLL(
LPWSAPROTOCOL_INFOW lpProtocolInfo)
{
PLIST_ENTRY CurrentEntry;
PWSHELPER_DLL HelperDLL;
UINT i;
//EnterCriticalSection(&HelperDLLDatabaseLock);
CurrentEntry = HelperDLLDatabaseListHead.Flink;
while (CurrentEntry != &HelperDLLDatabaseListHead) {
HelperDLL = CONTAINING_RECORD(CurrentEntry,
WSHELPER_DLL,
ListEntry);
for (i = 0; i < HelperDLL->Mapping->Rows; i++) {
if ((lpProtocolInfo->iAddressFamily == HelperDLL->Mapping->Mapping[i].AddressFamily) &&
(lpProtocolInfo->iSocketType == HelperDLL->Mapping->Mapping[i].SocketType) &&
((lpProtocolInfo->iProtocol == HelperDLL->Mapping->Mapping[i].Protocol) ||
(lpProtocolInfo->iSocketType == SOCK_RAW))) {
//LeaveCriticalSection(&HelperDLLDatabaseLock);
AFD_DbgPrint(MAX_TRACE, ("Returning helper DLL at (0x%X).\n", HelperDLL));
return HelperDLL;
}
}
CurrentEntry = CurrentEntry->Flink;
}
//LeaveCriticalSection(&HelperDLLDatabaseLock);
AFD_DbgPrint(MAX_TRACE, ("Could not locate helper DLL.\n"));
return NULL;
}
#define GET_ENTRY_POINT(helper, name) { \
PVOID entry; \
\
entry = GetProcAddress(helper->hModule, "##name"); \
if (!entry) \
return ERROR_BAD_PROVIDER; \
(*(PULONG*)helper->EntryTable.lp##name) = entry; \
}
INT GetHelperDLLEntries(
PWSHELPER_DLL HelperDLL)
{
GET_ENTRY_POINT(HelperDLL, WSHAddressToString);
GET_ENTRY_POINT(HelperDLL, WSHEnumProtocols);
GET_ENTRY_POINT(HelperDLL, WSHGetBroadcastSockaddr);
GET_ENTRY_POINT(HelperDLL, WSHGetProviderGuid);
GET_ENTRY_POINT(HelperDLL, WSHGetSockaddrType);
GET_ENTRY_POINT(HelperDLL, WSHGetSocketInformation);
GET_ENTRY_POINT(HelperDLL, WSHGetWildcardSockaddr);
GET_ENTRY_POINT(HelperDLL, WSHGetWinsockMapping);
GET_ENTRY_POINT(HelperDLL, WSHGetWSAProtocolInfo);
GET_ENTRY_POINT(HelperDLL, WSHIoctl);
GET_ENTRY_POINT(HelperDLL, WSHJoinLeaf);
GET_ENTRY_POINT(HelperDLL, WSHNotify);
GET_ENTRY_POINT(HelperDLL, WSHOpenSocket);
GET_ENTRY_POINT(HelperDLL, WSHOpenSocket2);
GET_ENTRY_POINT(HelperDLL, WSHSetSocketInformation);
GET_ENTRY_POINT(HelperDLL, WSHStringToAddress);
return NO_ERROR;
}
INT LoadHelperDLL(
PWSHELPER_DLL HelperDLL)
{
INT Status = NO_ERROR;
AFD_DbgPrint(MAX_TRACE, ("Loading helper dll at (0x%X).\n", HelperDLL));
if (!HelperDLL->hModule) {
/* DLL is not loaded so load it now */
HelperDLL->hModule = LoadLibrary(HelperDLL->LibraryName);
if (HelperDLL->hModule) {
Status = GetHelperDLLEntries(HelperDLL);
} else
Status = ERROR_DLL_NOT_FOUND;
} else
Status = NO_ERROR;
AFD_DbgPrint(MIN_TRACE, ("Status (%d).\n", Status));
return Status;
}
INT UnloadHelperDLL(
PWSHELPER_DLL HelperDLL)
{
INT Status = NO_ERROR;
AFD_DbgPrint(MAX_TRACE, ("HelperDLL (0x%X).\n", HelperDLL));
if (HelperDLL->hModule) {
if (!FreeLibrary(HelperDLL->hModule))
Status = GetLastError();
HelperDLL->hModule = NULL;
}
return Status;
}
VOID CreateHelperDLLDatabase(VOID)
{
PWSHELPER_DLL HelperDLL;
CP
//InitializeCriticalSection(&HelperDLLDatabaseLock);
InitializeListHead(&HelperDLLDatabaseListHead);
/* FIXME: Read helper DLL configuration from registry */
HelperDLL = CreateHelperDLL(L"wshtcpip.dll");
if (!HelperDLL) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return;
}
CP
HelperDLL->Mapping = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD));
if (!HelperDLL->Mapping) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return;
}
CP
HelperDLL->Mapping->Rows = 1;
HelperDLL->Mapping->Columns = 3;
HelperDLL->Mapping->Mapping[0].AddressFamily = AF_INET;
HelperDLL->Mapping->Mapping[0].SocketType = SOCK_RAW;
HelperDLL->Mapping->Mapping[0].Protocol = 0;
CP
LoadHelperDLL(HelperDLL);
CP
}
VOID DestroyHelperDLLDatabase(VOID)
{
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PWSHELPER_DLL HelperDLL;
CP
CurrentEntry = HelperDLLDatabaseListHead.Flink;
while (CurrentEntry != &HelperDLLDatabaseListHead) {
NextEntry = CurrentEntry->Flink;
HelperDLL = CONTAINING_RECORD(CurrentEntry,
WSHELPER_DLL,
ListEntry);
DestroyHelperDLL(HelperDLL);
CurrentEntry = NextEntry;
}
CP
//DeleteCriticalSection(&HelperDLLDatabaseLock);
}
/* EOF */

View file

@ -0,0 +1,247 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver DLL
* FILE: misc/sndrcv.c
* PURPOSE: Send/receive routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <msafd.h>
INT
WSPAPI
WSPAsyncSelect(
IN SOCKET s,
IN HWND hWnd,
IN UINT wMsg,
IN LONG lEvent,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPRecv(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPRecvDisconnect(
IN SOCKET s,
OUT LPWSABUF lpInboundDisconnectData,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPRecvFrom(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
OUT LPSOCKADDR lpFrom,
IN OUT LPINT lpFromLen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
PFILE_REQUEST_RECVFROM Request;
FILE_REPLY_RECVFROM Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
DWORD Size;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
Size = dwBufferCount * sizeof(WSABUF);
Request = (PFILE_REQUEST_RECVFROM)HeapAlloc(
GlobalHeap, 0, sizeof(FILE_REQUEST_RECVFROM) + Size);
if (!Request) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
/* Put buffer pointers after request structure */
Request->Buffers = (LPWSABUF)(Request + sizeof(FILE_REQUEST_RECVFROM));
Request->BufferCount = dwBufferCount;
Request->Flags = lpFlags;
Request->From = lpFrom;
Request->FromLen = lpFromLen;
RtlCopyMemory(Request->Buffers, lpBuffers, Size);
Status = NtDeviceIoControlFile((HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_RECVFROM,
Request,
sizeof(FILE_REQUEST_RECVFROM) + Size,
&Reply,
sizeof(FILE_REPLY_RECVFROM));
HeapFree(GlobalHeap, 0, Request);
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
if (!NT_SUCCESS(NtWaitForSingleObject((HANDLE)s, FALSE, NULL))) {
AFD_DbgPrint(MAX_TRACE, ("Wait failed.\n"));
/* FIXME: What error code should be returned? */
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
}
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
AFD_DbgPrint(MAX_TRACE, ("Receive successful.\n"));
return 0;
}
INT
WSPAPI
WSPSend(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPSendDisconnect(
IN SOCKET s,
IN LPWSABUF lpOutboundDisconnectData,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPSendTo(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN CONST LPSOCKADDR lpTo,
IN INT iToLen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
PFILE_REQUEST_SENDTO Request;
FILE_REPLY_SENDTO Reply;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
DWORD Size;
AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
Size = dwBufferCount * sizeof(WSABUF);
Request = (PFILE_REQUEST_SENDTO)HeapAlloc(
GlobalHeap, 0, sizeof(FILE_REQUEST_SENDTO) + Size);
if (!Request) {
AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
/* Put buffer pointers after request structure */
Request->Buffers = (LPWSABUF)(Request + sizeof(FILE_REQUEST_SENDTO));
Request->BufferCount = dwBufferCount;
Request->Flags = dwFlags;
Request->ToLen = iToLen;
RtlCopyMemory(&Request->To, lpTo, sizeof(SOCKADDR));
RtlCopyMemory(Request->Buffers, lpBuffers, Size);
Status = NtDeviceIoControlFile((HANDLE)s,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_AFD_SENDTO,
Request,
sizeof(FILE_REQUEST_SENDTO) + Size,
&Reply,
sizeof(FILE_REPLY_SENDTO));
HeapFree(GlobalHeap, 0, Request);
if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */
if (!NT_SUCCESS(NtWaitForSingleObject((HANDLE)s, FALSE, NULL))) {
AFD_DbgPrint(MAX_TRACE, ("Wait failed.\n"));
/* FIXME: What error code should be returned? */
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
}
if (!NT_SUCCESS(Status)) {
AFD_DbgPrint(MIN_TRACE, ("Status (0x%X).\n", Status));
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
AFD_DbgPrint(MAX_TRACE, ("Send successful.\n"));
return 0;
}
/* EOF */

View file

@ -0,0 +1,287 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Ancillary Function Driver DLL
* FILE: misc/stubs.c
* PURPOSE: Stubs
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <msafd.h>
SOCKET
WSPAPI
WSPAccept(
IN SOCKET s,
OUT LPSOCKADDR addr,
IN OUT LPINT addrlen,
IN LPCONDITIONPROC lpfnCondition,
IN DWORD dwCallbackData,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return INVALID_SOCKET;
}
INT
WSPAPI
WSPAddressToString(
IN LPSOCKADDR lpsaAddress,
IN DWORD dwAddressLength,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
OUT LPWSTR lpszAddressString,
IN OUT LPDWORD lpdwAddressStringLength,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPCancelBlockingCall(
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPConnect(
IN SOCKET s,
IN CONST LPSOCKADDR name,
IN INT namelen,
IN LPWSABUF lpCallerData,
OUT LPWSABUF lpCalleeData,
IN LPQOS lpSQOS,
IN LPQOS lpGQOS,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPDuplicateSocket(
IN SOCKET s,
IN DWORD dwProcessId,
OUT LPWSAPROTOCOL_INFOW lpProtocolInfo,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPEnumNetworkEvents(
IN SOCKET s,
IN WSAEVENT hEventObject,
OUT LPWSANETWORKEVENTS lpNetworkEvents,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPEventSelect(
IN SOCKET s,
IN WSAEVENT hEventObject,
IN LONG lNetworkEvents,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
BOOL
WSPAPI
WSPGetOverlappedResult(
IN SOCKET s,
IN LPWSAOVERLAPPED lpOverlapped,
OUT LPDWORD lpcbTransfer,
IN BOOL fWait,
OUT LPDWORD lpdwFlags,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return FALSE;
}
INT
WSPAPI
WSPGetPeerName(
IN SOCKET s,
OUT LPSOCKADDR name,
IN OUT LPINT namelen,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
BOOL
WSPAPI
WSPGetQOSByName(
IN SOCKET s,
IN OUT LPWSABUF lpQOSName,
OUT LPQOS lpQOS,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return FALSE;
}
INT
WSPAPI
WSPGetSockName(
IN SOCKET s,
OUT LPSOCKADDR name,
IN OUT LPINT namelen,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPGetSockOpt(
IN SOCKET s,
IN INT level,
IN INT optname,
OUT CHAR FAR* optval,
IN OUT LPINT optlen,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPIoctl(
IN SOCKET s,
IN DWORD dwIoControlCode,
IN LPVOID lpvInBuffer,
IN DWORD cbInBuffer,
OUT LPVOID lpvOutBuffer,
IN DWORD cbOutBuffer,
OUT LPDWORD lpcbBytesReturned,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IN LPWSATHREADID lpThreadId,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
SOCKET
WSPAPI
WSPJoinLeaf(
IN SOCKET s,
IN CONST LPSOCKADDR name,
IN INT namelen,
IN LPWSABUF lpCallerData,
OUT LPWSABUF lpCalleeData,
IN LPQOS lpSQOS,
IN LPQOS lpGQOS,
IN DWORD dwFlags,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return (SOCKET)0;
}
INT
WSPAPI
WSPListen(
IN SOCKET s,
IN INT backlog,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPSetSockOpt(
IN SOCKET s,
IN INT level,
IN INT optname,
IN CONST CHAR FAR* optval,
IN INT optlen,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPShutdown(
IN SOCKET s,
IN INT how,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
INT
WSPAPI
WSPStringToAddress(
IN LPWSTR AddressString,
IN INT AddressFamily,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
OUT LPSOCKADDR lpAddress,
IN OUT LPINT lpAddressLength,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
return 0;
}
/* EOF */

View file

@ -0,0 +1,10 @@
; MSAFD.DLL - Ancillary Function Driver DLL
LIBRARY msafd.dll
EXPORTS
WSPGetSockOpt@24
WSPSetSockOpt@24
WSPStartup@76
; EOF

View file

@ -0,0 +1,10 @@
; MSAFD.DLL - Ancillary Function Driver DLL
LIBRARY msafd.dll
EXPORTS
WSPGetSockOpt=WSPGetSockOpt@24
WSPSetSockOpt=WSPSetSockOpt@24
WSPStartup=WSPStartup@76
; EOF

View file

@ -0,0 +1,39 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "Ancillary Function Driver DLL\0"
VALUE "FileVersion", RES_STR_FILE_VERSION
VALUE "InternalName", "msafd\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "msafd.dll\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -12,9 +12,11 @@
typedef struct _CATALOG_ENTRY {
LIST_ENTRY ListEntry;
ULONG ReferenceCount;
CRITICAL_SECTION Lock;
WCHAR LibraryName[MAX_PATH];
HMODULE hModule;
WSAPROTOCOL_INFOW ProtocolInfo;
PWINSOCK_MAPPING Mapping;
LPWSPSTARTUP WSPStartup;
WSPDATA WSPData;
@ -23,6 +25,13 @@ typedef struct _CATALOG_ENTRY {
extern LIST_ENTRY Catalog;
VOID ReferenceProviderByPointer(
PCATALOG_ENTRY Provider);
VOID DereferenceProviderByPointer(
PCATALOG_ENTRY Provider);
PCATALOG_ENTRY CreateCatalogEntry(
LPWSTR LibraryName);
@ -32,6 +41,9 @@ INT DestroyCatalogEntry(
PCATALOG_ENTRY LocateProvider(
LPWSAPROTOCOL_INFOW lpProtocolInfo);
PCATALOG_ENTRY LocateProviderById(
DWORD CatalogEntryId);
INT LoadProvider(
PCATALOG_ENTRY Provider,
LPWSAPROTOCOL_INFOW lpProtocolInfo);

View file

@ -21,16 +21,11 @@
extern DWORD DebugTraceLevel;
#define Get_DbgPrint(quote...) L##quote
#define WS_DbgPrint(_t_, _x_) \
if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
WCHAR _buffer[256]; \
swprintf(_buffer, L"(%S:%d)(%S) ", __FILE__, __LINE__, __FUNCTION__); \
OutputDebugStringW(_buffer); \
swprintf(_buffer, Get_DbgPrint _x_); \
OutputDebugStringW(_buffer); \
DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \
DbgPrint _x_; \
}
#ifdef ASSERT
@ -63,7 +58,9 @@ extern DWORD DebugTraceLevel;
WS_DbgPrint(MIN_TRACE, ("is unimplemented, please try again later.\n"));
#define CHECKPOINT \
do { WS_DbgPrint(MIN_TRACE, ("\n")); } while(0);
WS_DbgPrint(MIN_TRACE, ("\n"));
#define CP CHECKPOINT
#endif /* __DEBUG_H */

View file

@ -0,0 +1,47 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: include/handle.h
* PURPOSE: Provider handle definitions
*/
#ifndef __HANDLE_H
#define __HANDLE_H
#include <ws2_32.h>
#include <catalog.h>
typedef struct _PROVIDER_HANDLE {
HANDLE Handle;
PCATALOG_ENTRY Provider;
} PROVIDER_HANDLE, *PPROVIDER_HANDLE;
#define HANDLE_BLOCK_ENTRIES ((PAGESIZE-sizeof(LIST_ENTRY))/sizeof(PROVIDER_HANDLE))
typedef struct _PROVIDER_HANDLE_BLOCK {
LIST_ENTRY Entry;
PROVIDER_HANDLE Handles[HANDLE_BLOCK_ENTRIES];
} PROVIDER_HANDLE_BLOCK, *PPROVIDER_HANDLE_BLOCK;
extern PPROVIDER_HANDLE_BLOCK ProviderHandleTable;
HANDLE
CreateProviderHandle(HANDLE Handle,
PCATALOG_ENTRY Provider);
BOOL
ReferenceProviderByHandle(HANDLE Handle,
PCATALOG_ENTRY* Provider);
BOOL
CloseProviderHandle(HANDLE Handle);
BOOL
InitProviderHandleTable(VOID);
VOID
FreeProviderHandleTable(VOID);
#endif /* __HANDLE_H */
/* EOF */

View file

@ -26,6 +26,7 @@ extern WSPUPCALLTABLE UpcallTable;
typedef struct _WINSOCK_THREAD_BLOCK {
INT LastErrorValue; /* Error value from last function that failed */
BOOL Initialized; /* TRUE if WSAStartup() has been successfully called */
CHAR Intoa[16]; /* Buffer for inet_ntoa() */
} WINSOCK_THREAD_BLOCK, *PWINSOCK_THREAD_BLOCK;

View file

@ -2,12 +2,12 @@
PATH_TO_TOP = ../..
CFLAGS = -Iinclude -DUNICODE
CFLAGS = -Iinclude -DUNICODE -DDBG
TARGETNAME=ws2_32
MISC_OBJECTS = misc/dllmain.o misc/catalog.o misc/event.o misc/ns.o \
misc/stubs.o misc/upcall.o
MISC_OBJECTS = misc/dllmain.o misc/catalog.o misc/event.o misc/handle.o \
misc/ns.o misc/sndrcv.o misc/stubs.o misc/upcall.o
RESOURCE_OBJECT = $(TARGETNAME).coff
@ -44,7 +44,6 @@ $(TARGETNAME).dll: $(LIBS) $(OBJECTS) $(TARGETNAME).def
$(CC) \
$(TARGETNAME).o \
$(LIBS) \
-specs=$(TARGETNAME)_specs \
-mdll \
-o junk.tmp \
-Wl,--base-file,base.tmp
@ -58,10 +57,9 @@ $(TARGETNAME).dll: $(LIBS) $(OBJECTS) $(TARGETNAME).def
$(CC) \
$(TARGETNAME).o \
$(LIBS) \
-specs=$(TARGETNAME)_specs \
-mdll \
-o $(TARGETNAME).dll \
-Wl,--image-base,0x10000 \
-Wl,--image-base,0x77780000 \
-Wl,--file-alignment,0x1000 \
-Wl,--section-alignment,0x1000 \
-Wl,temp.exp

View file

@ -14,23 +14,74 @@
LIST_ENTRY CatalogListHead;
CRITICAL_SECTION CatalogLock;
VOID ReferenceProviderByPointer(
PCATALOG_ENTRY Provider)
{
WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
//EnterCriticalSection(&Provider->Lock);
Provider->ReferenceCount++;
//LeaveCriticalSection(&Provider->Lock);
}
VOID DereferenceProviderByPointer(
PCATALOG_ENTRY Provider)
{
WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
#ifdef DBG
if (Provider->ReferenceCount <= 0) {
WS_DbgPrint(MIN_TRACE, ("Provider at 0x%X has invalid reference count (%ld).\n",
Provider, Provider->ReferenceCount));
}
#endif
//EnterCriticalSection(&Provider->Lock);
Provider->ReferenceCount--;
//LeaveCriticalSection(&Provider->Lock);
if (Provider->ReferenceCount == 0) {
DestroyCatalogEntry(Provider);
}
}
PCATALOG_ENTRY CreateCatalogEntry(
LPWSTR LibraryName)
{
PCATALOG_ENTRY Provider;
Provider = HeapAlloc(GlobalHeap, 0, sizeof(CATALOG_ENTRY));
if (!Provider)
return NULL;
WS_DbgPrint(MAX_TRACE, ("LibraryName (%S).\n", LibraryName));
InitializeCriticalSection(&Provider->Lock);
Provider->hModule = (HMODULE)INVALID_HANDLE_VALUE;
Provider = HeapAlloc(GlobalHeap, 0, sizeof(CATALOG_ENTRY));
if (!Provider) {
WS_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return NULL;
}
CP
ZeroMemory(Provider, sizeof(CATALOG_ENTRY));
CP
Provider->ReferenceCount = 1;
//InitializeCriticalSection(&Provider->Lock);
CP
Provider->hModule = NULL;
CP
lstrcpyW(Provider->LibraryName, LibraryName);
CP
Provider->Mapping = NULL;
EnterCriticalSection(&CatalogLock);
CP
//EnterCriticalSection(&CatalogLock);
CP
InsertTailList(&CatalogListHead, &Provider->ListEntry);
LeaveCriticalSection(&CatalogLock);
CP
//LeaveCriticalSection(&CatalogLock);
CP
return Provider;
}
@ -41,22 +92,27 @@ INT DestroyCatalogEntry(
{
INT Status;
EnterCriticalSection(&CatalogLock);
WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
CP
//EnterCriticalSection(&CatalogLock);
RemoveEntryList(&Provider->ListEntry);
LeaveCriticalSection(&CatalogLock);
//LeaveCriticalSection(&CatalogLock);
CP
HeapFree(GlobalHeap, 0, Provider->Mapping);
if (Provider->hModule != (HMODULE)INVALID_HANDLE_VALUE) {
CP
if (Provider->hModule) {
CP
Status = UnloadProvider(Provider);
CP
} else {
Status = NO_ERROR;
}
DeleteCriticalSection(&Provider->Lock);
CP
//DeleteCriticalSection(&Provider->Lock);
HeapFree(GlobalHeap, 0, Provider);
CP
return Status;
}
@ -68,7 +124,9 @@ PCATALOG_ENTRY LocateProvider(
PCATALOG_ENTRY Provider;
UINT i;
EnterCriticalSection(&CatalogLock);
WS_DbgPrint(MAX_TRACE, ("lpProtocolInfo (0x%X).\n", lpProtocolInfo));
//EnterCriticalSection(&CatalogLock);
CurrentEntry = CatalogListHead.Flink;
while (CurrentEntry != &CatalogListHead) {
Provider = CONTAINING_RECORD(CurrentEntry,
@ -80,14 +138,50 @@ PCATALOG_ENTRY LocateProvider(
(lpProtocolInfo->iSocketType == Provider->Mapping->Mapping[i].SocketType) &&
((lpProtocolInfo->iProtocol == Provider->Mapping->Mapping[i].Protocol) ||
(lpProtocolInfo->iSocketType == SOCK_RAW))) {
LeaveCriticalSection(&CatalogLock);
//LeaveCriticalSection(&CatalogLock);
WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X).\n", Provider));
return Provider;
}
}
CurrentEntry = CurrentEntry->Flink;
}
LeaveCriticalSection(&CatalogLock);
//LeaveCriticalSection(&CatalogLock);
WS_DbgPrint(MID_TRACE, ("Provider was not found.\n"));
return NULL;
}
PCATALOG_ENTRY LocateProviderById(
DWORD CatalogEntryId)
{
PLIST_ENTRY CurrentEntry;
PCATALOG_ENTRY Provider;
UINT i;
WS_DbgPrint(MAX_TRACE, ("CatalogEntryId (%d).\n", CatalogEntryId));
//EnterCriticalSection(&CatalogLock);
CurrentEntry = CatalogListHead.Flink;
while (CurrentEntry != &CatalogListHead) {
Provider = CONTAINING_RECORD(CurrentEntry,
CATALOG_ENTRY,
ListEntry);
if (Provider->ProtocolInfo.dwCatalogEntryId == CatalogEntryId) {
//LeaveCriticalSection(&CatalogLock);
WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X) Name (%s).\n",
Provider, Provider->LibraryName));
return Provider;
}
CurrentEntry = CurrentEntry->Flink;
}
//LeaveCriticalSection(&CatalogLock);
WS_DbgPrint(MID_TRACE, ("Provider was not found.\n"));
return NULL;
}
@ -97,22 +191,30 @@ INT LoadProvider(
PCATALOG_ENTRY Provider,
LPWSAPROTOCOL_INFOW lpProtocolInfo)
{
INT Status = NO_ERROR;
INT Status;
WS_DbgPrint(MIN_TRACE, ("Loading provider...\n"));
WS_DbgPrint(MAX_TRACE, ("Loading provider at (0x%X) Name (%S).\n",
Provider, Provider->LibraryName));
if (Provider->hModule == (HMODULE)INVALID_HANDLE_VALUE) {
if (!Provider->hModule) {
CP
/* DLL is not loaded so load it now */
Provider->hModule = LoadLibrary(Provider->LibraryName);
if (Provider->hModule != (HMODULE)INVALID_HANDLE_VALUE) {
CP
if (Provider->hModule) {
CP
Provider->WSPStartup = (LPWSPSTARTUP)GetProcAddress(Provider->hModule,
"WSPStartup");
CP
if (Provider->WSPStartup) {
Status = WSPStartup(MAKEWORD(2, 2),
&Provider->WSPData,
lpProtocolInfo,
UpcallTable,
&Provider->ProcTable);
WS_DbgPrint(MAX_TRACE, ("Calling WSPStartup at (0x%X).\n", Provider->WSPStartup));
Status = Provider->WSPStartup(MAKEWORD(2, 2),
&Provider->WSPData,
lpProtocolInfo,
UpcallTable,
&Provider->ProcTable);
CP
} else
Status = ERROR_BAD_PROVIDER;
} else
@ -120,7 +222,7 @@ INT LoadProvider(
} else
Status = NO_ERROR;
WS_DbgPrint(MIN_TRACE, ("Status %d\n", Status));
WS_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status));
return Status;
}
@ -131,15 +233,23 @@ INT UnloadProvider(
{
INT Status = NO_ERROR;
if (Provider->hModule != (HMODULE)INVALID_HANDLE_VALUE) {
WS_DbgPrint(MAX_TRACE, ("Unloading provider at (0x%X)\n", Provider));
if (Provider->hModule) {
WS_DbgPrint(MAX_TRACE, ("Calling WSPCleanup at (0x%X).\n",
Provider->ProcTable.lpWSPCleanup));
Provider->ProcTable.lpWSPCleanup(&Status);
if (!FreeLibrary(Provider->hModule))
if (!FreeLibrary(Provider->hModule)) {
WS_DbgPrint(MIN_TRACE, ("Could not free library.\n"));
Status = GetLastError();
}
Provider->hModule = (HMODULE)INVALID_HANDLE_VALUE;
}
WS_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status));
return Status;
}
@ -148,25 +258,46 @@ VOID CreateCatalog(VOID)
{
PCATALOG_ENTRY Provider;
InitializeCriticalSection(&CatalogLock);
CP
// FIXME: Crash
//InitializeCriticalSection(&CatalogLock);
CP
InitializeListHead(&CatalogListHead);
CP
/* FIXME: Read service provider catalog from registry */
#if 1
Provider = CreateCatalogEntry(L"msafd.dll");
if (!Provider)
if (!Provider) {
WS_DbgPrint(MIN_TRACE, ("Could not create catalog entry.\n"));
return;
}
CP
/* Assume one Service Provider with id 1 */
Provider->ProtocolInfo.dwCatalogEntryId = 1;
CP
Provider->Mapping = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD));
if (!Provider->Mapping)
if (!Provider->Mapping) {
WS_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return;
}
CP
Provider->Mapping->Rows = 1;
Provider->Mapping->Columns = 3;
Provider->Mapping->Mapping[0].AddressFamily = AF_INET;
Provider->Mapping->Mapping[0].SocketType = SOCK_RAW;
Provider->Mapping->Mapping[0].Protocol = 0;
CP
#endif
}
@ -174,20 +305,19 @@ VOID CreateCatalog(VOID)
VOID DestroyCatalog(VOID)
{
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PCATALOG_ENTRY Provider;
CurrentEntry = CatalogListHead.Flink;
while (CurrentEntry != &CatalogListHead) {
NextEntry = CurrentEntry->Flink;
Provider = CONTAINING_RECORD(CurrentEntry,
CATALOG_ENTRY,
ListEntry);
DestroyCatalogEntry(Provider);
CurrentEntry = CurrentEntry->Flink;
CurrentEntry = NextEntry;
}
DeleteCriticalSection(&CatalogLock);
//DeleteCriticalSection(&CatalogLock);
}
/* EOF */

View file

@ -9,12 +9,13 @@
*/
#include <ws2_32.h>
#include <catalog.h>
#include <handle.h>
#include <upcall.h>
#ifdef DBG
/* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = MIN_TRACE;
DWORD DebugTraceLevel = MAX_TRACE;
#endif /* DBG */
@ -59,18 +60,25 @@ WSAStartup(
IN WORD wVersionRequested,
OUT LPWSADATA lpWSAData)
{
WS_DbgPrint(MIN_TRACE, ("WSAStartup of ws2_32.dll\n"));
WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));
lpWSAData->wVersion = wVersionRequested;
lpWSAData->wHighVersion = 2;
CP
lstrcpyA(lpWSAData->szDescription, "WinSock 2.0");
CP
lstrcpyA(lpWSAData->szSystemStatus, "Running");
CP
lpWSAData->iMaxSockets = 0;
lpWSAData->iMaxUdpDg = 0;
lpWSAData->lpVendorInfo = NULL;
CP
WSASETINITIALIZED;
CP
return NO_ERROR;
}
@ -79,13 +87,15 @@ INT
EXPORT
WSACleanup(VOID)
{
WS_DbgPrint(MIN_TRACE, ("WSACleanup of ws2_32.dll\n"));
WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n"));
if (!WSAINITIALIZED) {
CP
WSASetLastError(WSANOTINITIALISED);
return WSANOTINITIALISED;
}
CP
return NO_ERROR;
}
@ -108,18 +118,24 @@ WSASocketA(
UNICODE_STRING StringU;
ANSI_STRING StringA;
WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
af, type, protocol));
if (lpProtocolInfo) {
CP
memcpy(&ProtocolInfoW,
lpProtocolInfo,
sizeof(WSAPROTOCOL_INFOA) -
sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
CP
RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
CP
RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
RtlAnsiStringToUnicodeString(&StringU,
&StringA,
FALSE);
CP
RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
CP
p = &ProtocolInfoW;
CP
} else {
p = NULL;
}
@ -143,7 +159,7 @@ WSASocketW(
IN GROUP g,
IN DWORD dwFlags)
/*
* FUNCTION: Creates a new socket
* FUNCTION: Creates a new socket descriptor
* ARGUMENTS:
* af = Address family
* type = Socket type
@ -152,7 +168,7 @@ WSASocketW(
* g = Reserved
* dwFlags = Socket flags
* RETURNS:
* Created socket, or INVALID_SOCKET if it could not be created
* Created socket descriptor, or INVALID_SOCKET if it could not be created
*/
{
INT Status;
@ -160,6 +176,9 @@ WSASocketW(
PCATALOG_ENTRY Provider;
WSAPROTOCOL_INFOW ProtocolInfo;
WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
af, type, protocol));
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return INVALID_SOCKET;
@ -188,12 +207,12 @@ WSASocketW(
}
Socket = Provider->ProcTable.lpWSPSocket(af,
type,
protocol,
lpProtocolInfo,
g,
dwFlags,
&Status);
type,
protocol,
lpProtocolInfo,
g,
dwFlags,
&Status);
if (Status != NO_ERROR) {
WSASetLastError(Status);
return INVALID_SOCKET;
@ -203,24 +222,146 @@ WSASocketW(
}
INT
EXPORT
closesocket(
IN SOCKET s)
/*
* FUNCTION: Closes a socket descriptor
* ARGUMENTS:
* s = Socket descriptor
* RETURNS:
* 0, or SOCKET_ERROR if an error ocurred
*/
{
PCATALOG_ENTRY Provider;
INT Errno;
INT Code;
WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
CloseProviderHandle((HANDLE)s);
DereferenceProviderByPointer(Provider);
Code = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
if (Code == SOCKET_ERROR)
WSASetLastError(Errno);
return 0;
}
INT
EXPORT
select(
IN INT nfds,
IN OUT LPFD_SET readfds,
IN OUT LPFD_SET writefds,
IN OUT LPFD_SET exceptfds,
IN CONST LPTIMEVAL timeout)
/*
* FUNCTION: Returns status of one or more sockets
* ARGUMENTS:
* nfds = Always ignored
* readfds = Pointer to socket set to be checked for readability (optional)
* writefds = Pointer to socket set to be checked for writability (optional)
* exceptfds = Pointer to socket set to be checked for errors (optional)
* timeout = Pointer to a TIMEVAL structure indicating maximum wait time
* (NULL means wait forever)
* RETURNS:
* Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
*/
{
PCATALOG_ENTRY Provider;
INT Count;
INT Errno;
ULONG i;
WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
readfds, writefds, exceptfds));
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
/* FIXME: Sockets in FD_SETs should be sorted by their provider */
/* FIXME: For now, assume only one service provider */
if ((readfds != NULL) && (readfds->fd_count > 0)) {
if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
} else if ((writefds != NULL) && (writefds->fd_count > 0)) {
if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
} else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
} else {
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
Count = Provider->ProcTable.lpWSPSelect(nfds, readfds, writefds, exceptfds, timeout, &Errno);
DereferenceProviderByPointer(Provider);
WSASetLastError(Errno);
if (Errno != NO_ERROR)
return SOCKET_ERROR;
return Count;
}
BOOL
STDCALL
DllMain(PVOID hInstDll,
DllMain(HANDLE hInstDll,
ULONG dwReason,
PVOID Reserved)
LPVOID lpReserved)
{
WS_DbgPrint(MIN_TRACE, ("DllMain of ws2_32.dll\n"));
WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
CP
#if 0
switch (dwReason) {
case DLL_PROCESS_ATTACH:
GlobalHeap = HeapCreate(0, 0, 0);
if (!GlobalHeap)
return FALSE;
case DLL_PROCESS_ATTACH: {
CP
GlobalHeap = GetProcessHeap();
//GlobalHeap = HeapCreate(0, 0, 0);
if (!GlobalHeap) {
WS_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return FALSE;
}
if (ReadCatalog() != NO_ERROR)
return FALSE;
CP
CreateCatalog();
CP
InitProviderHandleTable();
CP
/* FIXME: Causes trap
UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
@ -235,37 +376,64 @@ DllMain(PVOID hInstDll,
UpcallTable.lpWPUResetEvent = WPUResetEvent;
UpcallTable.lpWPUSetEvent = WPUSetEvent;
UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
UpcallTable.lpWPUCloseThread = WPUCloseThread;
break;
UpcallTable.lpWPUCloseThread = WPUCloseThread;*/
/* Fall through to thread attachment handler */
}
case DLL_THREAD_ATTACH: {
PWINSOCK_THREAD_BLOCK p;
p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
if (p) {
p->LastErrorValue = NO_ERROR;
p->Initialized = FALSE;
NtCurrentTeb()->WinSockData = p;
}
CP
p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
CP
if (!p) {
WS_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return FALSE;
}
CP
p->LastErrorValue = NO_ERROR;
p->Initialized = FALSE;
CP
NtCurrentTeb()->WinSockData = p;
break;
}
case DLL_PROCESS_DETACH: {
CP
HeapFree(GlobalHeap, 0, NtCurrentTeb()->WinSockData);
DestroyCatalog();
CP
FreeProviderHandleTable();
CP
//HeapDestroy(GlobalHeap);
break;
}
case DLL_THREAD_DETACH: {
PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
CP
if (p)
HeapFree(GlobalHeap, 0, p);
break;
}
case DLL_PROCESS_DETACH:
DestroyCatalog();
HeapDestroy(GlobalHeap);
break;
}
#endif
CP
return TRUE;
}

View file

@ -14,9 +14,19 @@ EXPORT
WSACloseEvent(
IN WSAEVENT hEvent)
{
UNIMPLEMENTED
BOOL Success;
return FALSE;
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return FALSE;
}
Success = CloseHandle((HANDLE)hEvent);
if (!Success)
WSASetLastError(WSA_INVALID_HANDLE);
return Success;
}
@ -24,9 +34,19 @@ WSAEVENT
EXPORT
WSACreateEvent(VOID)
{
UNIMPLEMENTED
HANDLE Event;
return (WSAEVENT)0;
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return FALSE;
}
Event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (Event == INVALID_HANDLE_VALUE)
WSASetLastError(WSA_INVALID_HANDLE);
return (WSAEVENT)Event;
}
@ -35,9 +55,19 @@ EXPORT
WSAResetEvent(
IN WSAEVENT hEvent)
{
UNIMPLEMENTED
BOOL Success;
return FALSE;
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return FALSE;
}
Success = ResetEvent((HANDLE)hEvent);
if (!Success)
WSASetLastError(WSA_INVALID_HANDLE);
return Success;
}
@ -46,9 +76,19 @@ EXPORT
WSASetEvent(
IN WSAEVENT hEvent)
{
UNIMPLEMENTED
BOOL Success;
return FALSE;
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return FALSE;
}
Success = SetEvent((HANDLE)hEvent);
if (!Success)
WSASetLastError(WSA_INVALID_HANDLE);
return Success;
}
@ -61,9 +101,28 @@ WSAWaitForMultipleEvents(
IN DWORD dwTimeout,
IN BOOL fAlertable)
{
UNIMPLEMENTED
DWORD Status;
return 0;
if (!WSAINITIALIZED) {
WSASetLastError(WSANOTINITIALISED);
return FALSE;
}
Status = WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable);
if (Status == WAIT_FAILED) {
Status = GetLastError();
if (Status == ERROR_NOT_ENOUGH_MEMORY)
WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
else if (Status == ERROR_INVALID_HANDLE)
WSASetLastError(WSA_INVALID_HANDLE);
else
WSASetLastError(WSA_INVALID_PARAMETER);
return WSA_WAIT_FAILED;
}
return Status;
}
/* EOF */

View file

@ -0,0 +1,281 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: misc/handle.c
* PURPOSE: Provider handle management
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <ws2_32.h>
#include <handle.h>
#include <catalog.h>
PPROVIDER_HANDLE_BLOCK ProviderHandleTable;
CRITICAL_SECTION ProviderHandleTableLock;
PPROVIDER_HANDLE
GetProviderByHandle(
PPROVIDER_HANDLE_BLOCK HandleTable,
HANDLE Handle)
/*
* FUNCTION: Get the data structure for a handle
* ARGUMENTS:
* HandleTable = Pointer to handle table
* Handle = Handle to get data structure for
* RETURNS:
* Pointer to the data structure identified by the handle on success,
* NULL on failure
*/
{
PPROVIDER_HANDLE_BLOCK Current;
PLIST_ENTRY CurrentEntry;
ULONG i;
WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle));
CurrentEntry = HandleTable->Entry.Flink;
while (CurrentEntry != &HandleTable->Entry) {
Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry);
for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) {
if ((Current->Handles[i].Provider != NULL) &&
(Current->Handles[i].Handle == Handle)) {
return &Current->Handles[i];
}
}
CurrentEntry = CurrentEntry->Flink;
}
return NULL;
}
VOID
CloseAllHandles(PPROVIDER_HANDLE_BLOCK HandleTable)
{
PPROVIDER_HANDLE_BLOCK Current;
PLIST_ENTRY CurrentEntry;
PCATALOG_ENTRY Provider;
ULONG i;
WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X).\n", HandleTable));
CurrentEntry = HandleTable->Entry.Flink;
while (CurrentEntry != &HandleTable->Entry) {
Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry);
for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) {
Provider = Current->Handles[i].Provider;
if (Provider != NULL) {
DereferenceProviderByPointer(Provider);
Current->Handles[i].Handle = (HANDLE)0;
Current->Handles[i].Provider = NULL;
break;
}
}
CurrentEntry = CurrentEntry->Flink;
}
}
VOID
DeleteHandleTable(PPROVIDER_HANDLE_BLOCK HandleTable)
{
PPROVIDER_HANDLE_BLOCK Current;
PLIST_ENTRY CurrentEntry;
CloseAllHandles(HandleTable);
CurrentEntry = RemoveHeadList(&HandleTable->Entry);
while (CurrentEntry != &HandleTable->Entry) {
Current = CONTAINING_RECORD(CurrentEntry,
PROVIDER_HANDLE_BLOCK,
Entry);
HeapFree(GlobalHeap, 0, Current);
CurrentEntry = RemoveHeadList(&HandleTable->Entry);
}
}
PCATALOG_ENTRY
DeleteProviderHandle(PPROVIDER_HANDLE_BLOCK HandleTable,
HANDLE Handle)
{
PPROVIDER_HANDLE Entry;
PCATALOG_ENTRY Provider;
WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle));
Entry = GetProviderByHandle(HandleTable, Handle);
if (!Entry) {
return NULL;
}
Provider = Entry->Provider;
if (Provider != NULL) {
Entry->Handle = (HANDLE)0;
Entry->Provider = NULL;
}
return Provider;
}
HANDLE
CreateProviderHandleTable(PPROVIDER_HANDLE_BLOCK HandleTable,
HANDLE Handle,
PCATALOG_ENTRY Provider)
{
PPROVIDER_HANDLE_BLOCK NewBlock;
PLIST_ENTRY CurrentEntry;
ULONG i;
WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X) Provider (0x%X).\n", HandleTable, Handle, Provider));
/* Scan through the currently allocated handle blocks looking for a free slot */
CurrentEntry = HandleTable->Entry.Flink;
while (CurrentEntry != &HandleTable->Entry) {
PPROVIDER_HANDLE_BLOCK Block = CONTAINING_RECORD(
CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry);
for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) {
WS_DbgPrint(MAX_TRACE, ("Considering slot %ld containing 0x%X.\n", i, Block->Handles[i].Provider));
if (!Block->Handles[i].Provider) {
Block->Handles[i].Handle = Handle;
Block->Handles[i].Provider = Provider;
return Handle;
}
}
CurrentEntry = CurrentEntry->Flink;
}
/* Add a new handle block to the end of the list */
NewBlock = (PPROVIDER_HANDLE_BLOCK)HeapAlloc(
GlobalHeap, 0, sizeof(PROVIDER_HANDLE_BLOCK));
if (!NewBlock) {
WS_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return NULL;
}
ZeroMemory(NewBlock, sizeof(PROVIDER_HANDLE_BLOCK));
InsertTailList(&HandleTable->Entry, &NewBlock->Entry);
NewBlock->Handles[0].Handle = Handle;
NewBlock->Handles[0].Provider = Provider;
return Handle;
}
HANDLE
CreateProviderHandle(HANDLE Handle,
PCATALOG_ENTRY Provider)
{
HANDLE h;
//EnterCriticalSection(&ProviderHandleTableLock);
h = CreateProviderHandleTable(ProviderHandleTable, Handle, Provider);
//LeaveCriticalSection(&ProviderHandleTableLock);
if (h != NULL) {
ReferenceProviderByPointer(Provider);
}
return h;
}
BOOL
ReferenceProviderByHandle(HANDLE Handle,
PCATALOG_ENTRY* Provider)
/*
* FUNCTION: Increments the reference count for a provider and returns a pointer to it
* ARGUMENTS:
* Handle = Handle for the provider
* Provider = Address of buffer to place pointer to provider
* RETURNS:
* TRUE if handle was valid, FALSE if not
*/
{
PPROVIDER_HANDLE ProviderHandle;
WS_DbgPrint(MAX_TRACE, ("Handle (0x%X) Provider (0x%X).\n", Handle, Provider));
//EnterCriticalSection(&ProviderHandleTableLock);
ProviderHandle = GetProviderByHandle(ProviderHandleTable, Handle);
//LeaveCriticalSection(&ProviderHandleTableLock);
if (ProviderHandle) {
ReferenceProviderByPointer(ProviderHandle->Provider);
*Provider = ProviderHandle->Provider;
}
return (ProviderHandle != NULL);
}
BOOL
CloseProviderHandle(HANDLE Handle)
{
PCATALOG_ENTRY Provider;
WS_DbgPrint(MAX_TRACE, ("Handle (0x%X).\n", Handle));
//EnterCriticalSection(&ProviderHandleTableLock);
Provider = DeleteProviderHandle(ProviderHandleTable, Handle);
if (!Provider) {
WS_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return FALSE;
}
//LeaveCriticalSection(&ProviderHandleTableLock);
DereferenceProviderByPointer(Provider);
return TRUE;
}
BOOL
InitProviderHandleTable(VOID)
{
ProviderHandleTable = (PPROVIDER_HANDLE_BLOCK)
HeapAlloc(GlobalHeap, 0, sizeof(PROVIDER_HANDLE_BLOCK));
if (!ProviderHandleTable) {
WS_DbgPrint(MIN_TRACE, ("Insufficient memory.\n"));
return FALSE;
}
ZeroMemory(ProviderHandleTable, sizeof(PROVIDER_HANDLE_BLOCK));
InitializeListHead(&ProviderHandleTable->Entry);
//InitializeCriticalSection(&ProviderHandleTableLock);
return TRUE;
}
VOID
FreeProviderHandleTable(VOID)
{
DeleteHandleTable(ProviderHandleTable);
//DeleteCriticalSection(&ProviderHandleTableLock);
}
/* EOF */

View file

@ -402,9 +402,19 @@ EXPORT
inet_ntoa(
IN IN_ADDR in)
{
UNIMPLEMENTED
CHAR b[10];
PCHAR p;
return (CHAR FAR*)NULL;
p = ((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Intoa;
_itoa(in.S_un.S_addr >> 24, b, 10);
strcpy(p, b);
_itoa(in.S_un.S_addr >> 16, b, 10);
strcat(p, b);
_itoa(in.S_un.S_addr >> 8, b, 10);
strcat(p, b);
_itoa(in.S_un.S_addr & 0xFF, b, 10);
strcat(p, b);
return (CHAR FAR*)p;
}

View file

@ -0,0 +1,193 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: misc/sndrcv.c
* PURPOSE: Send/receive functions
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <ws2_32.h>
#include <catalog.h>
INT
EXPORT
recv(
IN SOCKET s,
OUT CHAR FAR* buf,
IN INT len,
IN INT flags)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
recvfrom(
IN SOCKET s,
OUT CHAR FAR* buf,
IN INT len,
IN INT flags,
OUT LPSOCKADDR from,
IN OUT INT FAR* fromlen)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
send(
IN SOCKET s,
IN CONST CHAR FAR* buf,
IN INT len,
IN INT flags)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
sendto(
IN SOCKET s,
IN CONST CHAR FAR* buf,
IN INT len,
IN INT flags,
IN CONST LPSOCKADDR to,
IN INT tolen)
{
DWORD BytesSent;
WSABUF WSABuf;
WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n",
s, buf, len, flags));
WSABuf.len = len;
WSABuf.buf = (CHAR FAR*)buf;
return WSASendTo(s, &WSABuf, 1, &BytesSent, flags, to, tolen, NULL, NULL);
}
INT
EXPORT
WSARecv(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSARecvDisconnect(
IN SOCKET s,
OUT LPWSABUF lpInboundDisconnectData)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSARecvFrom(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
OUT LPSOCKADDR lpFrom,
IN OUT LPINT lpFromlen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSASend(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSASendDisconnect(
IN SOCKET s,
IN LPWSABUF lpOutboundDisconnectData)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSASendTo(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN CONST LPSOCKADDR lpTo,
IN INT iToLen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
PCATALOG_ENTRY Provider;
INT Errno;
INT Code;
WS_DbgPrint(MAX_TRACE, ("Called.\n"));
if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
Code = Provider->ProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount,
lpNumberOfBytesSent, dwFlags, lpTo, iToLen, lpOverlapped,
lpCompletionRoutine, NULL /* lpThreadId */, &Errno);
DereferenceProviderByPointer(Provider);
if (Code == SOCKET_ERROR)
WSASetLastError(Errno);
return Code;
}
/* EOF */

View file

@ -33,16 +33,6 @@ bind(
return 0;
}
INT
EXPORT
closesocket(
IN SOCKET s)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
connect(
@ -156,76 +146,6 @@ ntohs(
return 0;
}
INT
EXPORT
recv(
IN SOCKET s,
OUT CHAR FAR* buf,
IN INT len,
IN INT flags)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
recvfrom(
IN SOCKET s,
OUT CHAR FAR* buf,
IN INT len,
IN INT flags,
OUT LPSOCKADDR from,
IN OUT INT FAR* fromlen)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
select(
IN INT nfds,
IN OUT LPFD_SET readfds,
IN OUT LPFD_SET writefds,
IN OUT LPFD_SET exceptfds,
IN CONST LPTIMEVAL timeout)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
send(
IN SOCKET s,
IN CONST CHAR FAR* buf,
IN INT len,
IN INT flags)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
sendto(
IN SOCKET s,
IN CONST CHAR FAR* buf,
IN INT len,
IN INT flags,
IN CONST LPSOCKADDR to,
IN INT tolen)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
setsockopt(
@ -505,96 +425,6 @@ WSANtohs(
return 0;
}
INT
EXPORT
WSARecv(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSARecvDisconnect(
IN SOCKET s,
OUT LPWSABUF lpInboundDisconnectData)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSARecvFrom(
IN SOCKET s,
IN OUT LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesRecvd,
IN OUT LPDWORD lpFlags,
OUT LPSOCKADDR lpFrom,
IN OUT LPINT lpFromlen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSASend(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSASendDisconnect(
IN SOCKET s,
IN LPWSABUF lpOutboundDisconnectData)
{
UNIMPLEMENTED
return 0;
}
INT
EXPORT
WSASendTo(
IN SOCKET s,
IN LPWSABUF lpBuffers,
IN DWORD dwBufferCount,
OUT LPDWORD lpNumberOfBytesSent,
IN DWORD dwFlags,
IN CONST LPSOCKADDR lpTo,
IN INT iToLen,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
UNIMPLEMENTED
return 0;
}
FARPROC
EXPORT
WSASetBlockingHook(

View file

@ -8,6 +8,7 @@
* CSH 01/09-2000 Created
*/
#include <ws2_32.h>
#include <catalog.h>
BOOL
WSPAPI
@ -78,7 +79,6 @@ WPUFDIsSet(
UNIMPLEMENTED
return (SOCKET)0;
}
@ -103,9 +103,25 @@ WPUModifyIFSHandle(
IN SOCKET ProposedHandle,
OUT LPINT lpErrno)
{
UNIMPLEMENTED
PCATALOG_ENTRY Provider;
SOCKET Socket;
return (SOCKET)0;
WS_DbgPrint(MAX_TRACE, ("dwCatalogEntryId (%d) ProposedHandle (0x%X).\n",
dwCatalogEntryId, ProposedHandle));
Provider = LocateProviderById(dwCatalogEntryId);
if (!Provider) {
WS_DbgPrint(MIN_TRACE, ("Provider with catalog entry id (%d) was not found.\n",
dwCatalogEntryId));
*lpErrno = WSAEINVAL;
return INVALID_SOCKET;
}
Socket = (SOCKET)CreateProviderHandle(ProposedHandle, Provider);
*lpErrno = NO_ERROR;
return Socket;
}