[TDILIB, IPHLPAPI, WSHTCPIP]

- Move the TDI stuff from iphlpapi to a shared library called tdilib
[IP]
 - Implement tcpip side of IP_HDRINCL
[PSDK, WSHTCPIP, WSHIRDA]
 - Fix definition of WSHGetSocketInformation
[PSDK]
 - Add AO_OPTION_* defines
[WSHTCPIP]
 - Request notifications for bind also
 - Implement WSHSetSocketInformation
[MSAFD]
 - Implement event notifications (bonus: fixes a memory leak on socket closure due to unfreed helper context)
 - Store TdiConnectionHandle the same way we store TdiAddressHandle
 - Half-plement WSPSetSockOpt
 - Fix WSPGetSockOpt
[TCPIP]
 - Handle AO_OPTION_TTL, AO_OPTION_IP_DONTFRAGMENT (not working yet), AO_OPTION_BROADCAST (not working yet), and AO_OPTION_IP_HDRINCL
 - Add new members of ADDRESS_FILE for the preceding AO options
[AFD]
 - Return the connection handle in the Information of the IOSB (same as we do with the address file handle)
[GENERAL]
 - Tracert works now

svn path=/branches/aicom-network-branch/; revision=45093
This commit is contained in:
Cameron Gutman 2010-01-16 00:05:15 +00:00
parent 2522eb7b9b
commit 3f6a56fa36
21 changed files with 670 additions and 251 deletions

View file

