[ros-diffs] [dchapyshev] 34130: - Add inetmib1.dll from Wine - Small update snmpapi.def

dchapyshev at svn.reactos.org dchapyshev at svn.reactos.org
Fri Jun 27 19:08:03 CEST 2008


Author: dchapyshev
Date: Fri Jun 27 12:08:01 2008
New Revision: 34130

URL: http://svn.reactos.org/svn/reactos?rev=34130&view=rev
Log:
- Add inetmib1.dll from Wine
- Small update snmpapi.def

Added:
    trunk/reactos/dll/win32/inetmib1/
    trunk/reactos/dll/win32/inetmib1/inetmib1.rbuild   (with props)
    trunk/reactos/dll/win32/inetmib1/inetmib1.spec   (with props)
    trunk/reactos/dll/win32/inetmib1/main.c   (with props)
Modified:
    trunk/reactos/dll/win32/snmpapi/snmpapi.def
    trunk/reactos/dll/win32/win32.rbuild

Added: trunk/reactos/dll/win32/inetmib1/inetmib1.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetmib1/inetmib1.rbuild?rev=34130&view=auto
==============================================================================
--- trunk/reactos/dll/win32/inetmib1/inetmib1.rbuild (added)
+++ trunk/reactos/dll/win32/inetmib1/inetmib1.rbuild [iso-8859-1] Fri Jun 27 12:08:01 2008
@@ -1,0 +1,17 @@
+<module name="inetmib1" type="win32dll" baseaddress="${BASEADDRESS_INETMIB1}" installbase="system32" installname="inetmib1.dll" allowwarnings="true" entrypoint="0">
+        <importlibrary definition="inetmib1.spec.def" />
+        <include base="inetmib1">.</include>
+        <include base="ReactOS">include/reactos/wine</include>
+        <define name="__WINESRC__" />
+        <define name="__USE_W32API" />
+        <define name="_WIN32_IE">0x600</define>
+        <define name="_WIN32_WINNT">0x501</define>
+        <define name="WINVER">0x501</define>
+        <library>wine</library>
+        <library>snmpapi</library>
+        <library>kernel32</library>
+        <library>iphlpapi</library>
+        <library>ntdll</library>
+        <file>main.c</file>
+        <file>inetmib1.spec</file>
+</module>

Propchange: trunk/reactos/dll/win32/inetmib1/inetmib1.rbuild
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/dll/win32/inetmib1/inetmib1.spec
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetmib1/inetmib1.spec?rev=34130&view=auto
==============================================================================
--- trunk/reactos/dll/win32/inetmib1/inetmib1.spec (added)
+++ trunk/reactos/dll/win32/inetmib1/inetmib1.spec [iso-8859-1] Fri Jun 27 12:08:01 2008
@@ -1,0 +1,4 @@
+@ stdcall SnmpExtensionInit(long ptr ptr)
+@ stub SnmpExtensionInitEx
+@ stdcall SnmpExtensionQuery(long ptr ptr ptr)
+@ stub SnmpExtensionTrap

