- improve WsControl error checking
- make WsControl output more closely match Win98's - document WsControl behavior a bit better
This commit is contained in:
parent
ec42ea4dfb
commit
c24fc00f25
|
@ -2,6 +2,7 @@
|
|||
* WSOCK32 specific functions
|
||||
*
|
||||
* Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
|
||||
* Copyright (C) 2003 Juan Lang.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -81,22 +82,21 @@ INT WINAPI WS1_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *o
|
|||
* From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
|
||||
* Date: 1997/08/17
|
||||
*
|
||||
* WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
|
||||
* The WSCNTL_TCPIP_QUERY_INFO option is partially implemented based
|
||||
* on observing the behaviour of WsControl with an app in
|
||||
* Windows 98. It is not fully implemented, and there could
|
||||
* be (are?) errors due to incorrect assumptions made.
|
||||
*
|
||||
*
|
||||
* WsControl returns WSCTL_SUCCESS on success.
|
||||
* STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
|
||||
* (*pcbResponseInfoLen) is too small, otherwise errors return -1.
|
||||
*
|
||||
* It doesn't seem to generate errors that can be retrieved by
|
||||
* WSAGetLastError().
|
||||
* ERROR_LOCK_VIOLATION is returned if the output buffer length
|
||||
* (*pcbResponseInfoLen) is too small. This is an unusual error code, but
|
||||
* it matches Win98's behavior. Other errors come from winerror.h, not from
|
||||
* winsock.h. Again, this is to match Win98 behavior.
|
||||
*
|
||||
*/
|
||||
|
||||
DWORD WINAPI WsControl(DWORD protocoll,
|
||||
DWORD WINAPI WsControl(DWORD protocol,
|
||||
DWORD action,
|
||||
LPVOID pRequestInfo,
|
||||
LPDWORD pcbRequestInfoLen,
|
||||
|
@ -108,154 +108,273 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
|||
rather than void */
|
||||
TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
|
||||
|
||||
/* validate input parameters. Error codes are from winerror.h, not from
|
||||
* winsock.h. pcbResponseInfoLen is apparently allowed to be NULL for some
|
||||
* commands, since winipcfg.exe fails if we ensure it's non-NULL in every
|
||||
* case.
|
||||
*/
|
||||
if (protocol != IPPROTO_TCP) return ERROR_INVALID_PARAMETER;
|
||||
if (!pcommand) return ERROR_INVALID_PARAMETER;
|
||||
if (!pcbRequestInfoLen) return ERROR_INVALID_ACCESS;
|
||||
if (*pcbRequestInfoLen < sizeof(TDIObjectID)) return ERROR_INVALID_ACCESS;
|
||||
if (!pResponseInfo) return ERROR_INVALID_PARAMETER;
|
||||
if (pcommand->toi_type != INFO_TYPE_PROVIDER) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
|
||||
pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
|
||||
pcommand->toi_id, pcommand->toi_entity.tei_entity,
|
||||
pcommand->toi_entity.tei_instance,
|
||||
pcommand->toi_class, pcommand->toi_type );
|
||||
|
||||
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case WSCNTL_TCPIP_QUERY_INFO:
|
||||
{
|
||||
if (pcommand->toi_class != INFO_CLASS_GENERIC &&
|
||||
pcommand->toi_class != INFO_CLASS_PROTOCOL)
|
||||
{
|
||||
ERR("Unexpected class %ld for WSCNTL_TCPIP_QUERY_INFO",
|
||||
pcommand->toi_class);
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
}
|
||||
|
||||
switch (pcommand->toi_id)
|
||||
{
|
||||
/*
|
||||
ENTITY_LIST_ID seems to get number of adapters in the system.
|
||||
(almost like an index to be used when calling other WsControl options)
|
||||
/* ENTITY_LIST_ID gets the list of "entity IDs", where an entity
|
||||
may represent an interface, or a datagram service, or address
|
||||
translation, or other fun things. Typically an entity ID represents
|
||||
a class of service, which is further queried for what type it is.
|
||||
Different types will then have more specific queries defined.
|
||||
*/
|
||||
case ENTITY_LIST_ID:
|
||||
{
|
||||
TDIEntityID *baseptr = pResponseInfo;
|
||||
DWORD numInt, i, ipAddrTableSize;
|
||||
PMIB_IPADDRTABLE table;
|
||||
TDIEntityID *baseptr = (TDIEntityID *)pResponseInfo;
|
||||
DWORD numInt, i, ifTable, spaceNeeded;
|
||||
PMIB_IFTABLE table;
|
||||
|
||||
if (pcommand->toi_class != INFO_CLASS_GENERIC &&
|
||||
pcommand->toi_type != INFO_TYPE_PROVIDER)
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
if (pcommand->toi_class != INFO_CLASS_GENERIC)
|
||||
{
|
||||
FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
|
||||
pcommand->toi_class, pcommand->toi_type);
|
||||
return (WSAEOPNOTSUPP);
|
||||
FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx",
|
||||
pcommand->toi_class);
|
||||
return (ERROR_BAD_ENVIRONMENT);
|
||||
}
|
||||
|
||||
GetNumberOfInterfaces(&numInt);
|
||||
spaceNeeded = sizeof(TDIEntityID) * (numInt + 4);
|
||||
|
||||
if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) )
|
||||
if (*pcbResponseInfoLen < spaceNeeded)
|
||||
return (ERROR_LOCK_VIOLATION);
|
||||
|
||||
ifTable = 0;
|
||||
GetIfTable(NULL, &ifTable, FALSE);
|
||||
table = (PMIB_IFTABLE)calloc(1, ifTable);
|
||||
if (!table)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
GetIfTable(table, &ifTable, FALSE);
|
||||
|
||||
spaceNeeded = sizeof(TDIEntityID) * (table->dwNumEntries + 4);
|
||||
if (*pcbResponseInfoLen < spaceNeeded)
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
free(table);
|
||||
return (ERROR_LOCK_VIOLATION);
|
||||
}
|
||||
|
||||
/* expect a 1:1 correspondence between interfaces and IP
|
||||
addresses, so use the cheaper (less memory allocated)
|
||||
GetIpAddrTable rather than GetIfTable */
|
||||
ipAddrTableSize = 0;
|
||||
GetIpAddrTable(NULL, &ipAddrTableSize, FALSE);
|
||||
table = (PMIB_IPADDRTABLE)calloc(1, ipAddrTableSize);
|
||||
if (!table) return -1; /* FIXME: better error code */
|
||||
GetIpAddrTable(table, &ipAddrTableSize, FALSE);
|
||||
|
||||
/* 0 it out first */
|
||||
memset(baseptr, 0, sizeof(TDIEntityID)*(table->dwNumEntries*2));
|
||||
memset(baseptr, 0, spaceNeeded);
|
||||
|
||||
for (i = 0; i < table->dwNumEntries; i++)
|
||||
{
|
||||
/* tei_instance is an network interface identifier.
|
||||
I'm not quite sure what the difference is between tei_entity values of
|
||||
CL_NL_ENTITY and IF_ENTITY */
|
||||
baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++;
|
||||
baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++;
|
||||
/* Return IF_GENERIC on every interface, and AT_ENTITY,
|
||||
* CL_NL_ENTITY, CL_TL_ENTITY, and CO_TL_ENTITY on the first
|
||||
* interface. MS returns them only on the loopback
|
||||
* interface, but it doesn't seem to matter.
|
||||
*/
|
||||
if (i == 0)
|
||||
{
|
||||
baseptr->tei_entity = CO_TL_ENTITY;
|
||||
baseptr->tei_instance = table->table[i].dwIndex;
|
||||
baseptr++;
|
||||
baseptr->tei_entity = CL_TL_ENTITY;
|
||||
baseptr->tei_instance = table->table[i].dwIndex;
|
||||
baseptr++;
|
||||
baseptr->tei_entity = CL_NL_ENTITY;
|
||||
baseptr->tei_instance = table->table[i].dwIndex;
|
||||
baseptr++;
|
||||
baseptr->tei_entity = AT_ENTITY;
|
||||
baseptr->tei_instance = table->table[i].dwIndex;
|
||||
baseptr++;
|
||||
}
|
||||
baseptr->tei_entity = IF_GENERIC;
|
||||
baseptr->tei_instance = table->table[i].dwIndex;
|
||||
baseptr++;
|
||||
}
|
||||
|
||||
/* Calculate size of out buffer */
|
||||
*pcbResponseInfoLen = sizeof(TDIEntityID)*(table->dwNumEntries*2);
|
||||
*pcbResponseInfoLen = spaceNeeded;
|
||||
free(table);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* ENTITY_TYPE_ID is used to obtain simple information about a
|
||||
network card, such as MAC Address, description, interface type,
|
||||
number of network addresses, etc. */
|
||||
case ENTITY_TYPE_ID: /* ALSO: IP_MIB_STATS_ID */
|
||||
/* Returns MIB-II statistics for an interface */
|
||||
case ENTITY_TYPE_ID:
|
||||
switch (pcommand->toi_entity.tei_entity)
|
||||
{
|
||||
if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER)
|
||||
{
|
||||
if (pcommand->toi_entity.tei_entity == IF_ENTITY)
|
||||
case IF_GENERIC:
|
||||
if (pcommand->toi_class == INFO_CLASS_GENERIC)
|
||||
{
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
*((ULONG *)pResponseInfo) = IF_MIB;
|
||||
|
||||
/* Calculate size of out buffer */
|
||||
*pcbResponseInfoLen = sizeof (ULONG);
|
||||
|
||||
}
|
||||
else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
|
||||
{
|
||||
* ((ULONG *)pResponseInfo) = CL_NL_IP;
|
||||
|
||||
/* Calculate size of out buffer */
|
||||
*pcbResponseInfoLen = sizeof(ULONG);
|
||||
}
|
||||
}
|
||||
else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
|
||||
pcommand->toi_type == INFO_TYPE_PROVIDER)
|
||||
{
|
||||
if (pcommand->toi_entity.tei_entity == IF_ENTITY)
|
||||
else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
|
||||
{
|
||||
MIB_IFROW row;
|
||||
DWORD index = pcommand->toi_entity.tei_instance, ret;
|
||||
DWORD size = sizeof(row) - sizeof(row.wszName) -
|
||||
sizeof(row.bDescr);
|
||||
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
if (*pcbResponseInfoLen < size)
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
return (ERROR_LOCK_VIOLATION);
|
||||
row.dwIndex = index;
|
||||
ret = GetIfEntry(&row);
|
||||
if (ret != NO_ERROR)
|
||||
{
|
||||
ERR ("Error retrieving data for interface index %lu\n", index);
|
||||
return -1; /* FIXME: better error code */
|
||||
ERR ("Error retrieving data for interface index %lu\n",
|
||||
index);
|
||||
return ret;
|
||||
}
|
||||
size = sizeof(row) - sizeof(row.wszName) -
|
||||
sizeof(row.bDescr) + row.dwDescrLen;
|
||||
if (*pcbResponseInfoLen < size)
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
return (ERROR_LOCK_VIOLATION);
|
||||
memcpy(pResponseInfo, &row.dwIndex, size);
|
||||
*pcbResponseInfoLen = size;
|
||||
}
|
||||
else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY)
|
||||
{
|
||||
/* This case is used to obtain general statistics about the
|
||||
network */
|
||||
break;
|
||||
|
||||
if (*pcbResponseInfoLen < sizeof(MIB_IPSTATS))
|
||||
/* Returns address-translation related data. In our case, this is
|
||||
* ARP.
|
||||
* FIXME: Win98 seems to assume ARP will always be on interface
|
||||
* index 1, so arp.exe fails when this isn't the case.
|
||||
*/
|
||||
case AT_ENTITY:
|
||||
if (pcommand->toi_class == INFO_CLASS_GENERIC)
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
*((ULONG *)pResponseInfo) = AT_ARP;
|
||||
*pcbResponseInfoLen = sizeof(ULONG);
|
||||
}
|
||||
else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
|
||||
{
|
||||
PMIB_IPNETTABLE table;
|
||||
DWORD size;
|
||||
PULONG output = (PULONG)pResponseInfo;
|
||||
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
if (*pcbResponseInfoLen < sizeof(ULONG) * 2)
|
||||
return (ERROR_LOCK_VIOLATION);
|
||||
GetIpNetTable(NULL, &size, FALSE);
|
||||
table = (PMIB_IPNETTABLE)calloc(1, size);
|
||||
if (!table)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
GetIpNetTable(table, &size, FALSE);
|
||||
/* FIXME: I don't understand the meaning of the ARP output
|
||||
* very well, but it seems to indicate how many ARP entries
|
||||
* exist. I don't know whether this should reflect the
|
||||
* number per interface, as I'm only testing with a single
|
||||
* interface. So, I lie and say all ARP entries exist on
|
||||
* a single interface--the first one that appears in the
|
||||
* ARP table.
|
||||
*/
|
||||
*(output++) = table->dwNumEntries;
|
||||
*output = table->table[0].dwIndex;
|
||||
free(table);
|
||||
*pcbResponseInfoLen = sizeof(ULONG) * 2;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Returns connectionless network layer statistics--in our case,
|
||||
* this is IP.
|
||||
*/
|
||||
case CL_NL_ENTITY:
|
||||
if (pcommand->toi_class == INFO_CLASS_GENERIC)
|
||||
{
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
*((ULONG *)pResponseInfo) = CL_NL_IP;
|
||||
*pcbResponseInfoLen = sizeof(ULONG);
|
||||
}
|
||||
else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
|
||||
{
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
if (*pcbResponseInfoLen < sizeof(MIB_IPSTATS))
|
||||
return ERROR_LOCK_VIOLATION;
|
||||
GetIpStatistics((PMIB_IPSTATS)pResponseInfo);
|
||||
|
||||
/* Calculate size of out buffer */
|
||||
*pcbResponseInfoLen = sizeof(MIB_IPSTATS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
|
||||
pcommand->toi_class, pcommand->toi_type);
|
||||
|
||||
return (WSAEOPNOTSUPP);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* Returns connectionless transport layer statistics--in our case,
|
||||
* this is UDP.
|
||||
*/
|
||||
case CL_TL_ENTITY:
|
||||
if (pcommand->toi_class == INFO_CLASS_GENERIC)
|
||||
{
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
*((ULONG *)pResponseInfo) = CL_TL_UDP;
|
||||
*pcbResponseInfoLen = sizeof(ULONG);
|
||||
}
|
||||
else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
|
||||
{
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
if (*pcbResponseInfoLen < sizeof(MIB_UDPSTATS))
|
||||
return ERROR_LOCK_VIOLATION;
|
||||
GetUdpStatistics((PMIB_UDPSTATS)pResponseInfo);
|
||||
*pcbResponseInfoLen = sizeof(MIB_UDPSTATS);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Returns connection-oriented transport layer statistics--in our
|
||||
* case, this is TCP.
|
||||
*/
|
||||
case CO_TL_ENTITY:
|
||||
if (pcommand->toi_class == INFO_CLASS_GENERIC)
|
||||
{
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
*((ULONG *)pResponseInfo) = CO_TL_TCP;
|
||||
*pcbResponseInfoLen = sizeof(ULONG);
|
||||
}
|
||||
else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
|
||||
{
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
if (*pcbResponseInfoLen < sizeof(MIB_TCPSTATS))
|
||||
return ERROR_LOCK_VIOLATION;
|
||||
GetTcpStatistics((PMIB_TCPSTATS)pResponseInfo);
|
||||
*pcbResponseInfoLen = sizeof(MIB_TCPSTATS);
|
||||
}
|
||||
break;
|
||||
|
||||
/* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a
|
||||
particular network adapter */
|
||||
default:
|
||||
ERR("Unknown entity %ld for ENTITY_TYPE_ID query",
|
||||
pcommand->toi_entity.tei_entity);
|
||||
}
|
||||
break;
|
||||
|
||||
/* This call returns the IP address, subnet mask, and broadcast
|
||||
* address for an interface. If there are multiple IP addresses for
|
||||
* the interface with the given index, returns the "first" one.
|
||||
*/
|
||||
case IP_MIB_ADDRTABLE_ENTRY_ID:
|
||||
{
|
||||
DWORD index = pcommand->toi_entity.tei_instance;
|
||||
|
@ -263,18 +382,18 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
|||
PMIB_IPADDRTABLE table;
|
||||
DWORD tableSize, i;
|
||||
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
if (*pcbResponseInfoLen < sizeof(MIB_IPADDRROW))
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
return (ERROR_LOCK_VIOLATION);
|
||||
|
||||
/* overkill, get entire table, because there isn't an
|
||||
exported function that gets just one entry, and don't
|
||||
necessarily want our own private export. */
|
||||
/* get entire table, because there isn't an exported function that
|
||||
gets just one entry. */
|
||||
tableSize = 0;
|
||||
GetIpAddrTable(NULL, &tableSize, FALSE);
|
||||
table = (PMIB_IPADDRTABLE)calloc(1, tableSize);
|
||||
if (!table) return -1; /* FIXME: better error code */
|
||||
if (!table)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
GetIpAddrTable(table, &tableSize, FALSE);
|
||||
for (i = 0; i < table->dwNumEntries; i++)
|
||||
{
|
||||
|
@ -287,14 +406,10 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
|||
}
|
||||
free(table);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* Calculate size of out buffer */
|
||||
*pcbResponseInfoLen = sizeof(MIB_IPADDRROW);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* This call returns the routing table.
|
||||
* No official documentation found, even the name of the command is unknown.
|
||||
* Work is based on
|
||||
|
@ -310,24 +425,23 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
|||
PMIB_IPFORWARDTABLE table;
|
||||
IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo;
|
||||
|
||||
if (!pcbResponseInfoLen)
|
||||
return ERROR_BAD_ENVIRONMENT;
|
||||
GetIpForwardTable(NULL, &routeTableSize, FALSE);
|
||||
numRoutes = min(routeTableSize - sizeof(MIB_IPFORWARDTABLE), 0)
|
||||
/ sizeof(MIB_IPFORWARDROW) + 1;
|
||||
if (*pcbResponseInfoLen < sizeof(IPRouteEntry) * numRoutes)
|
||||
{
|
||||
return (STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
return (ERROR_LOCK_VIOLATION);
|
||||
table = (PMIB_IPFORWARDTABLE)calloc(1, routeTableSize);
|
||||
if (!table) return -1; /* FIXME: better return value */
|
||||
if (!table)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
GetIpForwardTable(table, &routeTableSize, FALSE);
|
||||
|
||||
memset(pResponseInfo, 0, sizeof(IPRouteEntry) * numRoutes);
|
||||
for (ndx = 0; ndx < table->dwNumEntries; ndx++)
|
||||
{
|
||||
winRouteTable->ire_addr =
|
||||
table->table[ndx].dwForwardDest;
|
||||
winRouteTable->ire_index =
|
||||
table->table[ndx].dwForwardIfIndex;
|
||||
winRouteTable->ire_addr = table->table[ndx].dwForwardDest;
|
||||
winRouteTable->ire_index = table->table[ndx].dwForwardIfIndex;
|
||||
winRouteTable->ire_metric =
|
||||
table->table[ndx].dwForwardMetric1;
|
||||
/* winRouteTable->ire_option4 =
|
||||
|
@ -353,11 +467,11 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
|||
|
||||
default:
|
||||
{
|
||||
FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx, toi_type=0x%lx\n",
|
||||
pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
|
||||
pcommand->toi_class, pcommand->toi_type);
|
||||
FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx\n",
|
||||
pcommand->toi_id, pcommand->toi_entity.tei_entity,
|
||||
pcommand->toi_entity.tei_instance, pcommand->toi_class);
|
||||
|
||||
return (WSAEOPNOTSUPP);
|
||||
return (ERROR_BAD_ENVIRONMENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,14 +496,12 @@ DWORD WINAPI WsControl(DWORD protocoll,
|
|||
}
|
||||
|
||||
default:
|
||||
{
|
||||
FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
|
||||
protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
|
||||
FIXME("Protocol Not Supported -> protocol=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
|
||||
protocol, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
|
||||
|
||||
return (WSAEOPNOTSUPP);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (WSCTL_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -6,9 +6,12 @@
|
|||
*
|
||||
* The functionality of WsControl was created by observing its behaviour
|
||||
* in Windows 98, so there are likely to be bugs with the assumptions
|
||||
* that were made.
|
||||
* that were made. A significant amount of help came from
|
||||
* http://tangentsoft.net/wskfaq/articles/wscontrol.html , especially the
|
||||
* trace by Thomas Divine (www.pcausa.net).
|
||||
*
|
||||
* Copyright 2000 James Hatheway
|
||||
* Copyright 2003 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -28,8 +31,6 @@
|
|||
#ifndef WSCONTROL_H_INCLUDED
|
||||
#define WSCONTROL_H_INCLUDED
|
||||
|
||||
typedef unsigned char uchar; /* This doesn't seem to be in any standard headers */
|
||||
|
||||
#define WSCTL_SUCCESS 0
|
||||
|
||||
/*
|
||||
|
@ -57,44 +58,6 @@ typedef struct TDIObjectID
|
|||
unsigned long toi_id;
|
||||
} TDIObjectID;
|
||||
|
||||
typedef struct IPSNMPInfo
|
||||
{
|
||||
unsigned long ipsi_forwarding;
|
||||
unsigned long ipsi_defaultttl;
|
||||
unsigned long ipsi_inreceives;
|
||||
unsigned long ipsi_inhdrerrors;
|
||||
unsigned long ipsi_inaddrerrors;
|
||||
unsigned long ipsi_forwdatagrams;
|
||||
unsigned long ipsi_inunknownprotos;
|
||||
unsigned long ipsi_indiscards;
|
||||
unsigned long ipsi_indelivers;
|
||||
unsigned long ipsi_outrequests;
|
||||
unsigned long ipsi_routingdiscards;
|
||||
unsigned long ipsi_outdiscards;
|
||||
unsigned long ipsi_outnoroutes;
|
||||
unsigned long ipsi_reasmtimeout;
|
||||
unsigned long ipsi_reasmreqds;
|
||||
unsigned long ipsi_reasmoks;
|
||||
unsigned long ipsi_reasmfails;
|
||||
unsigned long ipsi_fragoks;
|
||||
unsigned long ipsi_fragfails;
|
||||
unsigned long ipsi_fragcreates;
|
||||
unsigned long ipsi_numif;
|
||||
unsigned long ipsi_numaddr;
|
||||
unsigned long ipsi_numroutes;
|
||||
} IPSNMPInfo;
|
||||
|
||||
typedef struct IPAddrEntry
|
||||
{
|
||||
unsigned long iae_addr;
|
||||
unsigned long iae_index;
|
||||
unsigned long iae_mask;
|
||||
unsigned long iae_bcastaddr;
|
||||
unsigned long iae_reasmsize;
|
||||
ushort iae_context;
|
||||
ushort iae_pad;
|
||||
} IPAddrEntry;
|
||||
|
||||
#ifdef if_type
|
||||
#undef if_type
|
||||
#endif
|
||||
|
@ -114,7 +77,7 @@ typedef struct IFEntry
|
|||
unsigned long if_mtu;
|
||||
unsigned long if_speed;
|
||||
unsigned long if_physaddrlen;
|
||||
uchar if_physaddr[MAX_PHYSADDR_SIZE];
|
||||
unsigned char if_physaddr[MAX_PHYSADDR_SIZE];
|
||||
unsigned long if_adminstatus;
|
||||
unsigned long if_operstatus;
|
||||
unsigned long if_lastchange;
|
||||
|
@ -131,7 +94,7 @@ typedef struct IFEntry
|
|||
unsigned long if_outerrors;
|
||||
unsigned long if_outqlen;
|
||||
unsigned long if_descrlen;
|
||||
uchar if_descr[1];
|
||||
unsigned char if_descr[1];
|
||||
} IFEntry;
|
||||
|
||||
|
||||
|
@ -153,34 +116,58 @@ typedef struct IPRouteEntry {
|
|||
} IPRouteEntry;
|
||||
|
||||
|
||||
/* Not sure what EXACTLY most of this stuff does.
|
||||
WsControl was implemented mainly by observing
|
||||
its behaviour in Win98 ************************/
|
||||
/* Constants for use in the toi_id field */
|
||||
#define ENTITY_LIST_ID 0 /* to get the list of entity IDs */
|
||||
#define ENTITY_TYPE_ID 1 /* it's an interface; what type of interface is it? */
|
||||
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101 /* not real name */
|
||||
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
|
||||
|
||||
/* Constants for use in the toi_class field */
|
||||
#define INFO_CLASS_GENERIC 0x100
|
||||
#define INFO_CLASS_PROTOCOL 0x200
|
||||
|
||||
/* Constants for use in the toi_type field */
|
||||
#define INFO_TYPE_PROVIDER 0x100
|
||||
#define ENTITY_LIST_ID 0
|
||||
|
||||
/* Interface types. The first one can be returned in the entity ID list--it's
|
||||
* an interface, and it can be further queried for what type of interface it is.
|
||||
*/
|
||||
#define IF_GENERIC 0x200 /* generic interface */
|
||||
#define IF_MIB 0x202 /* supports MIB-2 interface */
|
||||
|
||||
/* address translation types. The first can be turned in the entity ID list--
|
||||
* it supports address translation of some type, and it can be further queried
|
||||
* for what type of address translation it supports (I think).
|
||||
*/
|
||||
#define AT_ENTITY 0x280
|
||||
#define AT_ARP 0x280
|
||||
#define AT_NULL 0x282 /* doesn't do address translation after all (liar) */
|
||||
|
||||
/* network layer service providers. The first one can be returned in the
|
||||
* entity list ID--it supports a network layer (datagram) service, and it can
|
||||
* be further queried for what type of network layer service it provides.
|
||||
*/
|
||||
#define CL_NL_ENTITY 0x301
|
||||
#define IF_ENTITY 0x200
|
||||
#define ENTITY_TYPE_ID 1
|
||||
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
|
||||
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101 /* FIXME: not real name */
|
||||
/************************************************/
|
||||
#define CL_NL_IPX 0x301 /* implements IPX--probably won't see this, since
|
||||
* we're querying the TCP protocol */
|
||||
#define CL_NL_IP 0x303 /* implements IP */
|
||||
|
||||
/* Valid values to get back from entity type ID query */
|
||||
#define CO_TL_NBF 0x400 /* Entity implements NBF prot. */
|
||||
#define CO_TL_SPX 0x402 /* Entity implements SPX prot. */
|
||||
#define CO_TL_TCP 0x404 /* Entity implements TCP prot. */
|
||||
#define CO_TL_SPP 0x406 /* Entity implements SPP prot. */
|
||||
#define CL_TL_NBF 0x401 /* CL NBF protocol */
|
||||
#define CL_TL_UDP 0x403 /* Entity implements UDP */
|
||||
#define ER_ICMP 0x380 /* The ICMP protocol */
|
||||
#define CL_NL_IPX 0x301 /* Entity implements IPX */
|
||||
#define CL_NL_IP 0x303 /* Entity implements IP */
|
||||
#define AT_ARP 0x280 /* Entity implements ARP */
|
||||
#define AT_NULL 0x282 /* Entity does no address */
|
||||
#define IF_GENERIC 0x200 /* Generic interface */
|
||||
#define IF_MIB 0x202 /* Supports MIB-2 interface */
|
||||
/* echo request/response types. The first can be returned in the entity ID
|
||||
* list--it can be further queried for what type of echo it supports (I think).
|
||||
*/
|
||||
#define ER_ENTITY 0x380
|
||||
#define ER_ICMP 0x380
|
||||
|
||||
/* connection-oriented transport layer protocols--you know the drill by now */
|
||||
#define CO_TL_ENTITY 0x400
|
||||
#define CO_TL_NBF 0x400
|
||||
#define CO_TL_SPX 0x402
|
||||
#define CO_TL_TCP 0x404
|
||||
#define CO_TL_SPP 0x406
|
||||
|
||||
/* connectionless transport layer protocols--you know the drill by now */
|
||||
#define CL_TL_ENTITY 0x401
|
||||
#define CL_TL_NBF 0x401
|
||||
#define CL_TL_UDP 0x403
|
||||
|
||||
#endif /* WSCONTROL_H_INCLUDED */
|
||||
|
|
Loading…
Reference in New Issue