@ -45,9 +45,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
/* Globals */
const PWCHAR TcpFileName = L"\\Device\\Tcp";
/* Functions */
/* I'm a bit skittish about maintaining this info in memory, as I'd rather
@ -64,171 +61,6 @@ void interfaceMapFree(void)
/* Ditto. */
}
NTSTATUS openTcpFile(PHANDLE tcpFile) {
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
TRACE("called.\n");
/* Shamelessly ripped from CreateFileW */
RtlInitUnicodeString( &fileName, TcpFileName );
InitializeObjectAttributes( &objectAttributes,
&fileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = ZwCreateFile( tcpFile,
SYNCHRONIZE | GENERIC_EXECUTE |
GENERIC_READ | GENERIC_WRITE,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
0,
0 );
/* String does not need to be freed: it points to the constant
* string we provided */
if (!NT_SUCCESS(status)) {
ERR("openTcpFile for <%wZ> failed: 0x%lx\n", &fileName, status);
*tcpFile = INVALID_HANDLE_VALUE;
}
return status;
}
void closeTcpFile( HANDLE h ) {
TRACE("called.\n");
ASSERT(h != INVALID_HANDLE_VALUE);
ZwClose( h );
}
/* A generic thing-getting function which interacts in the right way with
* TDI. This may seem oblique, but I'm using it to reduce code and hopefully
* make this thing easier to debug.
*
* The things returned can be any of:
* TDIEntityID
* TDIObjectID
* IFEntry
* IPSNMPInfo
* IPAddrEntry
* IPInterfaceInfo
*/
NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
DWORD toiClass,
DWORD toiType,
DWORD toiId,
DWORD teiEntity,
DWORD teiInstance,
DWORD fixedPart,
DWORD entrySize,
PVOID *tdiEntitySet,
PDWORD numEntries ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
PVOID entitySet = 0;
NTSTATUS status = STATUS_SUCCESS;
DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES,
arraySize = entrySize * MAX_TDI_ENTITIES;
TRACE("TdiGetSetOfThings(tcpFile %x,toiClass %x,toiType %x,toiId %x,"
"teiEntity %x,fixedPart %d,entrySize %d)\n",
(int)tcpFile,
(int)toiClass,
(int)toiType,
(int)toiId,
(int)teiEntity,
(int)fixedPart,
(int)entrySize );
req.ID.toi_class = toiClass;
req.ID.toi_type = toiType;
req.ID.toi_id = toiId;
req.ID.toi_entity.tei_entity = teiEntity;
req.ID.toi_entity.tei_instance = teiInstance;
/* There's a subtle problem here...
* If an interface is added at this exact instant, (as if by a PCMCIA
* card insertion), the array will still not have enough entries after
* have allocated it after the first DeviceIoControl call.
*
* We'll get around this by repeating until the number of interfaces
* stabilizes.
*/
do {
assert( !entitySet ); /* We must not have an entity set allocated */
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
0,
0,
&allocationSizeForEntityArray,
NULL );
if(!NT_SUCCESS(status))
{
ERR("IOCTL Failed\n");
return STATUS_UNSUCCESSFUL;
}
arraySize = allocationSizeForEntityArray;
entitySet = HeapAlloc( GetProcessHeap(), 0, arraySize );
if( !entitySet ) {
status = STATUS_INSUFFICIENT_RESOURCES;
WARN("TdiGetSetOfThings() => %08x\n", (int)status);
return status;
}
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
entitySet,
arraySize,
&allocationSizeForEntityArray,
NULL );
/* This is why we have the loop -- we might have added an adapter */
if( arraySize == allocationSizeForEntityArray )
break;
HeapFree( GetProcessHeap(), 0, entitySet );
entitySet = 0;
if(!status)
{
WARN("IOCTL Failed\n");
return STATUS_UNSUCCESSFUL;
}
WARN("TdiGetSetOfThings(): Array changed size: %d -> %d.\n",
arraySize, allocationSizeForEntityArray );
} while( TRUE ); /* We break if the array we received was the size we
* expected. Therefore, we got here because it wasn't */
*numEntries = (arraySize - fixedPart) / entrySize;
*tdiEntitySet = entitySet;
WARN("TdiGetSetOfThings() => Success: %d things @ %08x\n",
(int)*numEntries, (int)entitySet);
return STATUS_SUCCESS;
}
VOID tdiFreeThingSet( PVOID things ) {
HeapFree( GetProcessHeap(), 0, things );
}
NTSTATUS tdiGetMibForIfEntity
( HANDLE tcpFile, TDIEntityID *ent, IFEntrySafelySized *entry ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
@ -283,33 +115,6 @@ NTSTATUS tdiGetMibForIfEntity
return STATUS_SUCCESS;
}
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile,
TDIEntityID **entitySet,
PDWORD numEntities ) {
NTSTATUS status = tdiGetSetOfThings( tcpFile,
INFO_CLASS_GENERIC,
INFO_TYPE_PROVIDER,
ENTITY_LIST_ID,
GENERIC_ENTITY,
0,
0,
sizeof(TDIEntityID),
(PVOID *)entitySet,
numEntities );
if( NT_SUCCESS(status) ) {
int i;
for( i = 0; i < *numEntities; i++ ) {
TRACE("%-4d: %04x:%08x\n",
i,
(*entitySet)[i].tei_entity,
(*entitySet)[i].tei_instance );
}
}
return status;
}
BOOL isInterface( TDIEntityID *if_maybe ) {
return
if_maybe->tei_entity == IF_ENTITY;

View file

@ -3,12 +3,14 @@
<include base="iphlpapi">.</include>
<include base="ReactOS">include/reactos/wine</include>
<include base="dhcp">include</include>
<include base="tdilib">.</include>
<library>wine</library>
<library>ntdll</library>
<library>kernel32</library>
<library>advapi32</library>
<library>ws2_32</library>
<library>dhcpcsvc</library>
<library>tdilib</library>
<file>dhcp_reactos.c</file>
<file>ifenum_reactos.c</file>
<file>ipstats_reactos.c</file>

View file

@ -37,6 +37,8 @@
#include "ddk/tdiinfo.h"
#include "tcpioctl.h"
#include "tdilib.h"
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
@ -120,20 +122,9 @@ typedef enum _IPHLPAddrType {
} IPHLPAddrType;
/** Prototypes **/
NTSTATUS openTcpFile(PHANDLE tcpFile);
VOID closeTcpFile(HANDLE tcpFile);
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile, TDIEntityID **entitySet,
PDWORD numEntities );
NTSTATUS tdiGetSetOfThings( HANDLE tcpFile, DWORD toiClass, DWORD toiType,
DWORD toiId, DWORD teiEntity, DWORD teiInstance,
DWORD fixedPart,
DWORD entrySize, PVOID *tdiEntitySet,
PDWORD numEntries );
VOID tdiFreeThingSet( PVOID things );
NTSTATUS getNthIpEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent );
NTSTATUS tdiGetIpAddrsForIpEntity( HANDLE tcpFile, TDIEntityID *ent,
IPAddrEntry **addrs, PDWORD numAddrs );
int GetLongestChildKeyName( HANDLE RegHandle );
LONG OpenChildKeyRead( HANDLE RegHandle,
PWCHAR ChildKeyName,

View file

@ -426,6 +426,22 @@ WSPCloseSocket(IN SOCKET Handle,
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
if (Socket->HelperEvents & WSH_NOTIFY_CLOSE)
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
WSH_NOTIFY_CLOSE);
if (Status)
{
if (lpErrno) *lpErrno = Status;
NtClose(SockEvent);
return SOCKET_ERROR;
}
}
/* If a Close is already in Process, give up */
if (Socket->SharedData.State == SocketClosed)
{
@ -517,12 +533,11 @@ WSPCloseSocket(IN SOCKET Handle,
if (Status == STATUS_PENDING)
{
WaitForSingleObject(SockEvent, INFINITE);
Status = IoStatusBlock.Status;
}
}
}
/* FIXME: We should notify the Helper DLL of WSH_NOTIFY_CLOSE */
/* Cleanup Time! */
Socket->HelperContext = NULL;
Socket->SharedData.AsyncDisabledEvents = -1;
@ -635,6 +650,21 @@ WSPBind(SOCKET Handle,
NtClose( SockEvent );
if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_BIND))
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
WSH_NOTIFY_BIND);
if (Status)
{
if (lpErrno) *lpErrno = Status;
return SOCKET_ERROR;
}
}
return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
}
@ -694,6 +724,21 @@ WSPListen(SOCKET Handle,
NtClose( SockEvent );
if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_LISTEN))
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
WSH_NOTIFY_LISTEN);
if (Status)
{
if (lpErrno) *lpErrno = Status;
return SOCKET_ERROR;
}
}
return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
}
@ -1277,6 +1322,21 @@ WSPAccept(SOCKET Handle,
AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket));
if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
WSH_NOTIFY_ACCEPT);
if (Status)
{
if (lpErrno) *lpErrno = Status;
return INVALID_SOCKET;
}
}
*lpErrno = 0;
/* Return Socket */
@ -1433,6 +1493,8 @@ WSPConnect(SOCKET Handle,
Status = IOSB.Status;
}
Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
/* Get any pending connect data */
if (lpCalleeData != NULL)
{
@ -1464,6 +1526,35 @@ WSPConnect(SOCKET Handle,
NtClose( SockEvent );
if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT))
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
WSH_NOTIFY_CONNECT);
if (Status)
{
if (lpErrno) *lpErrno = Status;
return SOCKET_ERROR;
}
}
else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
{
Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
Socket->Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
WSH_NOTIFY_CONNECT_ERROR);
if (Status)
{
if (lpErrno) *lpErrno = Status;
return SOCKET_ERROR;
}
}
return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
}
int
@ -1850,11 +1941,52 @@ WSPGetSockOpt(IN SOCKET Handle,
case IPPROTO_TCP: /* FIXME */
default:
*lpErrno = WSAEINVAL;
return SOCKET_ERROR;
*lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
Handle,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
Level,
OptionName,
OptionValue,
(LPINT)OptionLength);
return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
}
}
INT
WSPAPI
WSPSetSockOpt(
IN SOCKET s,
IN INT level,
IN INT optname,
IN CONST CHAR FAR* optval,
IN INT optlen,
OUT LPINT lpErrno)
{
PSOCKET_INFORMATION Socket;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(s);
if (Socket == NULL)
{
*lpErrno = WSAENOTSOCK;
return SOCKET_ERROR;
}
/* FIXME: We should handle some cases here */
*lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
s,
Socket->TdiAddressHandle,
Socket->TdiConnectionHandle,
level,
optname,
(PCHAR)optval,
optlen);
return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
}
/*
* FUNCTION: Initialize service provider for a client

View file

@ -100,22 +100,6 @@ WSPJoinLeaf(
return (SOCKET)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
WSPStringToAddress(

View file

@ -91,7 +91,7 @@ WSHGetSocketInformation(
IN INT Level,
IN INT OptionName,
OUT PCHAR OptionValue,
OUT INT OptionLength)
OUT LPINT OptionLength)
{
UNIMPLEMENTED

View file

@ -156,9 +156,39 @@ WSHGetSockaddrType(
return NO_ERROR;
}
UINT
GetAddressOption(INT Level, INT OptionName)
{
switch (Level)
{
case IPPROTO_IP:
switch (OptionName)
{
case IP_TTL:
return AO_OPTION_TTL;
case IP_DONTFRAGMENT:
return AO_OPTION_IP_DONTFRAGMENT;
#if 0
case IP_RECEIVE_BROADCAST:
return AO_OPTION_BROADCAST;
#endif
case IP_HDRINCL:
return AO_OPTION_IP_HDRINCL;
default:
DPRINT1("Unknown option name for IPPROTO_IP: %d\n", OptionName);
return 0;
}
break;
default:
DPRINT1("Unknown level: %d\n", Level);
return 0;
}
}
INT
EXPORT
@ -170,7 +200,7 @@ WSHGetSocketInformation(
IN INT Level,
IN INT OptionName,
OUT PCHAR OptionValue,
OUT INT OptionLength)
OUT LPINT OptionLength)
{
UNIMPLEMENTED
@ -309,6 +339,37 @@ WSHJoinLeaf(
return NO_ERROR;
}
INT
SendRequest(
IN PVOID Request,
IN DWORD RequestSize,
IN DWORD IOCTL)
{
BOOLEAN Status;
HANDLE TcpCC;
DWORD BytesReturned;
if (openTcpFile(&TcpCC) != STATUS_SUCCESS)
return WSAEINVAL;
Status = DeviceIoControl(TcpCC,
IOCTL,
Request,
RequestSize,
NULL,
0,
&BytesReturned,
NULL);
closeTcpFile(TcpCC);
DPRINT("DeviceIoControl: %d\n", ((Status == TRUE) ? 0 : GetLastError()));
if (!Status)
return WSAEINVAL;
return NO_ERROR;
}
INT
EXPORT
@ -319,15 +380,86 @@ WSHNotify(
IN HANDLE TdiConnectionObjectHandle,
IN DWORD NotifyEvent)
{
PSOCKET_CONTEXT Context = HelperDllSocketContext;
NTSTATUS Status;
HANDLE TcpCC;
TDIEntityID *EntityIDs;
DWORD EntityCount, i;
PQUEUED_REQUEST QueuedRequest, NextQueuedRequest;
switch (NotifyEvent)
{
case WSH_NOTIFY_CLOSE:
HeapFree(GetProcessHeap(), 0, HelperDllSocketContext);
break;
DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
QueuedRequest = Context->RequestQueue;
while (QueuedRequest)
{
NextQueuedRequest = QueuedRequest->Next;
HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
HeapFree(GetProcessHeap(), 0, QueuedRequest);
QueuedRequest = NextQueuedRequest;
}
HeapFree(GetProcessHeap(), 0, HelperDllSocketContext);
break;
case WSH_NOTIFY_BIND:
DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
Status = openTcpFile(&TcpCC);
if (Status != STATUS_SUCCESS)
return WSAEINVAL;
Status = tdiGetEntityIDSet(TcpCC,
&EntityIDs,
&EntityCount);
closeTcpFile(TcpCC);
if (Status != STATUS_SUCCESS)
return WSAEINVAL;
for (i = 0; i < EntityCount; i++)
{
if (EntityIDs[i].tei_entity == CO_TL_ENTITY ||
EntityIDs[i].tei_entity == CL_TL_ENTITY ||
EntityIDs[i].tei_entity == ER_ENTITY)
{
Context->AddrFileInstance = EntityIDs[i].tei_instance;
Context->AddrFileEntityType = EntityIDs[i].tei_entity;
}
}
DPRINT("Instance: %x Type: %x\n", Context->AddrFileInstance, Context->AddrFileEntityType);
tdiFreeThingSet(EntityIDs);
Context->SocketState = SocketStateBound;
QueuedRequest = Context->RequestQueue;
while (QueuedRequest)
{
QueuedRequest->Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
QueuedRequest->Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
SendRequest(QueuedRequest->Info,
sizeof(*QueuedRequest->Info) + QueuedRequest->Info->BufferSize,
IOCTL_TCP_SET_INFORMATION_EX);
NextQueuedRequest = QueuedRequest->Next;
HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
HeapFree(GetProcessHeap(), 0, QueuedRequest);
QueuedRequest = NextQueuedRequest;
}
Context->RequestQueue = NULL;
break;
default:
DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent);
break;
DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent);
break;
}
return NO_ERROR;
@ -450,7 +582,7 @@ WSHOpenSocket2(
/* Setup a socket context area */
Context = HeapAlloc(GetProcessHeap(), 0, sizeof(SOCKET_CONTEXT));
Context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_CONTEXT));
if (!Context) {
RtlFreeUnicodeString(TransportDeviceName);
return WSAENOBUFS;
@ -460,14 +592,14 @@ WSHOpenSocket2(
Context->SocketType = *SocketType;
Context->Protocol = *Protocol;
Context->Flags = Flags;
Context->SocketState = SocketStateCreated;
*HelperDllSocketContext = Context;
*NotificationEvents = WSH_NOTIFY_CLOSE;
*NotificationEvents = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND;
return NO_ERROR;
}
INT
EXPORT
WSHSetSocketInformation(
@ -480,9 +612,74 @@ WSHSetSocketInformation(
IN PCHAR OptionValue,
IN INT OptionLength)
{
UNIMPLEMENTED
PSOCKET_CONTEXT Context = HelperDllSocketContext;
UINT RealOptionName;
INT Status;
PTCP_REQUEST_SET_INFORMATION_EX Info;
PQUEUED_REQUEST Queued, NextQueued;
return NO_ERROR;
DPRINT("WSHSetSocketInformation\n");
/* FIXME: We only handle address file object here */
RealOptionName = GetAddressOption(Level, OptionName);
if (!RealOptionName)
return WSAEINVAL;
Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + OptionLength);
if (!Info)
return WSAENOBUFS;
Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
Info->ID.toi_class = INFO_CLASS_PROTOCOL;
Info->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
Info->ID.toi_id = RealOptionName;
Info->BufferSize = OptionLength;
memcpy(Info->Buffer, OptionValue, OptionLength);
if (Context->SocketState == SocketStateCreated)
{
if (Context->RequestQueue)
{
Queued = Context->RequestQueue;
while ((NextQueued = Queued->Next))
{
Queued = NextQueued;
}
Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
if (!Queued->Next)
{
HeapFree(GetProcessHeap(), 0, Info);
return WSAENOBUFS;
}
NextQueued = Queued->Next;
NextQueued->Next = NULL;
NextQueued->Info = Info;
}
else
{
Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
if (!Context->RequestQueue)
{
HeapFree(GetProcessHeap(), 0, Info);
return WSAENOBUFS;
}
Context->RequestQueue->Next = NULL;
Context->RequestQueue->Info = Info;
}
return 0;
}
Status = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX);
HeapFree(GetProcessHeap(), 0, Info);
return Status;
}