Propchange: trunk/reactos/dll/win32/inetmib1/inetmib1.spec
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/dll/win32/inetmib1/main.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetmib1/main.c?rev=34130&view=auto
==============================================================================
--- trunk/reactos/dll/win32/inetmib1/main.c (added)
+++ trunk/reactos/dll/win32/inetmib1/main.c [iso-8859-1] Fri Jun 27 12:08:01 2008
@@ -1,0 +1,1171 @@
+/*
+ * Copyright 2008 Juan Lang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "windef.h"
+#include "winbase.h"
+#include "snmp.h"
+#include "iphlpapi.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(inetmib1);
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+	TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
+
+	switch (fdwReason)
+	{
+		case DLL_WINE_PREATTACH:
+			return FALSE;    /* prefer native version */
+		case DLL_PROCESS_ATTACH:
+			DisableThreadLibraryCalls(hinstDLL);
+			break;
+		case DLL_PROCESS_DETACH:
+			break;
+		default:
+			break;
+	}
+
+	return TRUE;
+}
+
+/**
+ * Utility functions
+ */
+static void copyInt(AsnAny *value, void *src)
+{
+    value->asnType = ASN_INTEGER;
+    value->asnValue.number = *(DWORD *)src;
+}
+
+static void setStringValue(AsnAny *value, BYTE type, DWORD len, BYTE *str)
+{
+    AsnAny strValue;
+
+    strValue.asnType = type;
+    strValue.asnValue.string.stream = str;
+    strValue.asnValue.string.length = len;
+    strValue.asnValue.string.dynamic = TRUE;
+    SnmpUtilAsnAnyCpy(value, &strValue);
+}
+
+static void copyLengthPrecededString(AsnAny *value, void *src)
+{
+    DWORD len = *(DWORD *)src;
+
+    setStringValue(value, ASN_OCTETSTRING, len, (BYTE *)src + sizeof(DWORD));
+}
+
+typedef void (*copyValueFunc)(AsnAny *value, void *src);
+
+struct structToAsnValue
+{
+    size_t        offset;
+    copyValueFunc copy;
+};
+
+static AsnInteger32 mapStructEntryToValue(struct structToAsnValue *map,
+    UINT mapLen, void *record, UINT id, BYTE bPduType, SnmpVarBind *pVarBind)
+{
+    /* OIDs are 1-based */
+    if (!id)
+        return SNMP_ERRORSTATUS_NOSUCHNAME;
+    --id;
+    if (id >= mapLen)
+        return SNMP_ERRORSTATUS_NOSUCHNAME;
+    if (!map[id].copy)
+        return SNMP_ERRORSTATUS_NOSUCHNAME;
+    map[id].copy(&pVarBind->value, (BYTE *)record + map[id].offset);
+    return SNMP_ERRORSTATUS_NOERROR;
+}
+
+static void copyIpAddr(AsnAny *value, void *src)
+{
+    setStringValue(value, ASN_IPADDRESS, sizeof(DWORD), src);
+}
+
+static UINT mib2[] = { 1,3,6,1,2,1 };
+static UINT mib2System[] = { 1,3,6,1,2,1,1 };
+
+typedef BOOL (*varqueryfunc)(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus);
+
+struct mibImplementation
+{
+    AsnObjectIdentifier name;
+    void              (*init)(void);
+    varqueryfunc        query;
+};
+
+static UINT mib2IfNumber[] = { 1,3,6,1,2,1,2,1 };
+static PMIB_IFTABLE ifTable;
+
+static void mib2IfNumberInit(void)
+{
+    DWORD size = 0, ret = GetIfTable(NULL, &size, FALSE);
+
+    if (ret == ERROR_INSUFFICIENT_BUFFER)
+    {
+        ifTable = HeapAlloc(GetProcessHeap(), 0, size);
+        if (ifTable)
+            GetIfTable(ifTable, &size, FALSE);
+    }
+}
+
+static BOOL mib2IfNumberQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier numberOid = DEFINE_OID(mib2IfNumber);
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        if ((bPduType == SNMP_PDU_GET &&
+            !SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength))
+            || SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength)
+            < 0)
+        {
+            DWORD numIfs = ifTable ? ifTable->dwNumEntries : 0;
+
+            copyInt(&pVarBind->value, &numIfs);
+            if (bPduType == SNMP_PDU_GETNEXT)
+                SnmpUtilOidCpy(&pVarBind->name, &numberOid);
+            *pErrorStatus = SNMP_ERRORSTATUS_NOERROR;
+        }
+        else
+        {
+            *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+            /* Caller deals with OID if bPduType == SNMP_PDU_GETNEXT, so don't
+             * need to set it here.
+             */
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static void copyOperStatus(AsnAny *value, void *src)
+{
+    value->asnType = ASN_INTEGER;
+    /* The IPHlpApi definition of operational status differs from the MIB2 one,
+     * so map it to the MIB2 value.
+     */
+    switch (*(DWORD *)src)
+    {
+    case MIB_IF_OPER_STATUS_OPERATIONAL:
+        value->asnValue.number = MIB_IF_ADMIN_STATUS_UP;
+        break;
+    case MIB_IF_OPER_STATUS_CONNECTING:
+    case MIB_IF_OPER_STATUS_CONNECTED:
+        value->asnValue.number = MIB_IF_ADMIN_STATUS_TESTING;
+        break;
+    default:
+        value->asnValue.number = MIB_IF_ADMIN_STATUS_DOWN;
+    };
+}
+
+/* Given an OID and a base OID that it must begin with, finds the item and
+ * integer instance from the OID.  E.g., given an OID foo.1.2 and a base OID
+ * foo, returns item 1 and instance 2.
+ * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is
+ * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME.
+ * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and
+ * instance, or item 1, instance 1 if either is missing.
+ */
+static AsnInteger32 getItemAndIntegerInstanceFromOid(AsnObjectIdentifier *oid,
+    AsnObjectIdentifier *base, BYTE bPduType, UINT *item, UINT *instance)
+{
+    AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR;
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GETNEXT:
+        if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0)
+        {
+            *item = 1;
+            *instance = 1;
+        }
+        else if (!SnmpUtilOidNCmp(oid, base, base->idLength))
+        {
+            if (oid->idLength == base->idLength ||
+                oid->idLength == base->idLength + 1)
+            {
+                /* Either the table or an item within the table is specified,
+                 * but the instance is not.  Get the first instance.
+                 */
+                *instance = 1;
+                if (oid->idLength == base->idLength + 1)
+                    *item = oid->ids[base->idLength];
+                else
+                    *item = 1;
+            }
+            else
+            {
+                *item = oid->ids[base->idLength];
+                *instance = oid->ids[base->idLength + 1] + 1;
+            }
+        }
+        else
+            ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+        break;
+    default:
+        if (!SnmpUtilOidNCmp(oid, base, base->idLength))
+        {
+            if (oid->idLength == base->idLength ||
+                oid->idLength == base->idLength + 1)
+            {
+                /* Either the table or an item within the table is specified,
+                 * but the instance is not.
+                 */
+                ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+            }
+            else
+            {
+                *item = oid->ids[base->idLength];
+                *instance = oid->ids[base->idLength + 1];
+            }
+        }
+        else
+            ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return ret;
+}
+
+/* Given an OID and a base OID that it must begin with, finds the item from the
+ * OID.  E.g., given an OID foo.1 and a base OID foo, returns item 1.
+ * If bPduType is not SNMP_PDU_GETNEXT and the item is missing, returns
+ * SNMP_ERRORSTATUS_NOSUCHNAME.
+ * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item, or item
+ * 1 if the item is missing.
+ */
+static AsnInteger32 getItemFromOid(AsnObjectIdentifier *oid,
+    AsnObjectIdentifier *base, BYTE bPduType, UINT *item)
+{
+    AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR;
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GETNEXT:
+        if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0)
+            *item = 1;
+        else if (!SnmpUtilOidNCmp(oid, base, base->idLength))
+        {
+            if (oid->idLength == base->idLength)
+            {
+                /* The item is missing, assume the first item */
+                *item = 1;
+            }
+            else
+                *item = oid->ids[base->idLength] + 1;
+        }
+        else
+            ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+        break;
+    default:
+        if (!SnmpUtilOidNCmp(oid, base, base->idLength))
+        {
+            if (oid->idLength == base->idLength)
+            {
+                /* The item is missing */
+                ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+            }
+            else
+            {
+                *item = oid->ids[base->idLength];
+                if (!*item)
+                    ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+            }
+        }
+        else
+            ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return ret;
+}
+
+struct GenericTable
+{
+    DWORD numEntries;
+    BYTE  entries[1];
+};
+
+static DWORD oidToIpAddr(AsnObjectIdentifier *oid)
+{
+    assert(oid && oid->idLength >= 4);
+    /* Map the IDs to an IP address in little-endian order */
+    return (BYTE)oid->ids[3] << 24 | (BYTE)oid->ids[2] << 16 |
+        (BYTE)oid->ids[1] << 8 | (BYTE)oid->ids[0];
+}
+
+typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst);
+typedef int (*compareFunc)(const void *key, const void *value);
+
+static UINT findValueInTable(AsnObjectIdentifier *oid,
+    struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey,
+    compareFunc compare)
+{
+    UINT index = 0;
+    void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize);
+
+    if (key)
+    {
+        void *value;
+
+        makeKey(oid, key);
+        value = bsearch(key, table->entries, table->numEntries, tableEntrySize,
+            compare);
+        if (value)
+            index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize
+                + 1;
+        HeapFree(GetProcessHeap(), 0, key);
+    }
+    return index;
+}
+
+/* Given an OID and a base OID that it must begin with, finds the item and
+ * element of the table whose IP address matches the instance from the OID.
+ * E.g., given an OID foo.1.2.3.4.5 and a base OID foo, returns item 1 and the
+ * index of the entry in the table whose IP address is 2.3.4.5.
+ * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is
+ * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME.
+ * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and
+ * instance, or item 1, instance 1 if either is missing.
+ */
+static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid,
+    AsnObjectIdentifier *base, BYTE bPduType, struct GenericTable *table,
+    size_t tableEntrySize, oidToKeyFunc makeKey, compareFunc compare,
+    UINT *item, UINT *instance)
+{
+    AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR;
+
+    if (!table)
+        return SNMP_ERRORSTATUS_NOSUCHNAME;
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GETNEXT:
+        if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0)
+        {
+            /* Return the first item and instance from the table */
+            *item = 1;
+            *instance = 1;
+        }
+        else if (!SnmpUtilOidNCmp(oid, base, base->idLength) &&
+            oid->idLength < base->idLength + 5)
+        {
+            /* Either the table or an item is specified, but the instance is
+             * not.
+             */
+            *instance = 1;
+            if (oid->idLength >= base->idLength + 1)
+            {
+                *item = oid->ids[base->idLength];
+                if (!*item)
+                    *item = 1;
+            }
+            else
+                *item = 1;
+        }
+        else if (!SnmpUtilOidNCmp(oid, base, base->idLength) &&
+            oid->idLength == base->idLength + 5)
+        {
+            *item = oid->ids[base->idLength];
+            if (!*item)
+            {
+                *instance = 1;
+                *item = 1;
+            }
+            else
+            {
+                AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1
+                    };
+
+                *instance = findValueInTable(&ipOid, table, tableEntrySize,
+                    makeKey, compare) + 1;
+                if (*instance > table->numEntries)
+                    ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+            }
+        }
+        else
+            ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+        break;
+    default:
+        if (!SnmpUtilOidNCmp(oid, base, base->idLength) &&
+            oid->idLength == base->idLength + 5)
+        {
+            *item = oid->ids[base->idLength];
+            if (!*item)
+                ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+            else
+            {
+                AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1
+                    };
+
+                *instance = findValueInTable(&ipOid, table, tableEntrySize,
+                    makeKey, compare);
+                if (!*instance)
+                    ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+            }
+        }
+        else
+            ret = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return ret;
+}
+
+static void setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base,
+    UINT item)
+{
+    UINT id;
+    AsnObjectIdentifier oid;
+
+    SnmpUtilOidCpy(dst, base);
+    oid.idLength = 1;
+    oid.ids = &id;
+    id = item;
+    SnmpUtilOidAppend(dst, &oid);
+}
+
+static void setOidWithItemAndIpAddr(AsnObjectIdentifier *dst,
+    AsnObjectIdentifier *base, UINT item, DWORD addr)
+{
+    UINT id;
+    BYTE *ptr;
+    AsnObjectIdentifier oid;
+
+    setOidWithItem(dst, base, item);
+    oid.idLength = 1;
+    oid.ids = &id;
+    for (ptr = (BYTE *)&addr; ptr < (BYTE *)&addr + sizeof(DWORD); ptr++)
+    {
+        id = *ptr;
+        SnmpUtilOidAppend(dst, &oid);
+    }
+}
+
+static void setOidWithItemAndInteger(AsnObjectIdentifier *dst,
+    AsnObjectIdentifier *base, UINT item, UINT instance)
+{
+    AsnObjectIdentifier oid;
+
+    setOidWithItem(dst, base, item);
+    oid.idLength = 1;
+    oid.ids = &instance;
+    SnmpUtilOidAppend(dst, &oid);
+}
+
+static struct structToAsnValue mib2IfEntryMap[] = {
+    { FIELD_OFFSET(MIB_IFROW, dwIndex), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwDescrLen), copyLengthPrecededString },
+    { FIELD_OFFSET(MIB_IFROW, dwType), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwMtu), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwSpeed), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwPhysAddrLen), copyLengthPrecededString },
+    { FIELD_OFFSET(MIB_IFROW, dwAdminStatus), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwOperStatus), copyOperStatus },
+    { FIELD_OFFSET(MIB_IFROW, dwLastChange), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwInOctets), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwInUcastPkts), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwInNUcastPkts), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwInDiscards), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwInErrors), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwInUnknownProtos), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwOutOctets), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwOutUcastPkts), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwOutNUcastPkts), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwOutDiscards), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwOutErrors), copyInt },
+    { FIELD_OFFSET(MIB_IFROW, dwOutQLen), copyInt },
+};
+
+static UINT mib2IfEntry[] = { 1,3,6,1,2,1,2,2,1 };
+
+static BOOL mib2IfEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier entryOid = DEFINE_OID(mib2IfEntry);
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        if (!ifTable)
+        {
+            /* There is no interface present, so let the caller deal
+             * with finding the successor.
+             */
+            *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+        }
+        else
+        {
+            UINT tableIndex = 0, item = 0;
+
+            *pErrorStatus = getItemAndIntegerInstanceFromOid(&pVarBind->name,
+                &entryOid, bPduType, &item, &tableIndex);
+            if (!*pErrorStatus)
+            {
+                assert(tableIndex);
+                assert(item);
+                if (tableIndex > ifTable->dwNumEntries)
+                    *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+                else
+                {
+                    *pErrorStatus = mapStructEntryToValue(mib2IfEntryMap,
+                        DEFINE_SIZEOF(mib2IfEntryMap),
+                        &ifTable->table[tableIndex - 1], item, bPduType,
+                        pVarBind);
+                    if (bPduType == SNMP_PDU_GETNEXT)
+                        setOidWithItemAndInteger(&pVarBind->name, &entryOid,
+                            item, tableIndex);
+                }
+            }
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static UINT mib2Ip[] = { 1,3,6,1,2,1,4 };
+static MIB_IPSTATS ipStats;
+
+static void mib2IpStatsInit(void)
+{
+    GetIpStatistics(&ipStats);
+}
+
+static struct structToAsnValue mib2IpMap[] = {
+    { FIELD_OFFSET(MIB_IPSTATS, dwForwarding), copyInt }, /* 1 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwDefaultTTL), copyInt }, /* 2 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwInReceives), copyInt }, /* 3 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwInHdrErrors), copyInt }, /* 4 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwInAddrErrors), copyInt }, /* 5 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwForwDatagrams), copyInt }, /* 6 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwInUnknownProtos), copyInt }, /* 7 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwInDiscards), copyInt }, /* 8 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwInDelivers), copyInt }, /* 9 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwOutRequests), copyInt }, /* 10 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwOutDiscards), copyInt }, /* 11 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwOutNoRoutes), copyInt }, /* 12 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwReasmTimeout), copyInt }, /* 13 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwReasmReqds), copyInt }, /* 14 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwReasmOks), copyInt }, /* 15 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwReasmFails), copyInt }, /* 16 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwFragOks), copyInt }, /* 17 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwFragFails), copyInt }, /* 18 */
+    { FIELD_OFFSET(MIB_IPSTATS, dwFragCreates), copyInt }, /* 19 */
+    { 0, NULL }, /* 20: not used, IP addr table */
+    { 0, NULL }, /* 21: not used, route table */
+    { 0, NULL }, /* 22: not used, net to media (ARP) table */
+    { FIELD_OFFSET(MIB_IPSTATS, dwRoutingDiscards), copyInt }, /* 23 */
+};
+
+static BOOL mib2IpStatsQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2Ip);
+    UINT item = 0;
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType,
+            &item);
+        if (!*pErrorStatus)
+        {
+            *pErrorStatus = mapStructEntryToValue(mib2IpMap,
+                DEFINE_SIZEOF(mib2IpMap), &ipStats, item, bPduType, pVarBind);
+            if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT)
+                setOidWithItem(&pVarBind->name, &myOid, item);
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1 };
+static PMIB_IPADDRTABLE ipAddrTable;
+
+static struct structToAsnValue mib2IpAddrMap[] = {
+    { FIELD_OFFSET(MIB_IPADDRROW, dwAddr), copyIpAddr },
+    { FIELD_OFFSET(MIB_IPADDRROW, dwIndex), copyInt },
+    { FIELD_OFFSET(MIB_IPADDRROW, dwMask), copyIpAddr },
+    { FIELD_OFFSET(MIB_IPADDRROW, dwBCastAddr), copyInt },
+    { FIELD_OFFSET(MIB_IPADDRROW, dwReasmSize), copyInt },
+};
+
+static void mib2IpAddrInit(void)
+{
+    DWORD size = 0, ret = GetIpAddrTable(NULL, &size, TRUE);
+
+    if (ret == ERROR_INSUFFICIENT_BUFFER)
+    {
+        ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size);
+        if (ipAddrTable)
+            GetIpAddrTable(ipAddrTable, &size, TRUE);
+    }
+}
+
+static void oidToIpAddrRow(AsnObjectIdentifier *oid, void *dst)
+{
+    MIB_IPADDRROW *row = dst;
+
+    row->dwAddr = oidToIpAddr(oid);
+}
+
+static int compareIpAddrRow(const void *a, const void *b)
+{
+    const MIB_IPADDRROW *key = a, *value = b;
+
+    return key->dwAddr - value->dwAddr;
+}
+
+static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2IpAddr);
+    UINT tableIndex = 0, item = 0;
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name,
+            &myOid, bPduType, (struct GenericTable *)ipAddrTable,
+            sizeof(MIB_IPADDRROW), oidToIpAddrRow, compareIpAddrRow, &item,
+            &tableIndex);
+        if (!*pErrorStatus)
+        {
+            assert(tableIndex);
+            assert(item);
+            *pErrorStatus = mapStructEntryToValue(mib2IpAddrMap,
+                DEFINE_SIZEOF(mib2IpAddrMap),
+                &ipAddrTable->table[tableIndex - 1], item, bPduType, pVarBind);
+            if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT)
+                setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item,
+                    ipAddrTable->table[tableIndex - 1].dwAddr);
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static UINT mib2IpRoute[] = { 1,3,6,1,2,1,4,21,1 };
+static PMIB_IPFORWARDTABLE ipRouteTable;
+
+static struct structToAsnValue mib2IpRouteMap[] = {
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardDest), copyIpAddr },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardIfIndex), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric1), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric2), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric3), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric4), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardNextHop), copyIpAddr },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardType), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardProto), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardAge), copyInt },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMask), copyIpAddr },
+    { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric5), copyInt },
+};
+
+static void mib2IpRouteInit(void)
+{
+    DWORD size = 0, ret = GetIpForwardTable(NULL, &size, TRUE);
+
+    if (ret == ERROR_INSUFFICIENT_BUFFER)
+    {
+        ipRouteTable = HeapAlloc(GetProcessHeap(), 0, size);
+        if (ipRouteTable)
+            GetIpForwardTable(ipRouteTable, &size, TRUE);
+    }
+}
+
+static void oidToIpForwardRow(AsnObjectIdentifier *oid, void *dst)
+{
+    MIB_IPFORWARDROW *row = dst;
+
+    row->dwForwardDest = oidToIpAddr(oid);
+}
+
+static int compareIpForwardRow(const void *a, const void *b)
+{
+    const MIB_IPFORWARDROW *key = a, *value = b;
+
+    return key->dwForwardDest - value->dwForwardDest;
+}
+
+static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2IpRoute);
+    UINT tableIndex = 0, item = 0;
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name,
+            &myOid, bPduType, (struct GenericTable *)ipRouteTable,
+            sizeof(MIB_IPFORWARDROW), oidToIpForwardRow, compareIpForwardRow,
+            &item, &tableIndex);
+        if (!*pErrorStatus)
+        {
+            assert(tableIndex);
+            assert(item);
+            *pErrorStatus = mapStructEntryToValue(mib2IpRouteMap,
+                DEFINE_SIZEOF(mib2IpRouteMap),
+                &ipRouteTable->table[tableIndex - 1], item, bPduType, pVarBind);
+            if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT)
+                setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item,
+                    ipRouteTable->table[tableIndex - 1].dwForwardDest);
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static UINT mib2IpNet[] = { 1,3,6,1,2,1,4,22,1 };
+static PMIB_IPNETTABLE ipNetTable;
+
+static struct structToAsnValue mib2IpNetMap[] = {
+    { FIELD_OFFSET(MIB_IPNETROW, dwIndex), copyInt },
+    { FIELD_OFFSET(MIB_IPNETROW, dwPhysAddrLen), copyLengthPrecededString },
+    { FIELD_OFFSET(MIB_IPNETROW, dwAddr), copyIpAddr },
+    { FIELD_OFFSET(MIB_IPNETROW, dwType), copyInt },
+};
+
+static void mib2IpNetInit(void)
+{
+    DWORD size = 0, ret = GetIpNetTable(NULL, &size, FALSE);
+
+    if (ret == ERROR_INSUFFICIENT_BUFFER)
+    {
+        ipNetTable = HeapAlloc(GetProcessHeap(), 0, size);
+        if (ipNetTable)
+            GetIpNetTable(ipNetTable, &size, FALSE);
+    }
+}
+
+static BOOL mib2IpNetQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2IpNet);
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        if (!ipNetTable)
+            *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+        else
+        {
+            UINT tableIndex = 0, item = 0;
+
+            *pErrorStatus = getItemAndIntegerInstanceFromOid(&pVarBind->name,
+                &myOid, bPduType, &item, &tableIndex);
+            if (!*pErrorStatus)
+            {
+                assert(tableIndex);
+                assert(item);
+                if (tableIndex > ipNetTable->dwNumEntries)
+                    *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+                else
+                {
+                    *pErrorStatus = mapStructEntryToValue(mib2IpNetMap,
+                        DEFINE_SIZEOF(mib2IpNetMap),
+                        &ipNetTable[tableIndex - 1], item, bPduType, pVarBind);
+                    if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT)
+                        setOidWithItemAndInteger(&pVarBind->name, &myOid, item,
+                            tableIndex);
+                }
+            }
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static UINT mib2Icmp[] = { 1,3,6,1,2,1,5 };
+static MIB_ICMP icmpStats;
+
+static void mib2IcmpInit(void)
+{
+    GetIcmpStatistics(&icmpStats);
+}
+
+static struct structToAsnValue mib2IcmpMap[] = {
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwMsgs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwErrors), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwDestUnreachs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimeExcds), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwParmProbs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwSrcQuenchs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwRedirects), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwEchos), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwEchoReps), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimestamps), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimestampReps), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwAddrMasks), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwAddrMaskReps), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwMsgs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwErrors), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwDestUnreachs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimeExcds), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwParmProbs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwSrcQuenchs), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwRedirects), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwEchos), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwEchoReps), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimestamps), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimestampReps), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwAddrMasks), copyInt },
+    { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwAddrMaskReps), copyInt },
+};
+
+static BOOL mib2IcmpQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2Icmp);
+    UINT item = 0;
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType,
+            &item);
+        if (!*pErrorStatus)
+        {
+            *pErrorStatus = mapStructEntryToValue(mib2IcmpMap,
+                DEFINE_SIZEOF(mib2IcmpMap), &icmpStats, item, bPduType,
+                pVarBind);
+            if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT)
+                setOidWithItem(&pVarBind->name, &myOid, item);
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static UINT mib2Tcp[] = { 1,3,6,1,2,1,6 };
+static MIB_TCPSTATS tcpStats;
+
+static void mib2TcpInit(void)
+{
+    GetTcpStatistics(&tcpStats);
+}
+
+static struct structToAsnValue mib2TcpMap[] = {
+    { FIELD_OFFSET(MIB_TCPSTATS, dwRtoAlgorithm), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwRtoMin), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwRtoMax), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwMaxConn), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwActiveOpens), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwPassiveOpens), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwAttemptFails), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwEstabResets), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwCurrEstab), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwInSegs), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwOutSegs), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwRetransSegs), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwInErrs), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwOutRsts), copyInt },
+    { FIELD_OFFSET(MIB_TCPSTATS, dwNumConns), copyInt },
+};
+
+static BOOL mib2TcpQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2Tcp);
+    UINT item = 0;
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType,
+            &item);
+        if (!*pErrorStatus)
+        {
+            *pErrorStatus = mapStructEntryToValue(mib2TcpMap,
+                DEFINE_SIZEOF(mib2TcpMap), &tcpStats, item, bPduType, pVarBind);
+            if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT)
+                setOidWithItem(&pVarBind->name, &myOid, item);
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+static UINT mib2Udp[] = { 1,3,6,1,2,1,7 };
+static MIB_UDPSTATS udpStats;
+
+static void mib2UdpInit(void)
+{
+    GetUdpStatistics(&udpStats);
+}
+
+static struct structToAsnValue mib2UdpMap[] = {
+    { FIELD_OFFSET(MIB_UDPSTATS, dwInDatagrams), copyInt },
+    { FIELD_OFFSET(MIB_UDPSTATS, dwNoPorts), copyInt },
+    { FIELD_OFFSET(MIB_UDPSTATS, dwInErrors), copyInt },
+    { FIELD_OFFSET(MIB_UDPSTATS, dwOutDatagrams), copyInt },
+};
+
+static BOOL mib2UdpQuery(BYTE bPduType, SnmpVarBind *pVarBind,
+    AsnInteger32 *pErrorStatus)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2Udp);
+    UINT item;
+
+    TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name),
+        pErrorStatus);
+
+    switch (bPduType)
+    {
+    case SNMP_PDU_GET:
+    case SNMP_PDU_GETNEXT:
+        *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType,
+            &item);
+        if (!*pErrorStatus)
+        {
+            *pErrorStatus = mapStructEntryToValue(mib2UdpMap,
+                DEFINE_SIZEOF(mib2UdpMap), &udpStats, item, bPduType, pVarBind);
+            if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT)
+                setOidWithItem(&pVarBind->name, &myOid, item);
+        }
+        break;
+    case SNMP_PDU_SET:
+        *pErrorStatus = SNMP_ERRORSTATUS_READONLY;
+        break;
+    default:
+        FIXME("0x%02x: unsupported PDU type\n", bPduType);
+        *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
+    }
+    return TRUE;
+}
+
+/* This list MUST BE lexicographically sorted */
+static struct mibImplementation supportedIDs[] = {
+    { DEFINE_OID(mib2IfNumber), mib2IfNumberInit, mib2IfNumberQuery },
+    { DEFINE_OID(mib2IfEntry), NULL, mib2IfEntryQuery },
+    { DEFINE_OID(mib2Ip), mib2IpStatsInit, mib2IpStatsQuery },
+    { DEFINE_OID(mib2IpAddr), mib2IpAddrInit, mib2IpAddrQuery },
+    { DEFINE_OID(mib2IpRoute), mib2IpRouteInit, mib2IpRouteQuery },
+    { DEFINE_OID(mib2IpNet), mib2IpNetInit, mib2IpNetQuery },
+    { DEFINE_OID(mib2Icmp), mib2IcmpInit, mib2IcmpQuery },
+    { DEFINE_OID(mib2Tcp), mib2TcpInit, mib2TcpQuery },
+    { DEFINE_OID(mib2Udp), mib2UdpInit, mib2UdpQuery },
+};
+static UINT minSupportedIDLength;
+
+BOOL WINAPI SnmpExtensionInit(DWORD dwUptimeReference,
+    HANDLE *phSubagentTrapEvent, AsnObjectIdentifier *pFirstSupportedRegion)
+{
+    AsnObjectIdentifier myOid = DEFINE_OID(mib2System);
+    UINT i;
+
+    TRACE("(%d, %p, %p)\n", dwUptimeReference, phSubagentTrapEvent,
+        pFirstSupportedRegion);
+
+    minSupportedIDLength = UINT_MAX;
+    for (i = 0; i < sizeof(supportedIDs) / sizeof(supportedIDs[0]); i++)
+    {
+        if (supportedIDs[i].init)
+            supportedIDs[i].init();
+        if (supportedIDs[i].name.idLength < minSupportedIDLength)
+            minSupportedIDLength = supportedIDs[i].name.idLength;
+    }
+    *phSubagentTrapEvent = NULL;
+    SnmpUtilOidCpy(pFirstSupportedRegion, &myOid);
+    return TRUE;
+}
+
+static struct mibImplementation *findSupportedQuery(UINT *ids, UINT idLength,
+    UINT *matchingIndex)
+{
+    int indexHigh = DEFINE_SIZEOF(supportedIDs) - 1, indexLow = 0, i;
+    struct mibImplementation *impl = NULL;
+    AsnObjectIdentifier oid1 = { idLength, ids};
+
+    if (!idLength)
+        return NULL;
+    for (i = (indexLow + indexHigh) / 2; !impl && indexLow <= indexHigh;
+         i = (indexLow + indexHigh) / 2)
+    {
+        INT cmp;
+
+        cmp = SnmpUtilOidNCmp(&oid1, &supportedIDs[i].name, idLength);
+        if (!cmp)
+        {
+            impl = &supportedIDs[i];
+            *matchingIndex = i;
+        }
+        else if (cmp > 0)
+            indexLow = i + 1;
+        else
+            indexHigh = i - 1;
+    }
+    return impl;
+}
+
+BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList,
+    AsnInteger32 *pErrorStatus, AsnInteger32 *pErrorIndex)
+{
+    AsnObjectIdentifier mib2oid = DEFINE_OID(mib2);
+    AsnInteger32 error = SNMP_ERRORSTATUS_NOERROR, errorIndex = 0;
+    UINT i;
+
+    TRACE("(0x%02x, %p, %p, %p)\n", bPduType, pVarBindList,
+        pErrorStatus, pErrorIndex);
+
+    for (i = 0; !error && i < pVarBindList->len; i++)
+    {
+        /* Ignore any OIDs not in MIB2 */
+        if (!SnmpUtilOidNCmp(&pVarBindList->list[i].name, &mib2oid,
+            mib2oid.idLength))
+        {
+            struct mibImplementation *impl = NULL;
+            UINT len, matchingIndex = 0;
+
+            TRACE("%s\n", SnmpUtilOidToA(&pVarBindList->list[i].name));
+            /* Search for an implementation matching as many octets as possible
+             */
+            for (len = pVarBindList->list[i].name.idLength;
+                len >= minSupportedIDLength && !impl; len--)
+                impl = findSupportedQuery(pVarBindList->list[i].name.ids, len,
+                    &matchingIndex);
+            if (impl && impl->query)
+                impl->query(bPduType, &pVarBindList->list[i], &error);
+            else
+                error = SNMP_ERRORSTATUS_NOSUCHNAME;
+            if (error == SNMP_ERRORSTATUS_NOSUCHNAME &&
+                bPduType == SNMP_PDU_GETNEXT)
+            {
+                /* GetNext is special: it finds the successor to the given OID,
+                 * so we have to continue until an implementation handles the
+                 * query or we exhaust the table of supported OIDs.
+                 */
+                for (; error == SNMP_ERRORSTATUS_NOSUCHNAME &&
+                    matchingIndex < DEFINE_SIZEOF(supportedIDs);
+                    matchingIndex++)
+                {
+                    error = SNMP_ERRORSTATUS_NOERROR;
+                    impl = &supportedIDs[matchingIndex];
+                    if (impl->query)
+                        impl->query(bPduType, &pVarBindList->list[i], &error);
+                    else
+                        error = SNMP_ERRORSTATUS_NOSUCHNAME;
+                }
+                /* If the query still isn't resolved, set the OID to the
+                 * successor to the last entry in the table.
+                 */
+                if (error == SNMP_ERRORSTATUS_NOSUCHNAME)
+                {
+                    SnmpUtilOidFree(&pVarBindList->list[i].name);
+                    SnmpUtilOidCpy(&pVarBindList->list[i].name,
+                        &supportedIDs[matchingIndex - 1].name);
+                    pVarBindList->list[i].name.ids[
+                        pVarBindList->list[i].name.idLength - 1] += 1;
+                }
+            }
+            if (error)
+                errorIndex = i + 1;
+        }
+    }
+    *pErrorStatus = error;
+    *pErrorIndex = errorIndex;
+    return TRUE;
+}

