mirror of
https://github.com/reactos/reactos.git
synced 2025-04-28 01:11:35 +00:00
[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:
parent
2522eb7b9b
commit
3f6a56fa36
21 changed files with 670 additions and 251 deletions
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -91,7 +91,7 @@ WSHGetSocketInformation(
|
|||
IN INT Level,
|
||||
IN INT OptionName,
|
||||
OUT PCHAR OptionValue,
|
||||
OUT INT OptionLength)
|
||||
OUT LPINT OptionLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
123
lib/tdilib/enum.c
Normal 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
54
lib/tdilib/handle.c
Normal 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
20
lib/tdilib/tdilib.h
Normal 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
9
lib/tdilib/tdilib.rbuild
Normal 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>
|
Loading…
Reference in a new issue