View file

@ -9,6 +9,10 @@
#define WIN32_NO_STATUS
#include <wsahelp.h>
#include <tdiinfo.h>
#include <tcpioctl.h>
#include <tdilib.h>
#include <ws2tcpip.h>
#include <rtlfuncs.h>
#define EXPORT WINAPI
@ -17,12 +21,27 @@
#define DD_UDP_DEVICE_NAME L"\\Device\\Udp"
#define DD_RAW_IP_DEVICE_NAME L"\\Device\\RawIp"
typedef enum _SOCKET_STATE {
SocketStateCreated,
SocketStateBound,
SocketStateListening,
SocketStateConnected
} SOCKET_STATE, *PSOCKET_STATE;
typedef struct _QUEUED_REQUEST {
PTCP_REQUEST_SET_INFORMATION_EX Info;
PVOID Next;
} QUEUED_REQUEST, *PQUEUED_REQUEST;
typedef struct _SOCKET_CONTEXT {
INT AddressFamily;
INT SocketType;
INT Protocol;
DWORD Flags;
DWORD AddrFileEntityType;
DWORD AddrFileInstance;
SOCKET_STATE SocketState;
PQUEUED_REQUEST RequestQueue;
} SOCKET_CONTEXT, *PSOCKET_CONTEXT;
#endif /* __WSHTCPIP_H */

