diff --git a/reactos/Makefile b/reactos/Makefile index e841585dfc7..8aad6102a42 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -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) diff --git a/reactos/drivers/net/afd/afd.def b/reactos/drivers/net/afd/afd.def new file mode 100644 index 00000000000..c83c3a9e031 --- /dev/null +++ b/reactos/drivers/net/afd/afd.def @@ -0,0 +1,7 @@ +; Ancillary Function Driver - ReactOS Operating System + +LIBRARY AFDTEST.SYS + +EXPORTS + +; EOF diff --git a/reactos/drivers/net/afd/afd.rc b/reactos/drivers/net/afd/afd.rc new file mode 100644 index 00000000000..65281ec0c6c --- /dev/null +++ b/reactos/drivers/net/afd/afd.rc @@ -0,0 +1,38 @@ +#include +#include + +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 + diff --git a/reactos/drivers/net/afd/afd/afd.c b/reactos/drivers/net/afd/afd/afd.c new file mode 100644 index 00000000000..dd242cb84c1 --- /dev/null +++ b/reactos/drivers/net/afd/afd/afd.c @@ -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 + +#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 */ diff --git a/reactos/drivers/net/afd/afd/dispatch.c b/reactos/drivers/net/afd/afd/dispatch.c new file mode 100644 index 00000000000..662993cf44c --- /dev/null +++ b/reactos/drivers/net/afd/afd/dispatch.c @@ -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 + +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 */ diff --git a/reactos/drivers/net/afd/afd/event.c b/reactos/drivers/net/afd/afd/event.c new file mode 100644 index 00000000000..fe0ee8c5e2f --- /dev/null +++ b/reactos/drivers/net/afd/afd/event.c @@ -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 + +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 */ diff --git a/reactos/drivers/net/afd/afd/opnclose.c b/reactos/drivers/net/afd/afd/opnclose.c new file mode 100644 index 00000000000..c882531e194 --- /dev/null +++ b/reactos/drivers/net/afd/afd/opnclose.c @@ -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 + +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 */ diff --git a/reactos/drivers/net/afd/afd/rdwr.c b/reactos/drivers/net/afd/afd/rdwr.c new file mode 100644 index 00000000000..c014a627c0a --- /dev/null +++ b/reactos/drivers/net/afd/afd/rdwr.c @@ -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 + +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 */ diff --git a/reactos/drivers/net/afd/afd/tdi.c b/reactos/drivers/net/afd/afd/tdi.c new file mode 100644 index 00000000000..d032e8504be --- /dev/null +++ b/reactos/drivers/net/afd/afd/tdi.c @@ -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 + +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 */ diff --git a/reactos/drivers/net/afd/include/afd.h b/reactos/drivers/net/afd/include/afd.h new file mode 100644 index 00000000000..a4dd8513c25 --- /dev/null +++ b/reactos/drivers/net/afd/include/afd.h @@ -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 +#include +#include +#include +#include +#include + +/* 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 */ diff --git a/reactos/drivers/net/afd/include/debug.h b/reactos/drivers/net/afd/include/debug.h new file mode 100644 index 00000000000..061c157c12a --- /dev/null +++ b/reactos/drivers/net/afd/include/debug.h @@ -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 */ diff --git a/reactos/drivers/net/afd/makefile b/reactos/drivers/net/afd/makefile new file mode 100644 index 00000000000..04461e09334 --- /dev/null +++ b/reactos/drivers/net/afd/makefile @@ -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 diff --git a/reactos/drivers/net/wshtcpip/debug.h b/reactos/drivers/net/wshtcpip/debug.h index aa0e09ca497..eef00c33880 100644 --- a/reactos/drivers/net/wshtcpip/debug.h +++ b/reactos/drivers/net/wshtcpip/debug.h @@ -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 */ diff --git a/reactos/drivers/net/wshtcpip/makefile b/reactos/drivers/net/wshtcpip/makefile index 0cdbdcbd7f8..6a5795c456b 100644 --- a/reactos/drivers/net/wshtcpip/makefile +++ b/reactos/drivers/net/wshtcpip/makefile @@ -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 diff --git a/reactos/drivers/net/wshtcpip/wshtcpip.c b/reactos/drivers/net/wshtcpip/wshtcpip.c index 25032a9e80a..06cf0828313 100644 --- a/reactos/drivers/net/wshtcpip/wshtcpip.c +++ b/reactos/drivers/net/wshtcpip/wshtcpip.c @@ -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); diff --git a/reactos/include/afd/shared.h b/reactos/include/afd/shared.h new file mode 100644 index 00000000000..ebef149cc03 --- /dev/null +++ b/reactos/include/afd/shared.h @@ -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 */ diff --git a/reactos/include/net/tdi.h b/reactos/include/net/tdi.h index 4e8a79e2617..cd9d37281b1 100644 --- a/reactos/include/net/tdi.h +++ b/reactos/include/net/tdi.h @@ -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 diff --git a/reactos/lib/msafd/.cvsignore b/reactos/lib/msafd/.cvsignore new file mode 100644 index 00000000000..2ec245bbd75 --- /dev/null +++ b/reactos/lib/msafd/.cvsignore @@ -0,0 +1,6 @@ +msafd.a +msafd.dll +msafd.coff +base.tmp +junk.tmp +temp.exp diff --git a/reactos/lib/msafd/include/debug.h b/reactos/lib/msafd/include/debug.h new file mode 100644 index 00000000000..2c1cd9a4fe2 --- /dev/null +++ b/reactos/lib/msafd/include/debug.h @@ -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 */ diff --git a/reactos/lib/msafd/include/helpers.h b/reactos/lib/msafd/include/helpers.h new file mode 100644 index 00000000000..a4647ec5fa2 --- /dev/null +++ b/reactos/lib/msafd/include/helpers.h @@ -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 + +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 */ diff --git a/reactos/lib/msafd/include/msafd.h b/reactos/lib/msafd/include/msafd.h new file mode 100644 index 00000000000..46b560d6ad7 --- /dev/null +++ b/reactos/lib/msafd/include/msafd.h @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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 */ diff --git a/reactos/lib/msafd/makefile b/reactos/lib/msafd/makefile new file mode 100644 index 00000000000..f843c4ab812 --- /dev/null +++ b/reactos/lib/msafd/makefile @@ -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 + diff --git a/reactos/lib/msafd/misc/dllmain.c b/reactos/lib/msafd/misc/dllmain.c new file mode 100644 index 00000000000..bd8bf6d769e --- /dev/null +++ b/reactos/lib/msafd/misc/dllmain.c @@ -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 +#include + +#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 */ diff --git a/reactos/lib/msafd/misc/helpers.c b/reactos/lib/msafd/misc/helpers.c new file mode 100644 index 00000000000..3ef0210b5d5 --- /dev/null +++ b/reactos/lib/msafd/misc/helpers.c @@ -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 +#include + +//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 */ diff --git a/reactos/lib/msafd/misc/sndrcv.c b/reactos/lib/msafd/misc/sndrcv.c new file mode 100644 index 00000000000..e0b2631ad44 --- /dev/null +++ b/reactos/lib/msafd/misc/sndrcv.c @@ -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 + +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 */ diff --git a/reactos/lib/msafd/misc/stubs.c b/reactos/lib/msafd/misc/stubs.c new file mode 100644 index 00000000000..23f231e1a9b --- /dev/null +++ b/reactos/lib/msafd/misc/stubs.c @@ -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 + + +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 */ diff --git a/reactos/lib/msafd/msafd.def b/reactos/lib/msafd/msafd.def new file mode 100644 index 00000000000..54062c4f2ad --- /dev/null +++ b/reactos/lib/msafd/msafd.def @@ -0,0 +1,10 @@ +; MSAFD.DLL - Ancillary Function Driver DLL + +LIBRARY msafd.dll + +EXPORTS +WSPGetSockOpt@24 +WSPSetSockOpt@24 +WSPStartup@76 + +; EOF diff --git a/reactos/lib/msafd/msafd.edf b/reactos/lib/msafd/msafd.edf new file mode 100644 index 00000000000..731b6f6ec16 --- /dev/null +++ b/reactos/lib/msafd/msafd.edf @@ -0,0 +1,10 @@ +; MSAFD.DLL - Ancillary Function Driver DLL + +LIBRARY msafd.dll + +EXPORTS +WSPGetSockOpt=WSPGetSockOpt@24 +WSPSetSockOpt=WSPSetSockOpt@24 +WSPStartup=WSPStartup@76 + +; EOF diff --git a/reactos/lib/msafd/msafd.rc b/reactos/lib/msafd/msafd.rc new file mode 100644 index 00000000000..dc3f8909a6e --- /dev/null +++ b/reactos/lib/msafd/msafd.rc @@ -0,0 +1,39 @@ +#include +#include + +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 + + diff --git a/reactos/lib/ws2_32/include/catalog.h b/reactos/lib/ws2_32/include/catalog.h index cada7ba76ff..6969c168dd0 100644 --- a/reactos/lib/ws2_32/include/catalog.h +++ b/reactos/lib/ws2_32/include/catalog.h @@ -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); diff --git a/reactos/lib/ws2_32/include/debug.h b/reactos/lib/ws2_32/include/debug.h index cb41161ff61..4e122013181 100644 --- a/reactos/lib/ws2_32/include/debug.h +++ b/reactos/lib/ws2_32/include/debug.h @@ -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 */ diff --git a/reactos/lib/ws2_32/include/handle.h b/reactos/lib/ws2_32/include/handle.h new file mode 100644 index 00000000000..97928f6801e --- /dev/null +++ b/reactos/lib/ws2_32/include/handle.h @@ -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 +#include + +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 */ diff --git a/reactos/lib/ws2_32/include/ws2_32.h b/reactos/lib/ws2_32/include/ws2_32.h index 91323ebd21a..dd7dbb31e0b 100644 --- a/reactos/lib/ws2_32/include/ws2_32.h +++ b/reactos/lib/ws2_32/include/ws2_32.h @@ -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; diff --git a/reactos/lib/ws2_32/makefile b/reactos/lib/ws2_32/makefile index 7b085c678bd..0d2b2cdc933 100644 --- a/reactos/lib/ws2_32/makefile +++ b/reactos/lib/ws2_32/makefile @@ -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 diff --git a/reactos/lib/ws2_32/misc/catalog.c b/reactos/lib/ws2_32/misc/catalog.c index 16e9b645210..21d0670f7f3 100644 --- a/reactos/lib/ws2_32/misc/catalog.c +++ b/reactos/lib/ws2_32/misc/catalog.c @@ -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 */ diff --git a/reactos/lib/ws2_32/misc/dllmain.c b/reactos/lib/ws2_32/misc/dllmain.c index 4f05cb9dd4d..7e5090efc26 100644 --- a/reactos/lib/ws2_32/misc/dllmain.c +++ b/reactos/lib/ws2_32/misc/dllmain.c @@ -9,12 +9,13 @@ */ #include #include +#include #include #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; } diff --git a/reactos/lib/ws2_32/misc/event.c b/reactos/lib/ws2_32/misc/event.c index 77d0de8eb3b..5b371ff26d5 100644 --- a/reactos/lib/ws2_32/misc/event.c +++ b/reactos/lib/ws2_32/misc/event.c @@ -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 */ diff --git a/reactos/lib/ws2_32/misc/handle.c b/reactos/lib/ws2_32/misc/handle.c new file mode 100644 index 00000000000..0686acf078f --- /dev/null +++ b/reactos/lib/ws2_32/misc/handle.c @@ -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 +#include +#include + +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 */ diff --git a/reactos/lib/ws2_32/misc/ns.c b/reactos/lib/ws2_32/misc/ns.c index 8a6d7bb70e6..83a9d7d2ebc 100644 --- a/reactos/lib/ws2_32/misc/ns.c +++ b/reactos/lib/ws2_32/misc/ns.c @@ -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; } diff --git a/reactos/lib/ws2_32/misc/sndrcv.c b/reactos/lib/ws2_32/misc/sndrcv.c new file mode 100644 index 00000000000..d7fc982d08a --- /dev/null +++ b/reactos/lib/ws2_32/misc/sndrcv.c @@ -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 +#include + +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 */ diff --git a/reactos/lib/ws2_32/misc/stubs.c b/reactos/lib/ws2_32/misc/stubs.c index 172e64dfbfc..6883d7e3b27 100644 --- a/reactos/lib/ws2_32/misc/stubs.c +++ b/reactos/lib/ws2_32/misc/stubs.c @@ -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( diff --git a/reactos/lib/ws2_32/misc/upcall.c b/reactos/lib/ws2_32/misc/upcall.c index afd800a3914..c4d9e0f8431 100644 --- a/reactos/lib/ws2_32/misc/upcall.c +++ b/reactos/lib/ws2_32/misc/upcall.c @@ -8,6 +8,7 @@ * CSH 01/09-2000 Created */ #include +#include 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; }