Propchange: trunk/reactos/dll/win32/inetmib1/main.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/win32/snmpapi/snmpapi.def
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/snmpapi/snmpapi.def?rev=34130&r1=34129&r2=34130&view=diff
==============================================================================
--- trunk/reactos/dll/win32/snmpapi/snmpapi.def [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/snmpapi/snmpapi.def [iso-8859-1] Fri Jun 27 12:08:01 2008
@@ -14,7 +14,7 @@
 SnmpTfxOpen
 SnmpTfxQuery
 SnmpUtilAnsiToUnicode
-SnmpUtilAsnAnyCpy
+SnmpUtilAsnAnyCpy at 8
 SnmpUtilAsnAnyFree
 SnmpUtilDbgPrint
 SnmpUtilIdsToA
@@ -25,12 +25,12 @@
 SnmpUtilOctetsCpy
 SnmpUtilOctetsFree
 SnmpUtilOctetsNCmp
-SnmpUtilOidAppend
+SnmpUtilOidAppend at 8
 SnmpUtilOidCmp
-SnmpUtilOidCpy
-SnmpUtilOidFree
-SnmpUtilOidNCmp
-SnmpUtilOidToA
+SnmpUtilOidCpy at 8
+SnmpUtilOidFree at 4
+SnmpUtilOidNCmp at 12
+SnmpUtilOidToA at 4
 SnmpUtilPrintAsnAny
 SnmpUtilPrintOid
 SnmpUtilUTF8ToUnicode

Modified: trunk/reactos/dll/win32/win32.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/win32.rbuild?rev=34130&r1=34129&r2=34130&view=diff
==============================================================================
--- trunk/reactos/dll/win32/win32.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/win32.rbuild [iso-8859-1] Fri Jun 27 12:08:01 2008
@@ -115,6 +115,9 @@
 <directory name="inetcomm">
 	<xi:include href="inetcomm/inetcomm.rbuild" />
 </directory>
+<directory name="inetmib1">
+	<xi:include href="inetmib1/inetmib1.rbuild" />
+</directory>
 <directory name="iphlpapi">
 	<xi:include href="iphlpapi/iphlpapi.rbuild" />
 </directory>



More information about the Ros-diffs mailing list