View file

@ -3,9 +3,11 @@
<module name="wshtcpip" type="win32dll" entrypoint="0" baseaddress="${BASEADDRESS_WSHTCPIP}" installbase="system32" installname="wshtcpip.dll" unicode="yes">
<importlibrary definition="wshtcpip.spec" />
<include base="wshtcpip">.</include>
<include base="tdilib">.</include>
<library>ntdll</library>
<library>kernel32</library>
<library>ws2_32</library>
<library>tdilib</library>
<file>wshtcpip.c</file>
<file>wshtcpip.rc</file>
</module>

View file

@ -302,7 +302,7 @@ static NTSTATUS NTAPI StreamSocketConnectComplete
NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
AFD_DbgPrint(MID_TRACE,("Completing connect %x\n", NextIrp));
NextIrp->IoStatus.Status = Status;
NextIrp->IoStatus.Information = 0;
NextIrp->IoStatus.Information = NT_SUCCESS(Status) ? ((ULONG_PTR)FCB->Connection.Handle) : 0;
if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
(void)IoSetCancelRoutine(NextIrp, NULL);
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );

View file

@ -136,6 +136,9 @@ typedef struct _ADDRESS_FILE {
USHORT Protocol; /* Protocol number */
USHORT Port; /* Network port (network byte order) */
UCHAR TTL; /* Time to live stored in packets sent from this address file */
UINT DF; /* Don't fragment */
UINT BCast; /* Receive broadcast packets */
UINT HeaderIncl; /* Include header in RawIP packets */
WORK_QUEUE_ITEM WorkItem; /* Work queue item handle */
DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine for delete request */
PVOID Context; /* Delete request context */

View file

@ -13,21 +13,50 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
PVOID Buffer,
UINT BufferSize)
{
//KIRQL OldIrql;
KIRQL OldIrql;
switch (ID->toi_id)
{
#if 0
case AO_OPTION_TTL:
if (BufferSize < sizeof(UCHAR))
if (BufferSize < sizeof(UINT))
return TDI_INVALID_PARAMETER;
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
LockObject(AddrFile, &OldIrql);
AddrFile->TTL = *((PUCHAR)Buffer);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
UnlockObject(AddrFile, OldIrql);
return TDI_SUCCESS;
#endif
case AO_OPTION_IP_DONTFRAGMENT:
if (BufferSize < sizeof(UINT))
return TDI_INVALID_PARAMETER;
LockObject(AddrFile, &OldIrql);
AddrFile->DF = *((PUINT)Buffer);
UnlockObject(AddrFile, OldIrql);
return TDI_SUCCESS;
case AO_OPTION_BROADCAST:
if (BufferSize < sizeof(UINT))
return TDI_INVALID_PARAMETER;
LockObject(AddrFile, &OldIrql);
AddrFile->BCast = *((PUINT)Buffer);
UnlockObject(AddrFile, OldIrql);
return TDI_SUCCESS;
case AO_OPTION_IP_HDRINCL:
if (BufferSize < sizeof(UINT))
return TDI_INVALID_PARAMETER;
LockObject(AddrFile, &OldIrql);
AddrFile->HeaderIncl = *((PUINT)Buffer);
UnlockObject(AddrFile, OldIrql);
return TDI_SUCCESS;
default:
DbgPrint("Unimplemented option %x\n", ID->toi_id);

View file

@ -244,15 +244,16 @@ NTSTATUS FileOpenAddress(
return STATUS_INSUFFICIENT_RESOURCES;
}
TI_DbgPrint(DEBUG_ADDRFILE, ("Address file object allocated at (0x%X).\n", AddrFile));
RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE));
AddrFile->RefCount = 1;
AddrFile->Free = AddrFileFree;
/* Set our default TTL */
/* Set our default options */
AddrFile->TTL = 128;
AddrFile->DF = 0;
AddrFile->BCast = 1;
AddrFile->HeaderIncl = 1;
/* Make sure address is a local unicast address or 0 */
/* FIXME: IPv4 only */

View file

@ -50,6 +50,46 @@
#define IP_INTFC_INFO_ID 0x103
#define MAX_PHYSADDR_SIZE 8
/* Address Object Options */
#define AO_OPTION_TTL 1
#define AO_OPTION_MCASTTTL 2
#define AO_OPTION_MCASTIF 3
#define AO_OPTION_XSUM 4
#define AO_OPTION_IPOPTIONS 5
#define AO_OPTION_ADD_MCAST 6
#define AO_OPTION_DEL_MCAST 7
#define AO_OPTION_TOS 8
#define AO_OPTION_IP_DONTFRAGMENT 9
#define AO_OPTION_MCASTLOOP 10
#define AO_OPTION_BROADCAST 11
#define AO_OPTION_IP_HDRINCL 12
#define AO_OPTION_RCVALL 13
#define AO_OPTION_RCVALL_MCAST 14
#define AO_OPTION_RCVALL_IGMPMCAST 15
#define AO_OPTION_UNNUMBEREDIF 16
#define AO_OPTION_IP_UCASTIF 17
#define AO_OPTION_ABSORB_RTRALERT 18
#define AO_OPTION_LIMIT_BCASTS 19
#define AO_OPTION_INDEX_BIND 20
#define AO_OPTION_INDEX_MCASTIF 21
#define AO_OPTION_INDEX_ADD_MCAST 22
#define AO_OPTION_INDEX_DEL_MCAST 23
#define AO_OPTION_IFLIST 24
#define AO_OPTION_ADD_IFLIST 25
#define AO_OPTION_DEL_IFLIST 26
#define AO_OPTION_IP_PKTINFO 27
#define AO_OPTION_ADD_MCAST_SRC 28
#define AO_OPTION_DEL_MCAST_SRC 29
#define AO_OPTION_MCAST_FILTER 30
#define AO_OPTION_BLOCK_MCAST_SRC 31
#define AO_OPTION_UNBLOCK_MCAST_SRC 32
#define AO_OPTION_UDP_CKSUM_COVER 33
#define AO_OPTION_WINDOW 34
#define AO_OPTION_SCALE_CWIN 35
#define AO_OPTION_RCV_HOPLIMIT 36
#define AO_OPTION_UNBIND 37
#define AO_OPTION_PROTECT 38
typedef struct IFEntry
{
ULONG if_index;

View file

@ -50,7 +50,7 @@ INT WINAPI WSHEnumProtocols(LPINT,LPWSTR,LPVOID,LPDWORD);
INT WINAPI WSHGetBroadcastSockaddr(PVOID,PSOCKADDR,PINT);
INT WINAPI WSHGetProviderGuid(LPWSTR,LPGUID);
INT WINAPI WSHGetSockaddrType(PSOCKADDR,DWORD,PSOCKADDR_INFO);
INT WINAPI WSHGetSocketInformation(PVOID,SOCKET,HANDLE,HANDLE,INT,INT,PCHAR,INT);
INT WINAPI WSHGetSocketInformation(PVOID,SOCKET,HANDLE,HANDLE,INT,INT,PCHAR,LPINT);
INT WINAPI WSHGetWildcardSockaddr(PVOID,PSOCKADDR,PINT);
DWORD WINAPI WSHGetWinsockMapping(PWINSOCK_MAPPING,DWORD);
INT WINAPI WSHGetWSAProtocolInfo(LPWSTR,LPWSAPROTOCOL_INFOW*,LPDWORD);
@ -69,7 +69,7 @@ typedef INT (WINAPI *PWSH_ENUM_PROTOCOLS)(LPINT,LPWSTR,LPVOID,LPDWORD);
typedef INT (WINAPI *PWSH_GET_BROADCAST_SOCKADDR)(PVOID,PSOCKADDR,PINT);
typedef INT (WINAPI *PWSH_GET_PROVIDER_GUID)(LPWSTR,LPGUID);
typedef INT (WINAPI *PWSH_GET_SOCKADDR_TYPE)(PSOCKADDR,DWORD,PSOCKADDR_INFO);
typedef INT (WINAPI *PWSH_GET_SOCKET_INFORMATION)(PVOID,SOCKET,HANDLE,HANDLE,INT,INT,PCHAR,INT);
typedef INT (WINAPI *PWSH_GET_SOCKET_INFORMATION)(PVOID,SOCKET,HANDLE,HANDLE,INT,INT,PCHAR,LPINT);
typedef INT (WINAPI *PWSH_GET_WILDCARD_SOCKEADDR)(PVOID,PSOCKADDR,PINT);
typedef DWORD (WINAPI *PWSH_GET_WINSOCK_MAPPING)(PWINSOCK_MAPPING,DWORD);
typedef INT (WINAPI *PWSH_GET_WSAPROTOCOL_INFO)(LPWSTR,LPWSAPROTOCOL_INFOW*,LPDWORD);

View file

@ -91,8 +91,13 @@ VOID DGDeliverData(
}
else
{
/* Give client the IP header too if it is a raw IP file object */
DataBuffer = IPPacket->Header;
if (AddrFile->HeaderIncl)
DataBuffer = IPPacket->Header;
else
{
DataBuffer = IPPacket->Data;
DataSize -= IPPacket->HeaderSize;
}
}
if (!IsListEmpty(&AddrFile->ReceiveQueue))

View file

@ -58,6 +58,9 @@
<directory name="smlib">
<xi:include href="smlib/smlib.rbuild" />
</directory>
<directory name="tdilib">
<xi:include href="tdilib/tdilib.rbuild" />
</directory>
<directory name="win32ksys">
<xi:include href="win32ksys/win32ksys.rbuild" />
</directory>

123
lib/tdilib/enum.c Normal file
View file

@ -0,0 +1,123 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TDI interface
* FILE: enum.c
* PURPOSE: TDI entity enumeration
*/
#include "iphlpapi_private.h"
#include "tdilib.h"
/* A generic thing-getting function which interacts in the right way with
* TDI. This may seem oblique, but I'm using it to reduce code and hopefully
* make this thing easier to debug.
*
* The things returned can be any of:
* TDIEntityID
* TDIObjectID
* IFEntry
* IPSNMPInfo
* IPAddrEntry
* IPInterfaceInfo
*/
NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
DWORD toiClass,
DWORD toiType,
DWORD toiId,
DWORD teiEntity,
DWORD teiInstance,
DWORD fixedPart,
DWORD entrySize,
PVOID *tdiEntitySet,
PDWORD numEntries ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
PVOID entitySet = 0;
NTSTATUS status = STATUS_SUCCESS;
DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES,
arraySize = entrySize * MAX_TDI_ENTITIES;
req.ID.toi_class = toiClass;
req.ID.toi_type = toiType;
req.ID.toi_id = toiId;
req.ID.toi_entity.tei_entity = teiEntity;
req.ID.toi_entity.tei_instance = teiInstance;
/* There's a subtle problem here...
* If an interface is added at this exact instant, (as if by a PCMCIA
* card insertion), the array will still not have enough entries after
* have allocated it after the first DeviceIoControl call.
*
* We'll get around this by repeating until the number of interfaces
* stabilizes.
*/
do {
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
0,
0,
&allocationSizeForEntityArray,
NULL );
if(!status)
{
return STATUS_UNSUCCESSFUL;
}
arraySize = allocationSizeForEntityArray;
entitySet = HeapAlloc( GetProcessHeap(), 0, arraySize );
if( !entitySet ) {
status = STATUS_INSUFFICIENT_RESOURCES;
return status;
}
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
entitySet,
arraySize,
&allocationSizeForEntityArray,
NULL );
/* This is why we have the loop -- we might have added an adapter */
if( arraySize == allocationSizeForEntityArray )
break;
HeapFree( GetProcessHeap(), 0, entitySet );
entitySet = 0;
if(!status)
return STATUS_UNSUCCESSFUL;
} while( TRUE ); /* We break if the array we received was the size we
* expected. Therefore, we got here because it wasn't */
*numEntries = (arraySize - fixedPart) / entrySize;
*tdiEntitySet = entitySet;
return STATUS_SUCCESS;
}
VOID tdiFreeThingSet( PVOID things ) {
HeapFree( GetProcessHeap(), 0, things );
}
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile,
TDIEntityID **entitySet,
PDWORD numEntities ) {
NTSTATUS status = tdiGetSetOfThings( tcpFile,
INFO_CLASS_GENERIC,
INFO_TYPE_PROVIDER,
ENTITY_LIST_ID,
GENERIC_ENTITY,
0,
0,
sizeof(TDIEntityID),
(PVOID *)entitySet,
numEntities );
return status;
}

54
lib/tdilib/handle.c Normal file
View file

@ -0,0 +1,54 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TDI interface
* FILE: handle.c
* PURPOSE: TDI transport handle management
*/
#include "iphlpapi_private.h"
const PWCHAR TcpFileName = L"\\Device\\Tcp";
NTSTATUS openTcpFile(PHANDLE tcpFile)
{
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
RtlInitUnicodeString( &fileName, TcpFileName );
InitializeObjectAttributes( &objectAttributes,
&fileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = ZwCreateFile( tcpFile,
SYNCHRONIZE | GENERIC_EXECUTE |
GENERIC_READ | GENERIC_WRITE,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
0,
0 );
/* String does not need to be freed: it points to the constant
* string we provided */
if (!NT_SUCCESS(status))
*tcpFile = INVALID_HANDLE_VALUE;
return status;
}
VOID closeTcpFile( HANDLE h )
{
ASSERT(h != INVALID_HANDLE_VALUE);
NtClose( h );
}

20
lib/tdilib/tdilib.h Normal file
View file

@ -0,0 +1,20 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TDI interface
* FILE: tdilib.h
* PURPOSE: Shared TDI library header
*/
#ifndef TDILIB_H
#define TDILIB_H
NTSTATUS openTcpFile(PHANDLE tcpFile);
VOID closeTcpFile(HANDLE tcpFile);
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile, TDIEntityID **entitySet,
PDWORD numEntities );
NTSTATUS tdiGetSetOfThings( HANDLE tcpFile, DWORD toiClass, DWORD toiType,
DWORD toiId, DWORD teiEntity, DWORD teiInstance,
DWORD fixedPart,
DWORD entrySize, PVOID *tdiEntitySet,
PDWORD numEntries );
VOID tdiFreeThingSet( PVOID things );
#endif

9
lib/tdilib/tdilib.rbuild Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="tdilib" type="staticlibrary">
<include base="iphlpapi">.</include>
<include base="tdilib">.</include>
<library>ntdll</library>
<file>enum.c</file>
<file>handle.c</file>
</module>