/*++
*******************************************************************************
* Copyright (c) 1990-97 Digi International Inc., All Rights Reserved				*
* 																										*
* This software contains proprietary and confidential information of Digi		*
* International Inc.  By accepting transfer of this copy, Recipient agrees		*
* to retain this software in confidence, to prevent disclosure to others,		*
* and to make no use of this software other than that for which it was			*
* delivered.  This is an unpublished copyrighted work of Digi International	*
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly	*
* prohibited.																						*
* 																										*
* Restricted Rights Legend																		*
*																										*
* Use, duplication, or disclosure by the Government is subject to					*
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in			*
* Technical Data and Computer Software clause at DFARS 252.227-7031 or			*
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -				*
* Restricted Rights at 48 CFR 52.227-19, as applicable.								*
*																										*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343				*
*																										*
*******************************************************************************

Module Name:

   rs232mib.c

Abstract:

    Physical Layer MIB SNMP Extension Agent for Windows NT.

    These files (rs232dll.c, rs232mib.c, and rs232mib.h) provide an 
    Extension Agent DLL which works in conjunction with the SNMP 
    Extendible Agent for Windows NT.

    This SNMP Extension Agent was derived from the sample on the Microsoft
    Developer's Toolkit. See the "Microsoft Windows/NT SNMP Programmer's Reference".

    This Extension Agent implements the Internet RS232 MIB. It's definition is 
    found in the IETF RFC 1317.

Author:

   Carl Caldwell

Revision History:

   $History: rs232mib.c $
 * 
 * *****************  Version 19  *****************
 * User: Mikez        Date: 7/08/97    Time: 9:48a
 * Updated in $/Components/Windows/NT/Sync/SxbSnmp/physical
 * Updated to support DStreams API.

--*/
#include <snmp.h>
#include "rs232mib.h"
#include "rs232sxb.h"
#include "regnames.h"
#include "dxbreg.h"

// Buffer for formatted Debug messages
char	DbgBuf[80];

// Termination event handle
extern HANDLE	terminateEvent;

// Handle used to control the data acquisition thread
extern HANDLE hSxbCollectionThread;

// Global Var that tells how many ports we are dealing with
AsnInteger portCount;

//Global var to shut down data collection
BOOL	done = FALSE;

// If an addition or deletion to the MIB is necessary, there are several
// places in the code that must be checked and possibly changed.
//
// The last field in each MIB entry is used to point to the NEXT
// leaf variable.  If an addition or deletetion is made, these pointers
// may need to be updated to reflect the modification.

// The prefix to all of these MIB variables is 1.3.6.1.2.1.10
// {.iso.org.dod.internet.mgmt.mib.transmission.rs232
UINT OID_Prefix[] = { 1, 3, 6, 1, 2, 1, 10, 33 };
AsnObjectIdentifier MIB_OidPrefix = { OID_SIZEOF(OID_Prefix), OID_Prefix };

//                         //
// OID definitions for MIB //
//                         //
// Definition of the RS232 group

UINT MIB_rs232[]  = { 33 };

// Definition of leaf variables under the RS232 group
// All leaf variables have a zero appended to their OID to indicate
// that it is the only instance of this variable and it exists.

UINT MIB_rs232Number[]              = { 1, 0 };

// The following definitions are those of the port table
// These entries are a little different in that they indicate
// The presence of the first configured port. If no ports are 
// configured, the DLL will fail to initialize. If more than one 
// port exists, they will be added during initialization by chaining
// columnwise to the previous port (i.e. port index 2 is the NEXT 
// MIB entry after port index 1, and port type 1 is the next MIB 
// entry after port index 2

UINT MIB_rs232PortIndex[]           = { 2, 1, 1, 1 };
UINT MIB_rs232PortType[]            = { 2, 1, 2, 1 };
UINT MIB_rs232PortInSigNumber[]     = { 2, 1, 3, 1 };
UINT MIB_rs232PortOutSigNumber[]    = { 2, 1, 4, 1 };
UINT MIB_rs232PortInSpeed[]         = { 2, 1, 5, 1 };
UINT MIB_rs232PortOutSpeed[]        = { 2, 1, 6, 1 };

// The following definitions are those of the sync port table
// These entries are different, as well,  in that they indicate
// The presence of the first configured port. If no ports are 
// configured, the DLL will fail to initialize. If more than one 
// port exists, they will be added during initialization by chaining
// columnwise as described above.

UINT MIB_rs232SyncPortIndex[]           = { 4, 1, 1, 1 };
UINT MIB_rs232SyncPortClockSource[]     = { 4, 1, 2, 1 };
UINT MIB_rs232SyncPortFrameChkErrs[]    = { 4, 1, 3, 1 };
UINT MIB_rs232SyncPortXmtUrunErrs[]     = { 4, 1, 4, 1 };
UINT MIB_rs232SyncPortRcvOrunErrs[]     = { 4, 1, 5, 1 };
UINT MIB_rs232SyncPortIntFrames[]       = { 4, 1, 6, 1 };
UINT MIB_rs232SyncPortAbortFrames[]     = { 4, 1, 7, 1 };

// The following definitions are those of the sync port input signal table
// These entries are different, as well. This table is a 2 dimensional 
// array based off port and signal name. The signals will be chained 
// columnwise; the first ports' signals, to the second. If no ports are
// configured, the DLL will fail to initialize. If more than one 
// port exists, they will be added during initialization by chaining
// columnwise as described above.

UINT MIB_rs232InSigPortIndex[]          = { 5, 1, 1, 1 };

UINT MIB_rs232InSigNameRts[]            = { 5, 1, 2, 1, 1 };
UINT MIB_rs232InSigNameCts[]            = { 5, 1, 2, 1, 2 };
UINT MIB_rs232InSigNameDsr[]            = { 5, 1, 2, 1, 3 };
UINT MIB_rs232InSigNameDtr[]            = { 5, 1, 2, 1, 4 };
UINT MIB_rs232InSigNameRi[]             = { 5, 1, 2, 1, 5 };
UINT MIB_rs232InSigNameDcd[]            = { 5, 1, 2, 1, 6 };

UINT MIB_rs232InSigStateRts[]           = { 5, 1, 3, 1, 1 };
UINT MIB_rs232InSigStateCts[]           = { 5, 1, 3, 1, 2 };
UINT MIB_rs232InSigStateDsr[]           = { 5, 1, 3, 1, 3 };
UINT MIB_rs232InSigStateDtr[]           = { 5, 1, 3, 1, 4 };
UINT MIB_rs232InSigStateRi[]            = { 5, 1, 3, 1, 5 };
UINT MIB_rs232InSigStateDcd[]           = { 5, 1, 3, 1, 6 };

UINT MIB_rs232InSigChangesRts[]         = { 5, 1, 4, 1, 1 };
UINT MIB_rs232InSigChangesCts[]         = { 5, 1, 4, 1, 2 };
UINT MIB_rs232InSigChangesDsr[]         = { 5, 1, 4, 1, 3 };
UINT MIB_rs232InSigChangesDtr[]         = { 5, 1, 4, 1, 4 };
UINT MIB_rs232InSigChangesRi[]          = { 5, 1, 4, 1, 5 };
UINT MIB_rs232InSigChangesDcd[]         = { 5, 1, 4, 1, 6 };

// The following definitions are those of the sync port output signal table
// These entries are different, as well. This table is a 2 dimensional 
// array based off port and signal name. The signals will be chained 
// columnwise; the first ports' signals, to the second. If no ports are
// configured, the DLL will fail to initialize. If more than one 
// port exists, they will be added during initialization by chaining
// columnwise as described above.

UINT MIB_rs232OutSigPortIndex[]         = { 6, 1, 1, 1 };

UINT MIB_rs232OutSigNameRts[]           = { 6, 1, 2, 1, 1 };
UINT MIB_rs232OutSigNameCts[]           = { 6, 1, 2, 1, 2 };
UINT MIB_rs232OutSigNameDsr[]           = { 6, 1, 2, 1, 3 };
UINT MIB_rs232OutSigNameDtr[]           = { 6, 1, 2, 1, 4 };
UINT MIB_rs232OutSigNameRi[]            = { 6, 1, 2, 1, 5 };
UINT MIB_rs232OutSigNameDcd[]           = { 6, 1, 2, 1, 6 };

UINT MIB_rs232OutSigStateRts[]          = { 6, 1, 3, 1, 1 };
UINT MIB_rs232OutSigStateCts[]          = { 6, 1, 3, 1, 2 };
UINT MIB_rs232OutSigStateDsr[]          = { 6, 1, 3, 1, 3 };
UINT MIB_rs232OutSigStateDtr[]          = { 6, 1, 3, 1, 4 };
UINT MIB_rs232OutSigStateRi[]           = { 6, 1, 3, 1, 5 };
UINT MIB_rs232OutSigStateDcd[]          = { 6, 1, 3, 1, 6 };

UINT MIB_rs232OutSigChangesRts[]        = { 6, 1, 4, 1, 1 };
UINT MIB_rs232OutSigChangesCts[]        = { 6, 1, 4, 1, 2 };
UINT MIB_rs232OutSigChangesDsr[]        = { 6, 1, 4, 1, 3 };
UINT MIB_rs232OutSigChangesDtr[]        = { 6, 1, 4, 1, 4 };
UINT MIB_rs232OutSigChangesRi[]         = { 6, 1, 4, 1, 5 };
UINT MIB_rs232OutSigChangesDcd[]        = { 6, 1, 4, 1, 6 };

//                             //
// Storage definitions for MIB //
//                             //
AsnInteger MIB_rs232NumberStor              = 1;

AsnInteger MIB_rs232PortIndexStor           = 1;
AsnInteger MIB_rs232PortTypeStor            = 1;
AsnInteger MIB_rs232PortInSigNumberStor     = 0;
AsnInteger MIB_rs232PortOutSigNumberStor    = 0;
AsnInteger MIB_rs232PortInSpeedStor         = 56000;
AsnInteger MIB_rs232PortOutSpeedStor        = 56000;

AsnInteger MIB_rs232SyncPortIndexStor        = 1;
AsnInteger MIB_rs232SyncPortClockSourceStor  = 1;
AsnCounter MIB_rs232SyncPortFrameChkErrsStor = 0;
AsnCounter MIB_rs232SyncPortXmtUrunErrsStor  = 0;
AsnCounter MIB_rs232SyncPortRcvOrunErrsStor  = 0;
AsnCounter MIB_rs232SyncPortIntFramesStor    = 0;
AsnCounter MIB_rs232SyncPortAbortFramesStor  = 0;

AsnInteger MIB_rs232InSigPortIndexStor       = 1;
AsnInteger MIB_rs232InSigNameRtsStor         = RS232MIB_SIG_NAME_RTS;
AsnInteger MIB_rs232InSigNameCtsStor         = RS232MIB_SIG_NAME_CTS;
AsnInteger MIB_rs232InSigNameDsrStor         = RS232MIB_SIG_NAME_DSR;
AsnInteger MIB_rs232InSigNameDtrStor         = RS232MIB_SIG_NAME_DTR;
AsnInteger MIB_rs232InSigNameRiStor          = RS232MIB_SIG_NAME_RI;
AsnInteger MIB_rs232InSigNameDcdStor         = RS232MIB_SIG_NAME_DCD;

AsnInteger MIB_rs232InSigStateRtsStor        = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232InSigStateCtsStor        = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232InSigStateDsrStor        = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232InSigStateDtrStor        = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232InSigStateRiStor         = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232InSigStateDcdStor        = RS232MIB_SIG_STATE_NONE;

AsnCounter MIB_rs232InSigChangesRtsStor      = 0;
AsnCounter MIB_rs232InSigChangesCtsStor      = 0;
AsnCounter MIB_rs232InSigChangesDsrStor      = 0;
AsnCounter MIB_rs232InSigChangesDtrStor      = 0;
AsnCounter MIB_rs232InSigChangesRiStor       = 0;
AsnCounter MIB_rs232InSigChangesDcdStor      = 0;

AsnInteger MIB_rs232OutSigPortIndexStor      = 1;

AsnInteger MIB_rs232OutSigNameRtsStor        = RS232MIB_SIG_NAME_RTS;
AsnInteger MIB_rs232OutSigNameCtsStor        = RS232MIB_SIG_NAME_CTS;
AsnInteger MIB_rs232OutSigNameDsrStor        = RS232MIB_SIG_NAME_DSR;
AsnInteger MIB_rs232OutSigNameDtrStor        = RS232MIB_SIG_NAME_DTR;
AsnInteger MIB_rs232OutSigNameRiStor         = RS232MIB_SIG_NAME_RI;
AsnInteger MIB_rs232OutSigNameDcdStor        = RS232MIB_SIG_NAME_DCD;

AsnInteger MIB_rs232OutSigStateRtsStor       = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232OutSigStateCtsStor       = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232OutSigStateDsrStor       = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232OutSigStateDtrStor       = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232OutSigStateRiStor        = RS232MIB_SIG_STATE_NONE;
AsnInteger MIB_rs232OutSigStateDcdStor       = RS232MIB_SIG_STATE_NONE;

AsnCounter MIB_rs232OutSigChangesRtsStor     = 0;
AsnCounter MIB_rs232OutSigChangesCtsStor     = 0;
AsnCounter MIB_rs232OutSigChangesDsrStor     = 0;
AsnCounter MIB_rs232OutSigChangesDtrStor     = 0;
AsnCounter MIB_rs232OutSigChangesRiStor      = 0;
AsnCounter MIB_rs232OutSigChangesDcdStor     = 0;


// MIB definiton
MIB_ENTRY Mib[] = {
      { { OID_SIZEOF(MIB_rs232Number), MIB_rs232Number },
    	&MIB_rs232NumberStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[1] },   //Index 0

      { { OID_SIZEOF(MIB_rs232PortIndex), MIB_rs232PortIndex },
    	&MIB_rs232PortIndexStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[2] },   //Index 1

      { { OID_SIZEOF(MIB_rs232PortType), MIB_rs232PortType },
	    &MIB_rs232PortTypeStor, NULL,
		ASN_INTEGER, 
	    MIB_ACCESS_READ, 
		MIB_leaf_func, 
		&Mib[3] },   //Index 2

      { { OID_SIZEOF(MIB_rs232PortInSigNumber), MIB_rs232PortInSigNumber },
	    &MIB_rs232PortInSigNumberStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[4] },   //Index 3

      { { OID_SIZEOF(MIB_rs232PortOutSigNumber), MIB_rs232PortOutSigNumber },
    	&MIB_rs232PortOutSigNumberStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[5] },   //Index 4

      { { OID_SIZEOF(MIB_rs232PortInSpeed), MIB_rs232PortInSpeed },
    	&MIB_rs232PortInSpeedStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READWRITE, 
		MIB_leaf_func, &Mib[6] },   //Index 5
      
      { { OID_SIZEOF(MIB_rs232PortOutSpeed), MIB_rs232PortOutSpeed },
    	&MIB_rs232PortOutSpeedStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READWRITE, 
		MIB_leaf_func, &Mib[7] },   //Index 6
      
      { { OID_SIZEOF(MIB_rs232SyncPortIndex), MIB_rs232SyncPortIndex },
    	&MIB_rs232SyncPortIndexStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[8] },   //Index 7
      
      { { OID_SIZEOF(MIB_rs232SyncPortClockSource), MIB_rs232SyncPortClockSource },
    	&MIB_rs232SyncPortClockSourceStor, NULL, 
		ASN_INTEGER,
	    MIB_ACCESS_READWRITE, 
		MIB_leaf_func, &Mib[9] },   //Index 8
      
      { { OID_SIZEOF(MIB_rs232SyncPortFrameChkErrs), MIB_rs232SyncPortFrameChkErrs},
    	&MIB_rs232SyncPortFrameChkErrsStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[10] },   //Index 9
      
      { { OID_SIZEOF(MIB_rs232SyncPortXmtUrunErrs), MIB_rs232SyncPortXmtUrunErrs},
    	&MIB_rs232SyncPortXmtUrunErrsStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[11] },   //Index 10
      
      { { OID_SIZEOF(MIB_rs232SyncPortRcvOrunErrs), MIB_rs232SyncPortRcvOrunErrs },
	    &MIB_rs232SyncPortRcvOrunErrsStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[12] },   //Index 11
      
      { { OID_SIZEOF(MIB_rs232SyncPortIntFrames), MIB_rs232SyncPortIntFrames },
    	&MIB_rs232SyncPortIntFramesStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[13] },   //Index 12
      
      { { OID_SIZEOF(MIB_rs232SyncPortAbortFrames), MIB_rs232SyncPortAbortFrames },
    	&MIB_rs232SyncPortAbortFramesStor, NULL,
		ASN_RFC1155_COUNTER,
		MIB_ACCESS_READ, 
		MIB_leaf_func, NULL },  //Index 13

		// The mib ends above. Control Signals included for completeness

      { { OID_SIZEOF(MIB_rs232InSigPortIndex), MIB_rs232InSigPortIndex},
    	&MIB_rs232InSigPortIndexStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[15] },  //Index 14

      { { OID_SIZEOF(MIB_rs232InSigNameRts), MIB_rs232InSigNameRts},
    	&MIB_rs232InSigNameRtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[16] },  //Index 15

      { { OID_SIZEOF(MIB_rs232InSigNameCts), MIB_rs232InSigNameCts},
    	&MIB_rs232InSigNameCtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[17] },  //Index 16

      { { OID_SIZEOF(MIB_rs232InSigNameDsr), MIB_rs232InSigNameDsr},
    	&MIB_rs232InSigNameDsrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[18] },  //Index 17

      { { OID_SIZEOF(MIB_rs232InSigNameDtr), MIB_rs232InSigNameDtr},
    	&MIB_rs232InSigNameDtrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[19] },  //Index 18

      { { OID_SIZEOF(MIB_rs232InSigNameRi), MIB_rs232InSigNameRi},
    	&MIB_rs232InSigNameRiStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[20] },  //Index 19

      { { OID_SIZEOF(MIB_rs232InSigNameDcd), MIB_rs232InSigNameDcd},
    	&MIB_rs232InSigNameDcdStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[21] },  //Index 20

      { { OID_SIZEOF(MIB_rs232InSigStateRts), MIB_rs232InSigStateRts},
    	&MIB_rs232InSigStateRtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[22] },  //Index 21

      { { OID_SIZEOF(MIB_rs232InSigStateCts), MIB_rs232InSigStateCts},
    	&MIB_rs232InSigStateCtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[23] },  //Index 22

      { { OID_SIZEOF(MIB_rs232InSigStateDsr), MIB_rs232InSigStateDsr},
    	&MIB_rs232InSigStateDsrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[24] },  //Index 23

      { { OID_SIZEOF(MIB_rs232InSigStateDtr), MIB_rs232InSigStateDtr},
    	&MIB_rs232InSigStateDtrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[25] },  //Index 24

      { { OID_SIZEOF(MIB_rs232InSigStateRi), MIB_rs232InSigStateRi},
    	&MIB_rs232InSigStateRiStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[26] },  //Index 25

      { { OID_SIZEOF(MIB_rs232InSigStateDcd), MIB_rs232InSigStateDcd},
    	&MIB_rs232InSigStateDcdStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[27] },  //Index 26

      { { OID_SIZEOF(MIB_rs232InSigChangesRts), MIB_rs232InSigChangesRts},
    	&MIB_rs232InSigChangesRtsStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[28] },  //Index 27

      { { OID_SIZEOF(MIB_rs232InSigChangesCts), MIB_rs232InSigChangesCts},
    	&MIB_rs232InSigChangesCtsStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[29] },  //Index 28

      { { OID_SIZEOF(MIB_rs232InSigChangesDsr), MIB_rs232InSigChangesDsr},
    	&MIB_rs232InSigChangesDsrStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[30] },  //Index 29

      { { OID_SIZEOF(MIB_rs232InSigChangesDtr), MIB_rs232InSigChangesDtr},
    	&MIB_rs232InSigChangesDtrStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[31] },  //Index 30

      { { OID_SIZEOF(MIB_rs232InSigChangesRi), MIB_rs232InSigChangesRi},
    	&MIB_rs232InSigChangesRiStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[32] },  //Index 31

      { { OID_SIZEOF(MIB_rs232InSigChangesDcd), MIB_rs232InSigChangesDcd},
    	&MIB_rs232InSigChangesDcdStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[33] },  //Index 32

      { { OID_SIZEOF(MIB_rs232OutSigPortIndex), MIB_rs232OutSigPortIndex},
    	&MIB_rs232OutSigPortIndexStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[34] },  //Index 33

      { { OID_SIZEOF(MIB_rs232OutSigNameRts), MIB_rs232OutSigNameRts},
    	&MIB_rs232OutSigNameRtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[35] },  //Index 34

      { { OID_SIZEOF(MIB_rs232OutSigNameCts), MIB_rs232OutSigNameCts},
    	&MIB_rs232OutSigNameCtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[36] },  //Index 35

      { { OID_SIZEOF(MIB_rs232OutSigNameDsr), MIB_rs232OutSigNameDsr},
    	&MIB_rs232OutSigNameDsrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[37] },  //Index 36

      { { OID_SIZEOF(MIB_rs232OutSigNameDtr), MIB_rs232OutSigNameDtr},
    	&MIB_rs232OutSigNameDtrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[38] },  //Index 37

      { { OID_SIZEOF(MIB_rs232OutSigNameRi), MIB_rs232OutSigNameRi},
    	&MIB_rs232OutSigNameRiStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[39] },  //Index 38

      { { OID_SIZEOF(MIB_rs232OutSigNameDcd), MIB_rs232OutSigNameDcd},
    	&MIB_rs232OutSigNameDcdStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[40] },  //Index 39

      { { OID_SIZEOF(MIB_rs232OutSigStateRts), MIB_rs232OutSigStateRts},
    	&MIB_rs232OutSigStateRtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[41] },  //Index 40

      { { OID_SIZEOF(MIB_rs232OutSigStateCts), MIB_rs232OutSigStateCts},
    	&MIB_rs232OutSigStateCtsStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[42] },  //Index 41

      { { OID_SIZEOF(MIB_rs232OutSigStateDsr), MIB_rs232OutSigStateDsr},
    	&MIB_rs232OutSigStateDsrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[43] },  //Index 42

      { { OID_SIZEOF(MIB_rs232OutSigStateDtr), MIB_rs232OutSigStateDtr},
    	&MIB_rs232OutSigStateDtrStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[44] },  //Index 43

      { { OID_SIZEOF(MIB_rs232OutSigStateRi), MIB_rs232OutSigStateRi},
    	&MIB_rs232OutSigStateRiStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[45] },  //Index 44

      { { OID_SIZEOF(MIB_rs232OutSigStateDcd), MIB_rs232OutSigStateDcd},
    	&MIB_rs232OutSigStateDcdStor, NULL,
		ASN_INTEGER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[46] },  //Index 45

      { { OID_SIZEOF(MIB_rs232OutSigChangesRts), MIB_rs232OutSigChangesRts},
    	&MIB_rs232OutSigChangesRtsStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[47] },  //Index 46

      { { OID_SIZEOF(MIB_rs232OutSigChangesCts), MIB_rs232OutSigChangesCts},
    	&MIB_rs232OutSigChangesCtsStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[48] },  //Index 47

      { { OID_SIZEOF(MIB_rs232OutSigChangesDsr), MIB_rs232OutSigChangesDsr},
    	&MIB_rs232OutSigChangesDsrStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[49] },  //Index 48

      { { OID_SIZEOF(MIB_rs232OutSigChangesDtr), MIB_rs232OutSigChangesDtr},
    	&MIB_rs232OutSigChangesDtrStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[50] },  //Index 49

      { { OID_SIZEOF(MIB_rs232OutSigChangesRi), MIB_rs232OutSigChangesRi},
    	&MIB_rs232OutSigChangesRiStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, &Mib[51] },  //Index 50

      { { OID_SIZEOF(MIB_rs232OutSigChangesDcd), MIB_rs232OutSigChangesDcd},
    	&MIB_rs232OutSigChangesDcdStor, NULL,
		ASN_RFC1155_COUNTER,
	    MIB_ACCESS_READ, 
		MIB_leaf_func, NULL }       //Index 51
      };

UINT MIB_num_variables = sizeof Mib / sizeof( MIB_ENTRY );

//
// InitMibTableEntries
//    Initializes the Table Entries in a Mib from the registry. The
//    port table is initialized, followed by the sync port table. If
//    control leads were exposed by the driver, the In and Out signal 
//    tables would come next:
//
// Notes:
//    InitInSigTablesMibEntries, and InitOutSigTablesMibEntries
//    Must be added when the SXB driver exposes control leads via the
//    Ioctl Interface.
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT InitMibTableEntries(IN OUT PWAN_SXB_INFO pWanInfo)
{
UINT            initStatus;
    // Initialize the four MIB elements
    initStatus = InitPortTableMibEntries(Mib, pWanInfo);
    if (!initStatus)
    { 
	    initStatus = InitSyncPortTableMibEntries(Mib, pWanInfo);
	    if (!initStatus)
	    {
			initStatus = InitInSigTableMibEntries(Mib, pWanInfo);
		    if (!initStatus)
		    {
				initStatus = InitOutSigTableMibEntries(Mib, pWanInfo);
		    }
	    }
    }
    return initStatus;
}    

//
// InitPortTableMibEntries
//    Initializes the Port Table Entries in the Mib from the registry.
//    The port table is initialized by appending columns to the vector
//    of port specfic Mib entries. In the initial data structuring stage,
//    The first port table entry (port index) links to the second entry.
//    This will be the case when only one port is active. However, when 
//    a second port is added, the second port index is chained to the first.
//    subsequently, the second row entry (port type) of the FIRST port becomes 
//    the NEXT mib entry of the first port. The table is contructed this way 
//    building and chaining columns (from the registry, initially) until all
//    port specific columns are intialized.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT InitPortTableMibEntries(PMIB_ENTRY pMibBase,
							 PWAN_SXB_INFO pWanInfo)
{

    UINT        initStatus = SNMP_ERRORSTATUS_NOERROR;

    // Variables to be obtained from the registry
    AsnInteger inSigCount;
    AsnInteger outSigCount;
    AsnInteger portNdx; 
    AsnInteger portSpeed;
    AsnInteger portType; 

	// Pointers to the IOCTL structures used to collect data from the SXB interface
	// First IOCTL gets stats, second in chain gets config data
	PWAN_SXB_INFO	pSxbIoctlData	= pWanInfo;

    
    // Pointers used to manipulate Mib table as it is built

    MIB_ENTRY FAR * pCurPortNdxMibEntry      = &Mib[RS232MIB_FIRST_PORT_NDX];
    MIB_ENTRY FAR * pCurPortTypeMibEntry     = &Mib[RS232MIB_FIRST_PORT_TYPE];
    MIB_ENTRY FAR * pCurInSigNumMibEntry     = &Mib[RS232MIB_FIRST_IN_SIG_NUM];
    MIB_ENTRY FAR * pCurOutSigNumMibEntry    = &Mib[RS232MIB_FIRST_OUT_SIG_NUM];
    MIB_ENTRY FAR * pCurInPortSpeedMibEntry  = &Mib[RS232MIB_FIRST_IN_PORT_SPEED];
    MIB_ENTRY FAR * pCurOutPortSpeedMibEntry = &Mib[RS232MIB_FIRST_OUT_PORT_SPEED];


    for (portNdx=1; portNdx <= portCount; portNdx++)
    {
		inSigCount   = 0;
		outSigCount  = 0;
		portSpeed    = 128000; 
		portType     = 3;

		//// Initialize the Mib variables with the registry values
		// Initialize the port index
		*( (long *) pCurPortNdxMibEntry->Storage )      = portNdx;
		pCurPortNdxMibEntry->pSxbRawData = NULL;

		// Initialize the port type
		*( (long *) pCurPortTypeMibEntry->Storage )     = portType;
		pCurPortTypeMibEntry->pSxbRawData = 
			&(pSxbIoctlData->upData.pPortMibData->rs232PortType);

#ifdef SNMP_DLL_DEBUG
		wsprintf(DbgBuf,
				"***I*** WAN: Port Type Location = 0x%lx\n",
				pCurPortTypeMibEntry->pSxbRawData);
		OutputDebugString(DbgBuf);
#endif

		// Initialize the input signal count
		*( (long *) pCurInSigNumMibEntry->Storage )     = inSigCount;
		pCurInSigNumMibEntry->pSxbRawData = NULL;

		// Initialize the output signal count
		*( (long *) pCurOutSigNumMibEntry->Storage )    = outSigCount;
		pCurOutSigNumMibEntry->pSxbRawData = NULL;

		// Initialize the input speed
		*( (long *) pCurInPortSpeedMibEntry->Storage )  = portSpeed;
		pCurInPortSpeedMibEntry->pSxbRawData = 
			&(pSxbIoctlData->upData.pPortMibData->rs232PortInPortSpeed);

		// Initialize the output speed
		*( (long *) pCurOutPortSpeedMibEntry->Storage ) = portSpeed;
		pCurOutPortSpeedMibEntry->pSxbRawData = 
			&(pSxbIoctlData->upData.pPortMibData->rs232PortOutPortSpeed);
		
		// Create a new column for the next port if not the last one.
		// The new column element will chain itself in after the existing
		// one, and will increment the last digit in the oid to reflect the
		// next indexed element in a particular row.
		if (portNdx  < portCount)
		{
			pCurPortNdxMibEntry      = CreateNextMibColFrom(pCurPortNdxMibEntry, 
															1, 
															TRUE,
															NULL);
			// Check for successful completion
			if (pCurPortNdxMibEntry == NULL)
			{
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
			}

			pCurPortTypeMibEntry     = CreateNextMibColFrom(pCurPortTypeMibEntry, 
															1, 
															TRUE,
															NULL);
			// Check for successful completion
			if (pCurPortTypeMibEntry == NULL)
			{
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
			}
			
			pCurInSigNumMibEntry     = CreateNextMibColFrom(pCurInSigNumMibEntry, 
															1, 
															TRUE,
															NULL);
			// Check for successful completion
			if (pCurInSigNumMibEntry == NULL)
			{
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
			}

			pCurOutSigNumMibEntry    = CreateNextMibColFrom(pCurOutSigNumMibEntry, 
															1, 
															TRUE,
															NULL);
			// Check for successful completion
			if (pCurOutSigNumMibEntry == NULL)
			{
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
			}

			pCurInPortSpeedMibEntry  = CreateNextMibColFrom(pCurInPortSpeedMibEntry, 
															1, 
															TRUE,
															NULL);
			// Check for successful completion
			if (pCurInPortSpeedMibEntry == NULL)
			{
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
			}

			pCurOutPortSpeedMibEntry = CreateNextMibColFrom(pCurOutPortSpeedMibEntry, 
															1, 
															TRUE,
															NULL);
			// Check for successful completion
			if (pCurOutPortSpeedMibEntry == NULL)
			{
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
			}

		} //end_if
		
		// Update the pointers into SXB IOCTL linked list
		// This list is paired: 1st IOCTL = portInfo, 2nd = syncPortInfo
		pSxbIoctlData	= pSxbIoctlData->pNextWanSxbInfo;
		if (pSxbIoctlData != NULL)
		{
			pSxbIoctlData	= pSxbIoctlData->pNextWanSxbInfo;
		}
		else 
		{
			//DebugBreak();
		}

    } //end_for

    return initStatus;
}

//
// InitSyncPortTableMibEntries
//    Initializes the Sync Port Table Entries in the Mib from the registry.
//    The port table is initialized in the same manner as the RS232 Port 
//    Table described above.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT InitSyncPortTableMibEntries(MIB_ENTRY FAR * pMibBase,
								PWAN_SXB_INFO pWanInfo)
{
    UINT        initStatus = SNMP_ERRORSTATUS_NOERROR;

    // Variables to be initialized
    
	AsnInteger portNdx; 
    AsnInteger ClockSource;
	
	// Pointers to the IOCTL structures used to collect data from the SXB interface
	// First IOCTL gets stats, second in chain gets config data

	PWAN_SXB_INFO	pSxbIoctlData	= pWanInfo->pNextWanSxbInfo;

    // Pointers used to manipulate Mib table as it is built

    MIB_ENTRY FAR * pCurPortNdxMibEntry      = &Mib[RS232MIB_FIRST_SYNC_PORT_NDX];
    MIB_ENTRY FAR * pCurClockSourceMibEntry  = &Mib[RS232MIB_FIRST_SYNC_PORT_CLK_SRC];
    MIB_ENTRY FAR * pCurFrameChkErrsMibEntry = &Mib[RS232MIB_FIRST_SYNC_PORT_FCS_ERRS];
    MIB_ENTRY FAR * pCurXmtUrunErrsMibEntry  = &Mib[RS232MIB_FIRST_SYNC_PORT_XUR_ERRS];
    MIB_ENTRY FAR * pCurRcvOrunErrsMibEntry  = &Mib[RS232MIB_FIRST_SYNC_PORT_ROR_ERRS];
    MIB_ENTRY FAR * pCurIntFramesMibEntry    = &Mib[RS232MIB_FIRST_SYNC_PORT_INT_FRM_ERRS];
    MIB_ENTRY FAR * pCurAbortFramesMibEntry  = &Mib[RS232MIB_FIRST_SYNC_PORT_ABT_FRM_ERRS];


    for (portNdx=1; portNdx <= portCount; portNdx++)
    {
	    ClockSource  = 2; 
	    
	    //// Initialize the Mib variables with the registry values
		// Initialize the port index
	    *( (long *) pCurPortNdxMibEntry->Storage )      = portNdx;
		pCurPortNdxMibEntry->pSxbRawData = NULL;

		// Initialize the clock source - FALSE => external
	    *( (long *) pCurClockSourceMibEntry->Storage )  = ClockSource;
		pCurClockSourceMibEntry->pSxbRawData = 
			&pSxbIoctlData->upData.pSyncPortMibData->rs232SyncPortClockSource;

		// Initialize the frame checks errors
	    *( (long *) pCurFrameChkErrsMibEntry->Storage ) = 0;
		pCurFrameChkErrsMibEntry->pSxbRawData = 
			&pSxbIoctlData->upData.pSyncPortMibData->rs232SyncPortFrameCheckErrs;

		// Initialize the transmit underrun errors
	    *( (long *) pCurXmtUrunErrsMibEntry->Storage )  = 0;
		pCurXmtUrunErrsMibEntry->pSxbRawData = 
			&pSxbIoctlData->upData.pSyncPortMibData->rs232SyncPortTransmitUnderrunErrs;

		// Initialize the receive overrun errors
	    *( (long *) pCurRcvOrunErrsMibEntry->Storage )  = 0;
		pCurRcvOrunErrsMibEntry->pSxbRawData = 
			&pSxbIoctlData->upData.pSyncPortMibData->rs232SyncPortReceiveOverrunErrs;

		// Initialize the interrupted frames
	    *( (long *) pCurIntFramesMibEntry->Storage )    = 0;
		pCurIntFramesMibEntry->pSxbRawData = 
			&pSxbIoctlData->upData.pSyncPortMibData->rs232SyncPortInterruptedFrames;

		// Initialize the aborted frames
	    *( (long *) pCurAbortFramesMibEntry->Storage )  = 0;
		pCurAbortFramesMibEntry->pSxbRawData = 
			&pSxbIoctlData->upData.pSyncPortMibData->rs232SyncPortAbortedFrames;
	    
	    // Create a new column for the next port if not the last one.
	    // The new column element will chain itself in after the existing
	    // one, and will increment the last digit in the oid to reflect the
	    // next indexed element in a particular row.
	    if (portNdx  < portCount)
	    {
	        pCurPortNdxMibEntry = CreateNextMibColFrom(pCurPortNdxMibEntry, 
														1, 
														TRUE,
														NULL);
	        // Check for successful completion
	        if (pCurPortNdxMibEntry == NULL)
	        {
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
	        }

	        pCurClockSourceMibEntry  = CreateNextMibColFrom(pCurClockSourceMibEntry, 
															1, 
															TRUE,
															NULL);
	        // Check for successful completion
	        if (pCurClockSourceMibEntry == NULL)
	        {
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
	        }
	        
	        pCurFrameChkErrsMibEntry = CreateNextMibColFrom(pCurFrameChkErrsMibEntry, 
															1, 
															TRUE,
															NULL);
	        // Check for successful completion
	        if (pCurFrameChkErrsMibEntry == NULL)
	        {
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
	        }

	        pCurXmtUrunErrsMibEntry = CreateNextMibColFrom(pCurXmtUrunErrsMibEntry, 
															1, 
															TRUE,
															NULL);
	        // Check for successful completion
	        if (pCurXmtUrunErrsMibEntry == NULL)
	        {
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
	        }

	        pCurRcvOrunErrsMibEntry = CreateNextMibColFrom(pCurRcvOrunErrsMibEntry, 
															1, 
															TRUE,
															NULL);
	        // Check for successful completion
	        if (pCurRcvOrunErrsMibEntry == NULL)
	        {
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
	        }

	        pCurIntFramesMibEntry = CreateNextMibColFrom(pCurIntFramesMibEntry, 
															1, 
															TRUE,
															NULL);
	        // Check for successful completion
	        if (pCurIntFramesMibEntry == NULL)
	        {
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
	        }

	        pCurAbortFramesMibEntry = CreateNextMibColFrom(pCurAbortFramesMibEntry, 
															1, 
															TRUE,
															NULL);
	        // Check for successful completion
	        if (pCurAbortFramesMibEntry == NULL)
	        {
				initStatus = SNMP_ERRORSTATUS_GENERR;
				break;
	        }

		}	//end_if

		// Update the pointers into SXB IOCTL linked list
		// This list is paired: 1st IOCTL = PortInfo, 2nd = SyncPortInfo
		pSxbIoctlData = pSxbIoctlData->pNextWanSxbInfo;
		if (pSxbIoctlData != NULL)
		{
			pSxbIoctlData = pSxbIoctlData->pNextWanSxbInfo;
		}

    }	//end_while
    return initStatus;
}    

//
// InitInSigTableMibEntries
//    Initializes the Input Signal Table Entries in the Mib from the registry.
//    The port table is initialized in the same manner as the RS232 Port 
//    Table described above.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT InitInSigTableMibEntries(MIB_ENTRY FAR * pMibBase,
							 PWAN_SXB_INFO pWanInfo)
{
    UINT        initStatus = SNMP_ERRORSTATUS_NOERROR;

    // Variables to be initialized
    AsnInteger portNdx;
    AsnInteger signalState = RS232MIB_SIG_STATE_NONE;
    AsnCounter signalStateChanges = 0;
    
	// Pointers to the IOCTL structures used to collect data from the SXB interface
	// First IOCTL gets stats, second in chain gets config data

	PWAN_SXB_INFO	pSxbStats	= pWanInfo;
	PWAN_SXB_INFO	pSxbConfig	= pWanInfo->pNextWanSxbInfo;

    // Pointers used to manipulate Mib table as it is built

    MIB_ENTRY FAR * pCurPortNdxMibEntry     = &Mib[RS232MIB_FIRST_IN_SIG_NDX];
    MIB_ENTRY FAR * pCurSigNameRtsMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_NAME_RTS];
    MIB_ENTRY FAR * pCurSigNameCtsMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_NAME_CTS];
    MIB_ENTRY FAR * pCurSigNameDsrMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_NAME_DSR];
    MIB_ENTRY FAR * pCurSigNameDtrMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_NAME_DTR];
    MIB_ENTRY FAR * pCurSigNameRiMibEntry   = &Mib[RS232MIB_FIRST_IN_SIG_NAME_RI];
    MIB_ENTRY FAR * pCurSigNameDcdMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_NAME_DCD];
    MIB_ENTRY FAR * pCurStateRtsMibEntry    = &Mib[RS232MIB_FIRST_IN_SIG_STATE_RTS];
    MIB_ENTRY FAR * pCurStateCtsMibEntry    = &Mib[RS232MIB_FIRST_IN_SIG_STATE_CTS];
    MIB_ENTRY FAR * pCurStateDsrMibEntry    = &Mib[RS232MIB_FIRST_IN_SIG_STATE_DSR];
    MIB_ENTRY FAR * pCurStateDtrMibEntry    = &Mib[RS232MIB_FIRST_IN_SIG_STATE_DTR];
    MIB_ENTRY FAR * pCurStateRiMibEntry     = &Mib[RS232MIB_FIRST_IN_SIG_STATE_RI];
    MIB_ENTRY FAR * pCurStateDcdMibEntry    = &Mib[RS232MIB_FIRST_IN_SIG_STATE_DCD];
    MIB_ENTRY FAR * pCurChangesRtsMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_CHANGES_RTS];
    MIB_ENTRY FAR * pCurChangesCtsMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_CHANGES_CTS];
    MIB_ENTRY FAR * pCurChangesDsrMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_CHANGES_DSR];
    MIB_ENTRY FAR * pCurChangesDtrMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_CHANGES_DTR];
    MIB_ENTRY FAR * pCurChangesRiMibEntry   = &Mib[RS232MIB_FIRST_IN_SIG_CHANGES_RI];
    MIB_ENTRY FAR * pCurChangesDcdMibEntry  = &Mib[RS232MIB_FIRST_IN_SIG_CHANGES_DCD];

    for (portNdx=1; portNdx <= portCount; portNdx++)
    {
	    signalState         = RS232MIB_SIG_STATE_NONE;
        signalStateChanges  = 0;
    
	    
	    ////Initialize the Mib variables 
	    *( (long *) pCurPortNdxMibEntry->Storage )      = portNdx;
		pCurPortNdxMibEntry->pSxbRawData = NULL;

        *( (long *) pCurSigNameRtsMibEntry->Storage )   = RS232MIB_SIG_NAME_RTS;
		pCurSigNameRtsMibEntry->pSxbRawData = NULL;

		*( (long *) pCurSigNameCtsMibEntry->Storage )   = RS232MIB_SIG_NAME_CTS;
		pCurSigNameCtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameDsrMibEntry->Storage )   = RS232MIB_SIG_NAME_DSR;
		pCurSigNameDsrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameDtrMibEntry->Storage )   = RS232MIB_SIG_NAME_DTR;
		pCurSigNameDtrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameRiMibEntry->Storage )    = RS232MIB_SIG_NAME_RI;
		pCurSigNameRiMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameDcdMibEntry->Storage )   = RS232MIB_SIG_NAME_DCD;
		pCurSigNameDcdMibEntry->pSxbRawData = NULL;

        *( (long *) pCurStateRtsMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateRtsMibEntry->pSxbRawData = NULL;

		*( (long *) pCurStateCtsMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateCtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateDsrMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateDsrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateDtrMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateDtrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateRiMibEntry->Storage )      = RS232MIB_SIG_STATE_NONE;
		pCurStateRiMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateDcdMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateDcdMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesRtsMibEntry->Storage )   = 0;
		pCurChangesRtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesCtsMibEntry->Storage )   = 0;
		pCurChangesCtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesDsrMibEntry->Storage )   = 0;
		pCurChangesDsrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesDtrMibEntry->Storage )   = 0;
		pCurChangesDtrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesRiMibEntry->Storage )    = 0;
		pCurChangesRiMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesDcdMibEntry->Storage )   = 0;
		pCurChangesDcdMibEntry->pSxbRawData = NULL;

        // Create a new column for the next port if not the last one.
	    // The new column element will chain itself in after the existing
	    // one, and will increment the port id digit in the oid to reflect the
	    // next indexed element in a particular row.
	    if (portNdx  < portCount)
	    {   

            // Insert the next port ndx element
            pCurPortNdxMibEntry = CreateNextMibColFrom(pCurPortNdxMibEntry, 
														1, 
														TRUE,
														NULL);
	        // Check for successful completion
	        if (pCurPortNdxMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
	    

            // Insert the Signal Name Group
            pCurSigNameRtsMibEntry = CreateNextMibColFrom(pCurSigNameRtsMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameRtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next rts to last port ndx
            pCurSigNameRtsMibEntry->MibNext = pCurSigNameDcdMibEntry->MibNext;
            pCurSigNameDcdMibEntry->MibNext = pCurSigNameRtsMibEntry;
	    
            pCurSigNameCtsMibEntry  = CreateNextMibColFrom(pCurSigNameCtsMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurSigNameCtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next cts to last rts
            pCurSigNameCtsMibEntry->MibNext = pCurSigNameRtsMibEntry->MibNext;
            pCurSigNameRtsMibEntry->MibNext = pCurSigNameCtsMibEntry;
	    
            pCurSigNameDsrMibEntry = CreateNextMibColFrom(pCurSigNameDsrMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameDsrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dsr to last cts
            pCurSigNameDsrMibEntry->MibNext = pCurSigNameCtsMibEntry->MibNext;
            pCurSigNameCtsMibEntry->MibNext = pCurSigNameDsrMibEntry;
	    
            pCurSigNameDtrMibEntry = CreateNextMibColFrom(pCurSigNameDtrMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameDtrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dtr to last dsr
            pCurSigNameDtrMibEntry->MibNext = pCurSigNameDsrMibEntry->MibNext;
            pCurSigNameDsrMibEntry->MibNext = pCurSigNameDtrMibEntry;
	    
            pCurSigNameRiMibEntry  = CreateNextMibColFrom(pCurSigNameRiMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameRiMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ri to last dtr
            pCurSigNameRiMibEntry->MibNext = pCurSigNameDtrMibEntry->MibNext;
            pCurSigNameDtrMibEntry->MibNext = pCurSigNameRiMibEntry;
	    
            pCurSigNameDcdMibEntry = CreateNextMibColFrom(pCurSigNameDcdMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameDcdMibEntry== NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dcd to last ri
            pCurSigNameDcdMibEntry->MibNext = pCurSigNameRiMibEntry->MibNext;
            pCurSigNameRiMibEntry->MibNext = pCurSigNameDcdMibEntry;


            // Insert the next signal state group
            pCurStateRtsMibEntry = CreateNextMibColFrom(pCurStateRtsMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurStateRtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next rts state to last dcd
            pCurStateRtsMibEntry->MibNext = pCurStateDcdMibEntry->MibNext;
            pCurStateDcdMibEntry->MibNext = pCurStateRtsMibEntry;

            pCurStateCtsMibEntry = CreateNextMibColFrom(pCurStateCtsMibEntry, 
														2, 
														FALSE,
														NULL
														);
	        // Check for successful completion
	        if (pCurStateCtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next cts state to last rts state
            pCurStateCtsMibEntry->MibNext = pCurStateRtsMibEntry->MibNext;
            pCurStateRtsMibEntry->MibNext = pCurStateCtsMibEntry;

            pCurStateDsrMibEntry = CreateNextMibColFrom(pCurStateDsrMibEntry, 
														2, 
														FALSE,
														NULL
														);
	        // Check for successful completion
	        if (pCurStateDsrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dsr state to last cts state
            pCurStateDsrMibEntry->MibNext = pCurStateCtsMibEntry->MibNext;
            pCurStateCtsMibEntry->MibNext = pCurStateDsrMibEntry;

            pCurStateDtrMibEntry = CreateNextMibColFrom(pCurStateDtrMibEntry, 
														2, 
														FALSE,
														NULL
														);
	        // Check for successful completion
	        if (pCurStateDtrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dtr state to last dsr state
            pCurStateDtrMibEntry->MibNext = pCurStateDsrMibEntry->MibNext;
            pCurStateDsrMibEntry->MibNext = pCurStateDtrMibEntry;

            pCurStateRiMibEntry = CreateNextMibColFrom(pCurStateRiMibEntry, 
														2, 
														FALSE,
														NULL
														);
	        // Check for successful completion
	        if (pCurStateRiMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ri state to last dtr state
            pCurStateRiMibEntry->MibNext = pCurStateDtrMibEntry->MibNext;
            pCurStateDtrMibEntry->MibNext = pCurStateRiMibEntry;

            pCurStateDcdMibEntry = CreateNextMibColFrom(pCurStateDcdMibEntry, 
														2, 
														FALSE,
														NULL
														);
	        // Check for successful completion
	        if (pCurStateDcdMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dcd state to last ri state
            pCurStateDcdMibEntry ->MibNext = pCurStateRiMibEntry->MibNext;
            pCurStateRiMibEntry->MibNext = pCurStateDcdMibEntry;

            
            //Insert the next signal states group
            pCurChangesRtsMibEntry = CreateNextMibColFrom(pCurChangesRtsMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurChangesRtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next rts changes to last dcd state 
            pCurChangesRtsMibEntry->MibNext = pCurChangesDcdMibEntry->MibNext;
            pCurChangesDcdMibEntry ->MibNext = pCurChangesRtsMibEntry;

            pCurChangesCtsMibEntry = CreateNextMibColFrom(pCurChangesCtsMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurChangesCtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ct changes to last rts changes
            pCurChangesCtsMibEntry->MibNext = pCurChangesRtsMibEntry->MibNext;
            pCurChangesRtsMibEntry->MibNext = pCurChangesCtsMibEntry;

            pCurChangesDsrMibEntry = CreateNextMibColFrom(pCurChangesDsrMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurChangesDsrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dsr changes to last cts changes
            pCurChangesDsrMibEntry->MibNext = pCurChangesCtsMibEntry->MibNext;
            pCurChangesCtsMibEntry->MibNext = pCurChangesDsrMibEntry;

            pCurChangesDtrMibEntry = CreateNextMibColFrom(pCurChangesDtrMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurChangesDtrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dtr changes to last dsr changes
            pCurChangesDtrMibEntry->MibNext = pCurChangesDsrMibEntry->MibNext;
            pCurChangesDsrMibEntry->MibNext = pCurChangesDtrMibEntry;

            pCurChangesRiMibEntry = CreateNextMibColFrom(pCurChangesRiMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurChangesRiMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ri changes to last dtr changes
            pCurChangesRiMibEntry->MibNext = pCurChangesDtrMibEntry->MibNext;
            pCurChangesDtrMibEntry->MibNext = pCurChangesRiMibEntry;

            pCurChangesDcdMibEntry = CreateNextMibColFrom(pCurChangesDcdMibEntry, 
															2, 
															FALSE,
															NULL
															);
	        // Check for successful completion
	        if (pCurChangesDcdMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dcd changes to last ri changes
            pCurChangesDcdMibEntry->MibNext = pCurChangesRiMibEntry->MibNext;
            pCurChangesRiMibEntry->MibNext = pCurChangesDcdMibEntry;

	    }	//end_if

		// Update the pointers into SXB IOCTL linked list
		// This list is paired: 1st IOCTL = stats, 2nd = data
		pSxbStats	= pSxbConfig->pNextWanSxbInfo;
		if (pSxbStats != NULL)
		{
			pSxbConfig	= pSxbStats->pNextWanSxbInfo;
		}

    }	//end_while

    return initStatus;
}    

//
// InitOutSigTableMibEntries
//    Initializes the Output Signal Table Entries in the Mib from the registry.
//    The port table is initialized in the same manner as the RS232 Port 
//    Table described above.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT InitOutSigTableMibEntries(MIB_ENTRY FAR * pMibBase,
							 PWAN_SXB_INFO pWanInfo)
{
    UINT        initStatus = SNMP_ERRORSTATUS_NOERROR;

    // Variables to be initialized
    AsnInteger portNdx;
    AsnInteger signalState = RS232MIB_SIG_STATE_NONE;
    AsnCounter signalStateChanges = 0;
    
	// Pointers to the IOCTL structures used to collect data from the SXB interface
	// First IOCTL gets stats, second in chain gets config data

	PWAN_SXB_INFO	pSxbStats	= pWanInfo;
	PWAN_SXB_INFO	pSxbConfig	= pWanInfo->pNextWanSxbInfo;

    // Pointers used to manipulate Mib table as it is built

    MIB_ENTRY FAR * pCurPortNdxMibEntry     = &Mib[RS232MIB_FIRST_OUT_SIG_NDX];
    MIB_ENTRY FAR * pCurSigNameRtsMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_NAME_RTS];
    MIB_ENTRY FAR * pCurSigNameCtsMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_NAME_CTS];
    MIB_ENTRY FAR * pCurSigNameDsrMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_NAME_DSR];
    MIB_ENTRY FAR * pCurSigNameDtrMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_NAME_DTR];
    MIB_ENTRY FAR * pCurSigNameRiMibEntry   = &Mib[RS232MIB_FIRST_OUT_SIG_NAME_RI];
    MIB_ENTRY FAR * pCurSigNameDcdMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_NAME_DCD];
    MIB_ENTRY FAR * pCurStateRtsMibEntry    = &Mib[RS232MIB_FIRST_OUT_SIG_STATE_RTS];
    MIB_ENTRY FAR * pCurStateCtsMibEntry    = &Mib[RS232MIB_FIRST_OUT_SIG_STATE_CTS];
    MIB_ENTRY FAR * pCurStateDsrMibEntry    = &Mib[RS232MIB_FIRST_OUT_SIG_STATE_DSR];
    MIB_ENTRY FAR * pCurStateDtrMibEntry    = &Mib[RS232MIB_FIRST_OUT_SIG_STATE_DTR];
    MIB_ENTRY FAR * pCurStateRiMibEntry     = &Mib[RS232MIB_FIRST_OUT_SIG_STATE_RI];
    MIB_ENTRY FAR * pCurStateDcdMibEntry    = &Mib[RS232MIB_FIRST_OUT_SIG_STATE_DCD];
    MIB_ENTRY FAR * pCurChangesRtsMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_CHANGES_RTS];
    MIB_ENTRY FAR * pCurChangesCtsMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_CHANGES_CTS];
    MIB_ENTRY FAR * pCurChangesDsrMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_CHANGES_DSR];
    MIB_ENTRY FAR * pCurChangesDtrMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_CHANGES_DTR];
    MIB_ENTRY FAR * pCurChangesRiMibEntry   = &Mib[RS232MIB_FIRST_OUT_SIG_CHANGES_RI];
    MIB_ENTRY FAR * pCurChangesDcdMibEntry  = &Mib[RS232MIB_FIRST_OUT_SIG_CHANGES_DCD];

    for (portNdx=1; portNdx <= portCount; portNdx++)
    {
	    signalState         = RS232MIB_SIG_STATE_NONE;
        signalStateChanges  = 0;
    
	    
	    //Initialize the Mib variables with the registry values
	    *( (long *) pCurPortNdxMibEntry->Storage )      = portNdx;
		pCurPortNdxMibEntry->pSxbRawData = NULL;

        *( (long *) pCurSigNameRtsMibEntry->Storage )   = RS232MIB_SIG_NAME_RTS;
		pCurSigNameRtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameCtsMibEntry->Storage )   = RS232MIB_SIG_NAME_CTS;
		pCurSigNameCtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameCtsMibEntry->Storage )   = RS232MIB_SIG_NAME_DSR;
		pCurSigNameCtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameDtrMibEntry->Storage )   = RS232MIB_SIG_NAME_DTR;
		pCurSigNameDtrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameRiMibEntry->Storage )    = RS232MIB_SIG_NAME_RI;
		pCurSigNameRiMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurSigNameDcdMibEntry->Storage )   = RS232MIB_SIG_NAME_DCD;
		pCurSigNameDcdMibEntry->pSxbRawData = NULL;

        *( (long *) pCurStateRtsMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateRtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateCtsMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateCtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateDsrMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateDsrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateDtrMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateDtrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateRiMibEntry->Storage )      = RS232MIB_SIG_STATE_NONE;
		pCurStateRiMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurStateDcdMibEntry->Storage )     = RS232MIB_SIG_STATE_NONE;
		pCurStateDcdMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesRtsMibEntry->Storage )   = 0;
		pCurChangesRtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesCtsMibEntry->Storage )   = 0;
		pCurChangesCtsMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesDsrMibEntry->Storage )   = 0;
		pCurChangesDsrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesDtrMibEntry->Storage )   = 0;
		pCurChangesDtrMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesRiMibEntry->Storage )    = 0;
		pCurChangesRiMibEntry->pSxbRawData = NULL;

	    *( (long *) pCurChangesDcdMibEntry->Storage )   = 0;
		pCurChangesDcdMibEntry->pSxbRawData = NULL;

        // Create a new column for the next port if not the last one.
	    // The new column element will chain itself in after the existing
	    // one, and will increment the port id digit in the oid to reflect the
	    // next indexed element in a particular row.
	    if (portNdx  < portCount)
	    {   

            // Insert the next port ndx element
            pCurPortNdxMibEntry = CreateNextMibColFrom(pCurPortNdxMibEntry, 
														1, 
														TRUE, 
														NULL);
	        // Check for successful completion
	        if (pCurPortNdxMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
	    

            // Insert the Signal Name Group
            pCurSigNameRtsMibEntry = CreateNextMibColFrom(pCurSigNameRtsMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameRtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next rts to last port ndx
            pCurSigNameRtsMibEntry->MibNext = pCurSigNameDcdMibEntry->MibNext;
            pCurSigNameDcdMibEntry->MibNext = pCurSigNameRtsMibEntry;
	    
            pCurSigNameCtsMibEntry  = CreateNextMibColFrom(pCurSigNameCtsMibEntry, 
															2, 
															FALSE, 
															NULL);
	        // Check for successful completion
	        if (pCurSigNameCtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            
			//Chain the next cts to last rts
            pCurSigNameCtsMibEntry->MibNext = pCurSigNameRtsMibEntry->MibNext;
            pCurSigNameRtsMibEntry->MibNext = pCurSigNameCtsMibEntry;
	    
            pCurSigNameDsrMibEntry = CreateNextMibColFrom(pCurSigNameDsrMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameDsrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dsr to last cts
            pCurSigNameDsrMibEntry->MibNext = pCurSigNameCtsMibEntry->MibNext;
            pCurSigNameCtsMibEntry->MibNext = pCurSigNameDsrMibEntry;
	    
            pCurSigNameDtrMibEntry = CreateNextMibColFrom(pCurSigNameDtrMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameDtrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dtr to last dsr
            pCurSigNameDtrMibEntry->MibNext = pCurSigNameDsrMibEntry->MibNext;
            pCurSigNameDsrMibEntry->MibNext = pCurSigNameDtrMibEntry;
	    
            pCurSigNameRiMibEntry  = CreateNextMibColFrom(pCurSigNameRiMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameRiMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ri to last dtr
            pCurSigNameRiMibEntry->MibNext = pCurSigNameDtrMibEntry->MibNext;
            pCurSigNameDtrMibEntry->MibNext = pCurSigNameRiMibEntry;
	    
            pCurSigNameDcdMibEntry = CreateNextMibColFrom(pCurSigNameDcdMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurSigNameDcdMibEntry== NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dcd to last ri
            pCurSigNameDcdMibEntry->MibNext = pCurSigNameRiMibEntry->MibNext;
            pCurSigNameRiMibEntry->MibNext = pCurSigNameDcdMibEntry;


            // Insert the next signal state group
            pCurStateRtsMibEntry = CreateNextMibColFrom(pCurStateRtsMibEntry, 
														2, 
														FALSE,
														NULL);
	        // Check for successful completion
	        if (pCurStateRtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next rts state to last dcd
            pCurStateRtsMibEntry->MibNext = pCurStateDcdMibEntry->MibNext;
            pCurStateDcdMibEntry->MibNext = pCurStateRtsMibEntry;

            pCurStateCtsMibEntry = CreateNextMibColFrom(pCurStateCtsMibEntry, 
														2, 
														FALSE,
														NULL);
	        // Check for successful completion
	        if (pCurStateCtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next cts state to last rts state
            pCurStateCtsMibEntry->MibNext = pCurStateRtsMibEntry->MibNext;
            pCurStateRtsMibEntry->MibNext = pCurStateCtsMibEntry;

            pCurStateDsrMibEntry = CreateNextMibColFrom(pCurStateDsrMibEntry, 
														2, 
														FALSE,
														NULL);
	        // Check for successful completion
	        if (pCurStateDsrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dsr state to last cts state
            pCurStateDsrMibEntry->MibNext = pCurStateCtsMibEntry->MibNext;
            pCurStateCtsMibEntry->MibNext = pCurStateDsrMibEntry;

            pCurStateDtrMibEntry = CreateNextMibColFrom(pCurStateDtrMibEntry, 
														2, 
														FALSE,
														NULL);
	        // Check for successful completion
	        if (pCurStateDtrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dtr state to last dsr state
            pCurStateDtrMibEntry->MibNext = pCurStateDsrMibEntry->MibNext;
            pCurStateDsrMibEntry->MibNext = pCurStateDtrMibEntry;

            pCurStateRiMibEntry = CreateNextMibColFrom(pCurStateRiMibEntry, 
														2, 
														FALSE,
														NULL);
	        // Check for successful completion
	        if (pCurStateRiMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ri state to last dtr state
            pCurStateRiMibEntry->MibNext = pCurStateDtrMibEntry->MibNext;
            pCurStateDtrMibEntry->MibNext = pCurStateRiMibEntry;

            pCurStateDcdMibEntry = CreateNextMibColFrom(pCurStateDcdMibEntry, 
														2, 
														FALSE,
														NULL);
	        // Check for successful completion
	        if (pCurStateDcdMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dcd state to last ri state
            pCurStateDcdMibEntry ->MibNext = pCurStateRiMibEntry->MibNext;
            pCurStateRiMibEntry->MibNext = pCurStateDcdMibEntry;

            
            //Insert the next signal states group
            pCurChangesRtsMibEntry = CreateNextMibColFrom(pCurChangesRtsMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurChangesRtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next rts changes to last dcd state 
            pCurChangesRtsMibEntry->MibNext = pCurChangesDcdMibEntry->MibNext;
            pCurChangesDcdMibEntry ->MibNext = pCurChangesRtsMibEntry;

            pCurChangesCtsMibEntry = CreateNextMibColFrom(pCurChangesCtsMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurChangesCtsMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ct changes to last rts changes
            pCurChangesCtsMibEntry->MibNext = pCurChangesRtsMibEntry->MibNext;
            pCurChangesRtsMibEntry->MibNext = pCurChangesCtsMibEntry;

            pCurChangesDsrMibEntry = CreateNextMibColFrom(pCurChangesDsrMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurChangesDsrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dsr changes to last cts changes
            pCurChangesDsrMibEntry->MibNext = pCurChangesCtsMibEntry->MibNext;
            pCurChangesCtsMibEntry->MibNext = pCurChangesDsrMibEntry;

            pCurChangesDtrMibEntry = CreateNextMibColFrom(pCurChangesDtrMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurChangesDtrMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dtr changes to last dsr changes
            pCurChangesDtrMibEntry->MibNext = pCurChangesDsrMibEntry->MibNext;
            pCurChangesDsrMibEntry->MibNext = pCurChangesDtrMibEntry;

            pCurChangesRiMibEntry = CreateNextMibColFrom(pCurChangesRiMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurChangesRiMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next ri changes to last dtr changes
            pCurChangesRiMibEntry->MibNext = pCurChangesDtrMibEntry->MibNext;
            pCurChangesDtrMibEntry->MibNext = pCurChangesRiMibEntry;

            pCurChangesDcdMibEntry = CreateNextMibColFrom(pCurChangesDcdMibEntry, 
															2, 
															FALSE,
															NULL);
	        // Check for successful completion
	        if (pCurChangesDcdMibEntry == NULL)
	        {
    		    initStatus = SNMP_ERRORSTATUS_GENERR;
	    	    break;
	        }
            //Chain the next dcd changes to last ri changes
            pCurChangesDcdMibEntry->MibNext = pCurChangesRiMibEntry->MibNext;
            pCurChangesRiMibEntry->MibNext = pCurChangesDcdMibEntry;

	    }	// end_if

		// Update the pointers into SXB IOCTL linked list
		// This list is paired: 1st IOCTL = stats, 2nd = data
		pSxbStats	= pSxbConfig->pNextWanSxbInfo;
		if (pSxbStats != NULL)
		{
			pSxbConfig	= pSxbStats->pNextWanSxbInfo;
		}

    }	//end_while

    return initStatus;
}    

//
// CreateNextMibColFrom
//    Creates the nest mib column element in a row fraom an existing row
//    MIB element. It will bump the last oid digit to indicate a new column.
//    It will also create the necessary storage as well. If a NULL mib pointer
//    is returned the operation has failed.
//
// Notes:
//    The Adjust Index parameter is included to tell the utility which parameter
//    in a multi-dimensional array must be adjusted. A value of 1 means the last
//    digit. A value of 2 means the nex to last digit, and so on. The insertInChain
//    parameter will insert the new element into the mib structure. This is used when
//    adding a one dimensional column. If a 2 dimensional array is being expanded, the
//    calling routine must manage linkage on a vector by vector basis.
//
// Return Codes:
//    Pointer to a new Mib Element. NULL if failure.
//
// Error Codes:
//    None.
//
PMIB_ENTRY CreateNextMibColFrom(
                MIB_ENTRY FAR * pOldMibEntry, 
                UINT			AdjustIndex,
                BOOL			insertInChain,
				PVOID			pRawData
           )
{
    UINT            createStatus = 0;
    MIB_ENTRY FAR * pNewMibEntry;

    // Allocate memory for the new MIB_ENTRY
    pNewMibEntry = SNMP_malloc(sizeof(MIB_ENTRY));
  
    if (pNewMibEntry == NULL)
    {
	    return NULL;
    }
    
    // Allocate storage for the Oid
    pNewMibEntry->Oid.ids = SNMP_malloc(pOldMibEntry->Oid.idLength);
    if (pNewMibEntry->Oid.ids == NULL)
    {
	    SNMP_free (pNewMibEntry);
	    return NULL;
    }

    // Copy the oid from old to new, and bump the last digit
    createStatus = SNMP_oidcpy(&(pNewMibEntry->Oid), &(pOldMibEntry->Oid));

    if (createStatus != TRUE)
	{
#ifdef SNMP_DLL_DEBUG
		OutputDebugString("***E*** RS232: CreateNewColumn Failed on OID Copy!\n");
#endif
		SNMP_free(pNewMibEntry);
		return NULL;
	}

    // Bump the last digit of the Oid up by one
    pNewMibEntry->Oid.ids[pNewMibEntry->Oid.idLength-AdjustIndex] += 1;

    // Copy over the Mib Entry's type field
    pNewMibEntry->Type = pOldMibEntry->Type;

    // Copy over the Mib Entry's access field
    pNewMibEntry->Access = pOldMibEntry->Access;

    // Copy over the Mib Entry's function pointer field
    pNewMibEntry->MibFunc = pOldMibEntry->MibFunc;

    // If required, chain the new column element into the Mib by:
    //   1. Setting New.NextMib = Old.NextMib
    //   2. Setting Old.NextMib = &New
    //
    if (insertInChain == TRUE)
    {
        pNewMibEntry->MibNext = pOldMibEntry->MibNext;
        pOldMibEntry->MibNext = pNewMibEntry;
    }

    // Copy the Oid Storage area from old to new
    switch (pOldMibEntry->Type) {
    
    case ASN_RFC1155_COUNTER:
    case ASN_INTEGER:
	    pNewMibEntry->Storage = SNMP_malloc(sizeof(AsnInteger));
	    *( (long *) pNewMibEntry->Storage ) = *( (long *) pOldMibEntry->Storage );
	    break;
    
    default:
	    createStatus = 0;
    	break;
    }

    if (!createStatus)
    {
	    SNMP_free (pNewMibEntry->Storage);
	    SNMP_oidfree (&(pNewMibEntry->Oid));
	    SNMP_free (pNewMibEntry);
	    pNewMibEntry = NULL;
    }

    return pNewMibEntry;
}    

//
// ResolveVarBind
//    Resolves a single variable binding.  Modifies the variable on a GET
//    or a GET-NEXT.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT ResolveVarBind(
	IN OUT RFC1157VarBind *VarBind, // Variable Binding to resolve
	IN UINT PduAction               // Action specified in PDU
	 )

{
MIB_ENTRY            *MibPtr;
AsnObjectIdentifier  TempOid;
int                  CompResult;
UINT                 I;
UINT                 nResult;

   // Search for var bind name in the MIB
   I      = 0;
   MibPtr = Mib;

   while ( MibPtr != NULL )
   {
      // Construct OID with complete prefix for comparison purposes
      SNMP_oidcpy( &TempOid, &MIB_OidPrefix );
      SNMP_oidappend( &TempOid, &(MibPtr->Oid) );

      // Check for OID in MIB - On a GET-NEXT the OID does not have to exactly
      // match a variable in the MIB, it must only fall under the MIB root.
      CompResult = SNMP_oidcmp( &VarBind->name, &TempOid );
      if ( CompResult < 0 )
	  {
	     // Since there is not an exact match, the only valid action is GET-NEXT
	     if ( PduAction  != MIB_ACTION_GETNEXT )
	     {
			nResult = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
	     }

	     // Since the match was not exact, but var bind name is within MIB,
	     // we are at the NEXT MIB variable down from the one specified.
	     PduAction = MIB_ACTION_GET;
	     
		 // Replace var bind name with new name
		 SNMP_oidfree( &VarBind->name );
		 SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
		 SNMP_oidappend( &VarBind->name, &MibPtr->Oid );
		 break;
      }
      else
      {
		 if (CompResult == 0)
			 break;
      }

      // Free OID memory before checking another variable
      SNMP_oidfree( &TempOid );

      MibPtr = MibPtr->MibNext;
   } // while

   // If OID not within scope of MIB, then no such name
   if ( MibPtr == NULL )
   {
      nResult = SNMP_ERRORSTATUS_NOSUCHNAME;
      goto Exit;
   }

   // Call function to process request.  Each MIB entry has a function pointer
   // that knows how to process its MIB variable.
   nResult = (*MibPtr->MibFunc)( PduAction, MibPtr, VarBind );

   // Free temp memory
   SNMP_oidfree( &TempOid );

Exit:
   return nResult;
} // ResolveVarBind


//
// MIB_leaf_func
//    Performs generic actions on LEAF variables in the MIB.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT MIB_leaf_func(
	IN UINT Action,
	    IN MIB_ENTRY *MibPtr,
	    IN RFC1157VarBind *VarBind
	 )

{
UINT   ErrStat;

   switch ( Action )
   {
      case MIB_ACTION_GETNEXT:
	     // If there is no GET-NEXT pointer, this is the end of this MIB
	     if ( MibPtr->MibNext == NULL )
	     {
		ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
		goto Exit;
	     }

	 // Setup var bind name of NEXT MIB variable
	 SNMP_oidfree( &VarBind->name );
	 SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
	 SNMP_oidappend( &VarBind->name, &MibPtr->MibNext->Oid );

	 // Call function to process request.  Each MIB entry has a function
	 // pointer that knows how to process its MIB variable.
	 ErrStat = (*MibPtr->MibNext->MibFunc)( MIB_ACTION_GET,
			MibPtr->MibNext, VarBind );
	 break;

      case MIB_ACTION_GET:
         // Make sure that this variable's ACCESS is GET'able
	     if ( MibPtr->Access != MIB_ACCESS_READ &&
		  MibPtr->Access != MIB_ACCESS_READWRITE )
	     {
	        ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
		    goto Exit;
	     }

	     // Setup varbind's return value
	     VarBind->value.asnType = MibPtr->Type;
	     switch ( VarBind->value.asnType )
	     {
	     case ASN_RFC1155_COUNTER:
	     case ASN_RFC1155_GAUGE:
	     case ASN_INTEGER:
			 if (MibPtr->pSxbRawData != NULL)
			 {
				 VarBind->value.asnValue.number = *((AsnInteger*)MibPtr->pSxbRawData);
			 }
			 else
			 {
				 VarBind->value.asnValue.number = *(AsnInteger *)(MibPtr->Storage);
			 }
		     break;

	      case ASN_OCTETSTRING: // This entails ASN_RFC1213_DISPSTRING also
		     VarBind->value.asnValue.string.length =
			  strlen( (LPSTR)MibPtr->Storage );

		       if ( NULL == 
			    (VarBind->value.asnValue.string.stream =
			    SNMP_malloc(VarBind->value.asnValue.string.length *
				   sizeof(char))) )
		       {
			  ErrStat = SNMP_ERRORSTATUS_GENERR;
			  goto Exit;
		       }

		       memcpy( VarBind->value.asnValue.string.stream,
			       (LPSTR)MibPtr->Storage,
			       VarBind->value.asnValue.string.length );
		       VarBind->value.asnValue.string.dynamic = TRUE;

		       break;

		   default:
		       ErrStat = SNMP_ERRORSTATUS_GENERR;
		       goto Exit;
	       }
	       break;

      case MIB_ACTION_SET:
	 // Make sure that this variable's ACCESS is SET'able
#ifdef WRITE_IMPLEMENTED
		if ( MibPtr->Access != MIB_ACCESS_READWRITE &&
			MibPtr->Access != MIB_ACCESS_WRITE )
	    {
#endif
			ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
#ifdef WRITE_IMPLEMENTED
	    }

		// Check for proper type before setting
		if ( MibPtr->Type != VarBind->value.asnType )
	    {
			ErrStat = SNMP_ERRORSTATUS_BADVALUE;
			goto Exit;
	    }

	    // Save value in MIB
	    switch ( VarBind->value.asnType )
	    {

		case ASN_RFC1155_COUNTER:
		case ASN_INTEGER:
			*(AsnInteger *)(MibPtr->Storage) = VarBind->value.asnValue.number;
			break;

	    default:
			ErrStat = SNMP_ERRORSTATUS_GENERR;
			goto Exit;
	    }
#endif
		break;

      default:
	 ErrStat = SNMP_ERRORSTATUS_GENERR;
	     goto Exit;
   } // switch

   // Signal no error occurred
   ErrStat = SNMP_ERRORSTATUS_NOERROR;

Exit:
   return ErrStat;

} // end MIB_leaf_func

//
// MIB_Interface_Type_func
//    Performs actions on Interface type variable in the MIB.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT MIB_Interface_Type_func(
		IN UINT Action,
	    IN MIB_ENTRY *MibPtr,
	    IN RFC1157VarBind *VarBind
	 )

{
UINT   ErrStat;

	switch ( Action )
	{
	case MIB_ACTION_GETNEXT:
	    // If there is no GET-NEXT pointer, this is the end of this MIB
	    if ( MibPtr->MibNext == NULL )
	    {
			ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
	    }

		// Setup var bind name of NEXT MIB variable
		SNMP_oidfree( &VarBind->name );
		SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
		SNMP_oidappend( &VarBind->name, &MibPtr->MibNext->Oid );

		// Call function to process request.  Each MIB entry has a function
		// pointer that knows how to process its MIB variable.
		ErrStat = (*MibPtr->MibNext->MibFunc)( MIB_ACTION_GET,
				MibPtr->MibNext, VarBind );
		break;

	case MIB_ACTION_GET:
        // Make sure that this variable's ACCESS is GET'able
	    if ( MibPtr->Access != MIB_ACCESS_READ &&
			MibPtr->Access != MIB_ACCESS_READWRITE )
	    {
			ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
	    }

	    // Setup varbind's return value
	    VarBind->value.asnType = MibPtr->Type;
	    switch ( VarBind->value.asnType )
	    {
	    case ASN_INTEGER:
			// Interface Definition translation
			switch (*((uint32*)MibPtr->pSxbRawData))
			{
			case WAN_X21:
				*(AsnInteger *)(MibPtr->Storage) = RS232MIB_PORT_TYPE_RS422;
				break;
			case WAN_V28:
				*(AsnInteger *)(MibPtr->Storage) = RS232MIB_PORT_TYPE_RS232;
				break;
			case WAN_V35:
				*(AsnInteger *)(MibPtr->Storage) = RS232MIB_PORT_TYPE_V35;
				break;
			default:
				*(AsnInteger *)(MibPtr->Storage) = RS232MIB_PORT_TYPE_OTHER;
				break;
			}
			VarBind->value.asnValue.number = *(AsnInteger *)(MibPtr->Storage);
		    break;

		default:
	       ErrStat = SNMP_ERRORSTATUS_GENERR;
	       goto Exit;
		}
		break;

	case MIB_ACTION_SET:
	//Make sure that this variable's ACCESS is SET'able
#ifdef WRITE_IMPLEMENTED
		if ( MibPtr->Access != MIB_ACCESS_READWRITE &&
			MibPtr->Access != MIB_ACCESS_WRITE )
	    {
#endif
			ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
#ifdef WRITE_IMPLEMENTED
	    }

		// Check for proper type before setting
		if ( MibPtr->Type != VarBind->value.asnType )
	    {
			ErrStat = SNMP_ERRORSTATUS_BADVALUE;
			goto Exit;
	    }

	    // Save value in MIB
		switch ( VarBind->value.asnType )
	    {

		case ASN_RFC1155_COUNTER:
		case ASN_INTEGER:
			*(AsnInteger *)(MibPtr->Storage) = VarBind->value.asnValue.number;
			break;

		default:
			ErrStat = SNMP_ERRORSTATUS_GENERR;
			goto Exit;
	    }
		break;
#endif

	default:
		 ErrStat = SNMP_ERRORSTATUS_GENERR;
	     goto Exit;
   } // switch

   // Signal no error occurred
   ErrStat = SNMP_ERRORSTATUS_NOERROR;

Exit:
   return ErrStat;
} // MIB_Interface_Type_func

//
// MIB_ClockSource_func
//    Performs actions on ClockSource variable in the MIB.
//
// Notes:
//
// Return Codes:
//    Standard PDU error codes.
//
// Error Codes:
//    None.
//
UINT MIB_ClockSource_func(
		IN UINT Action,
	    IN MIB_ENTRY *MibPtr,
	    IN RFC1157VarBind *VarBind
	 )

{
UINT   ErrStat;

	switch ( Action )
	{
	case MIB_ACTION_GETNEXT:
	    // If there is no GET-NEXT pointer, this is the end of this MIB
	    if ( MibPtr->MibNext == NULL )
	    {
			ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
	    }

		// Setup var bind name of NEXT MIB variable
		SNMP_oidfree( &VarBind->name );
		SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix );
		SNMP_oidappend( &VarBind->name, &MibPtr->MibNext->Oid );

		// Call function to process request.  Each MIB entry has a function
		// pointer that knows how to process its MIB variable.
		ErrStat = (*MibPtr->MibNext->MibFunc)( MIB_ACTION_GET,
				MibPtr->MibNext, VarBind );
		break;

	case MIB_ACTION_GET:
        // Make sure that this variable's ACCESS is GET'able
	    if ( MibPtr->Access != MIB_ACCESS_READ &&
			MibPtr->Access != MIB_ACCESS_READWRITE )
	    {
			ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
	    }

	    // Setup varbind's return value
	    VarBind->value.asnType = MibPtr->Type;
	    switch ( VarBind->value.asnType )
	    {
	    case ASN_INTEGER:
			// Interface Definition translation
			switch (*((AsnInteger*)MibPtr->pSxbRawData))
			{
			case 0:
				*(AsnInteger *)(MibPtr->Storage) = RS232MIB_SYNC_PORT_CLOCK_SOURCE_EXTERNAL;
				break;
			default:
				*(AsnInteger *)(MibPtr->Storage) = RS232MIB_SYNC_PORT_CLOCK_SOURCE_INTERNAL;
				break;
			}
			VarBind->value.asnValue.number = *(AsnInteger *)(MibPtr->Storage);
		    break;

		default:
	       ErrStat = SNMP_ERRORSTATUS_GENERR;
	       goto Exit;
		}
		break;

	case MIB_ACTION_SET:
	//Make sure that this variable's ACCESS is SET'able
#ifdef WRITE_IMPLEMENTED
		if ( MibPtr->Access != MIB_ACCESS_READWRITE &&
			MibPtr->Access != MIB_ACCESS_WRITE )
	    {
#endif
			ErrStat = SNMP_ERRORSTATUS_NOSUCHNAME;
			goto Exit;
#ifdef WRITE_IMPLEMENTED
	    }

		// Check for proper type before setting
		if ( MibPtr->Type != VarBind->value.asnType )
	    {
			ErrStat = SNMP_ERRORSTATUS_BADVALUE;
			goto Exit;
	    }

	    // Save value in MIB
		switch ( VarBind->value.asnType )
	    {

		case ASN_RFC1155_COUNTER:
		case ASN_INTEGER:
			*(AsnInteger *)(MibPtr->Storage) = VarBind->value.asnValue.number;
			break;

		default:
			ErrStat = SNMP_ERRORSTATUS_GENERR;
			goto Exit;
	    }
		break;
#endif

	default:
		 ErrStat = SNMP_ERRORSTATUS_GENERR;
	     goto Exit;
   } // switch

   // Signal no error occurred
   ErrStat = SNMP_ERRORSTATUS_NOERROR;

Exit:
   return ErrStat;
} // MIB_MIB_ClockSource_func

//
// rs232_Update_MIB_Data
//    Collects all the data needed to update the MIB structure
//
// Notes:
//      This routine is spawned as a thread from the init routine. It runs
//  off a timer tick in .1 second increments.
//
// Return Codes:
//
// Error Codes:
//
long WINAPI rs232_Update_MIB_Data(long pWanInfo)
{
BOOL                bSuccess;
PWAN_SXB_INFO       pBaseWanInfo = (PWAN_SXB_INFO)pWanInfo;
PWAN_SXB_INFO       pCurWanInfo;
PX_IOCTL            pCurSxbIoctl;
int					ndx=0;
DWORD				returnStatus = 0;
CHAR				curDevName[SXB_DEVICE_NAME_SIZE];
BOOL				handleOpen = FALSE;
UINT				retryCount;

	// Open a file handle to each port required
	if (( pCurWanInfo = pBaseWanInfo ) == NULL ) {
#ifdef SNMP_DLL_DEBUG
		OutputDebugString("***E*** WAN: No input parameter to SXB Data Collector\n");
#endif
		return -1;
	}
	
	while (pCurWanInfo != NULL)
	{
		// APP FILE HANDLE OPEN:
		// Open an application file handle to the SXB driver
		strcpy(curDevName, pCurWanInfo->DeviceName);

        if( (pCurWanInfo->hSxbPort = 
                    CreateFile(  pCurWanInfo->DeviceName,
			                     GENERIC_READ | GENERIC_WRITE,
			                     FILE_SHARE_READ | FILE_SHARE_WRITE,
			                     NULL,
			                     CREATE_ALWAYS,
			                     FILE_ATTRIBUTE_NORMAL,
			                     NULL )) == INVALID_HANDLE_VALUE )
        {
			returnStatus = GetLastError();
#ifdef SNMP_DLL_DEBUG
			wsprintf(DbgBuf,
					"***E*** WAN: Couldn't open file handle to SXB adapter, Error = 0x%x\n",
					returnStatus);
			OutputDebugString(DbgBuf);
#endif
			goto Exit;
        }

		// SXB INTERNAL HANDLE OPEN:
		// First, Open a USER PORT inside SXB for IOCTL use
		bSuccess = FALSE;
		retryCount = 0;
		while (!bSuccess && (retryCount < 5))
		{
			DS_OPEN Open;
			ZeroMemory( &Open, sizeof( Open ) );
			strcpy(curDevName, pCurWanInfo->DeviceName);
			strcpy(Open.DeviceName, ID_STR_SXB_WAN_STATS );
			bSuccess = DeviceIoControl( pCurWanInfo->hSxbPort,
										(ULONG)IOCTL_DS_OPEN,
										&Open, sizeof( Open ),
										&Open, sizeof( Open ),
										&(pCurWanInfo->dwBytesWritten), NULL );

			pCurWanInfo->VCWanDevice = Open.hStream;
			if( !bSuccess || Open.ErrorCode )
			{
				returnStatus = GetLastError();
#ifdef SNMP_DLL_DEBUG
				wsprintf(DbgBuf,"***E*** WAN: IOCTL_S_OPEN failed 0x%x, ErrorCode 0x%x\n",
								returnStatus, Open.ErrorCode );
				OutputDebugString(DbgBuf);
#endif
				retryCount++;
				StrToWStr(  pCurWanInfo->WanName,
							ID_STR_SXB_WAN_STATS,
							strlen(ID_STR_SXB_WAN_STATS) + 1 );

				SleepEx(20,FALSE);
			}
		}

		if (!bSuccess)
		{
			goto Exit;
		}

		// ACCOUNTING FOR multiple IOCTLs PER RS232 PORT
        // You need to init each subsequent IOCTL in each group. It is the same
		// Port handle as the first
		do
		{
			if ((pCurWanInfo = pCurWanInfo->pNextWanSxbInfo) != NULL)
			{
#ifdef SNMP_DLL_DEBUG
				wsprintf(DbgBuf,
						"Current Port Device Name='%s', Compare Device Name = '%s'\n", 
						curDevName,
						pCurWanInfo->DeviceName);
				OutputDebugString(DbgBuf);
#endif

				if (strcmp(curDevName,pCurWanInfo->DeviceName) == 0)
				{
					pCurWanInfo->hSxbPort = 
						pCurWanInfo->pPreviousWanSxbInfo->hSxbPort;
					pCurWanInfo->VCWanDevice =
						pCurWanInfo->pPreviousWanSxbInfo->VCWanDevice;
				}
			}
			else
			{
				break;
			}
		} while ((pCurWanInfo != NULL) && 
				(strcmp(curDevName,pCurWanInfo->DeviceName) == 0));
	} //end_while
	
	// If the WAN User ports opened okay, start collecting stats
	ndx = 0;
	do
	{
 		pCurWanInfo = pBaseWanInfo; 

		while (pCurWanInfo != 0)
		{
			//
			// Okay, lets send down the requests for stats and config!
			//
			pCurSxbIoctl = &(pCurWanInfo->XIoctl);
				// Do IOCTL specific init for Port Table
				if (pCurWanInfo->IoctlType == PORT_IOCTL_NDX_PORT_DATA)
				{
					pCurSxbIoctl->DsIoctl.Command = RFC_1317_RS232;
					pCurWanInfo->upData.pPortMibData = (PVOID)&(pCurSxbIoctl->Data);
					pCurWanInfo->upData.pPortMibData->rs232PortIndex = 
						pCurWanInfo->Snid;
					pCurSxbIoctl->DsIoctl.cbDataIn = pCurSxbIoctl->DsIoctl.cbMaxDataOut = sizeof(rfc_1317_rs232_t);
					//DebugBreak();
				}
				else // The SyncPort ioctl comes second in the linked list
				{
					pCurSxbIoctl->DsIoctl.Command = RFC_1317_SYNCPORT;
					pCurWanInfo->upData.pSyncPortMibData = (PVOID)&(pCurSxbIoctl->Data);
					pCurWanInfo->upData.pSyncPortMibData->rs232SyncPortIndex = 
						pCurWanInfo->Snid;
					pCurSxbIoctl->DsIoctl.cbDataIn = pCurSxbIoctl->DsIoctl.cbMaxDataOut = sizeof(rfc_1317_syncport_t);
				}

				// Do IOCTL independent init
				pCurSxbIoctl->DsIoctl.hStream = pCurWanInfo->VCWanDevice;
				pCurSxbIoctl->DsIoctl.pDataIn = pCurSxbIoctl->DsIoctl.pDataOut = (PVOID)&pCurSxbIoctl->Data;

				// Now that we've built an IOCTL, send it down to SXB
				bSuccess = DeviceIoControl( pCurWanInfo->hSxbPort,
													 (ULONG)IOCTL_DS_IOCTL,
													 &pCurSxbIoctl->DsIoctl, sizeof(DS_IOCTL),
													 &pCurSxbIoctl->DsIoctl, sizeof(DS_IOCTL),
													 &(pCurWanInfo->dwBytesWritten), NULL );
				if( !bSuccess  )
				{
					returnStatus = GetLastError();
#ifdef SNMP_DLL_DEBUG
					wsprintf(DbgBuf,"***E*** WAN: Failure on USER IOCTL = %x\n",
									 returnStatus);
					OutputDebugString(DbgBuf);
#endif
				}
				else
				{
					if ( pCurSxbIoctl->DsIoctl.ErrorCode )
					{
#ifdef SNMP_DLL_DEBUG
						wsprintf(DbgBuf,
						         "***E*** WAN: IOCTL error Return 0x%x, Error 0x%x\n",
										 pCurSxbIoctl->DsIoctl.ReturnValue,
										 pCurSxbIoctl->DsIoctl.ErrorCode );
						OutputDebugString(DbgBuf);
#endif
						returnStatus = pCurSxbIoctl->DsIoctl.ErrorCode * -1;
					}
					else
					{
					}
				}
			// Go to the next IOCTL
			pCurWanInfo = pCurWanInfo->pNextWanSxbInfo;
		} //end_while

		SleepEx(500,FALSE);

	} while ( WaitForSingleObject( terminateEvent, 0) != WAIT_OBJECT_0);

Exit:
	return returnStatus;
}  // end DoWanStats

//
// rs232_Terminate_MIB_Data_Collection
//    Collects all the data needed to update the MIB structure
//
// Notes:
//      This routine is spawned as a thread from the init routine. It runs
//  off a timer tick in .1 second increments.
//
// Return Codes:
//
// Error Codes:
//
void rs232_Terminate_MIB_Data_Collection(
			IN	PWAN_SXB_INFO pBaseWanInfo,
			IN	PSXB_PORT_INFO pBaseSxbPortInfo)
{
BOOL				bSuccess;
BOOL				firstPassFlag;
PWAN_SXB_INFO		pDelWanInfo;
PWAN_SXB_INFO		pCurWanInfo;
HANDLE				hSxbDevice = NULL;       
PSXB_CIRCUIT_INFO	pCircuitInfo;
PSXB_CIRCUIT_INFO	pNextCircuitInfo;
PSXB_PORT_INFO		pCurPortInfo;
PSXB_PORT_INFO		pDelPortInfo;
DWORD				returnStatus = 0;
	
	// Signal to stop
	SetEvent(terminateEvent); //This will notify the collection threads

	// Wait on the data collector thread to terminate
	returnStatus = WaitForSingleObject(hSxbCollectionThread,1000);
	switch (returnStatus) {
	case WAIT_OBJECT_0:
#ifdef SNMP_DLL_DEBUG
		wsprintf(DbgBuf,"***I*** WAN: Wait for collection terminate completed\n");
		OutputDebugString(DbgBuf);
#endif
		break;
	
	case WAIT_TIMEOUT:
#ifdef SNMP_DLL_DEBUG
		wsprintf(DbgBuf,"***E*** WAN: Wait for collection terminate timed out\n");
		OutputDebugString(DbgBuf);
#endif
		break;
	
	case WAIT_ABANDONED:
	default:
#ifdef SNMP_DLL_DEBUG
		wsprintf(DbgBuf,
				"***E*** FREL: Wait for collection terminate failed, error=%x\n",
				GetLastError()
				);
		OutputDebugString(DbgBuf);
#endif
		break;
	}

 	if ((pCurWanInfo = pBaseWanInfo) == NULL) {
#ifdef SNMP_DLL_DEBUG
	    OutputDebugString("***E*** WAN: rs232_Terminate_MIB_Data_Collection Failure\n");
#endif
		return;
	}
    
	firstPassFlag = TRUE;
	while (pCurWanInfo != NULL)
    {
		if (hSxbDevice != pCurWanInfo->hSxbPort)
		{
			DS_CLOSE Close;
			Close.hStream = pCurWanInfo->VCWanDevice;
			hSxbDevice = pCurWanInfo->hSxbPort;

			// Close the handle depending on the snid
			bSuccess = DeviceIoControl( hSxbDevice,
												 (ULONG)IOCTL_DS_CLOSE,
												 &Close, sizeof( Close ),
												 &Close, sizeof( Close ),
												 &(pCurWanInfo->dwBytesWritten), NULL );
			if( !bSuccess  )
			{
				returnStatus = GetLastError();
#ifdef SNMP_DLL_DEBUG
				wsprintf(DbgBuf,"***W*** WAN: Failure on IOCTL_S_CLOSE\n= %x\n",
								returnStatus);
				OutputDebugString(DbgBuf);
#endif
				hSxbDevice = NULL;
			}
			else
			{
				CloseHandle( pCurWanInfo->hSxbPort);
			}
		} // end if
		pCurWanInfo->hSxbPort = NULL;
		pDelWanInfo = pCurWanInfo;
		pCurWanInfo = pCurWanInfo->pNextWanSxbInfo;

		if (firstPassFlag)
		{
			// Don't free the first SXB Info structure. It was a global var
			firstPassFlag = FALSE;
		}
		else
		{
			// Free the other SXB Info structures. They were allocated
			SNMP_free(pDelWanInfo);
		}
	} // end while

	// Delete the SxbPortInfo structures
	pCurPortInfo = pBaseSxbPortInfo;
	while (pCurPortInfo != NULL)
	{
		// Delete the circuit tables for each port
		pCircuitInfo = pCurPortInfo->pCircuitList;
		while (pCircuitInfo !=NULL)
		{
			pNextCircuitInfo = pCircuitInfo->pNextSxbCircuitInfo;
			SNMP_free(pCircuitInfo);
			pCircuitInfo = pNextCircuitInfo;
		}

		// Release the port Info structures
		pDelPortInfo = pCurPortInfo;
		pCurPortInfo = pCurPortInfo->pNextSxbPortInfo;
		SNMP_free (pDelPortInfo);
	}
}  // end rs232_Terminate_MIB_Data_Collection

//
// rs232_Init_MIB_Data_Structures
//    Collects all the data needed to update the MIB structure
//
// Notes:
//      This routine is spawned as a thread from the init routine. It runs
//  off a timer tick in .1 second increments.
//
// Return Codes:
//
// Error Codes:
//
long rs232_Init_MIB_Data_Structures(
					IN PWAN_SXB_INFO pWanInfo,
					IN PSXB_PORT_INFO pSxbPortInfo
					)
{
   
	PWAN_SXB_INFO   pCurWanInfo;
	PSXB_PORT_INFO  pCurPortInfo;
	BOOL			firstTimeThrough = TRUE;

	if ((pCurWanInfo = pWanInfo) == NULL)
	{
		//DebugBreak();
		return -1;
	}

	if ((pCurPortInfo = pSxbPortInfo) == NULL)
	{
		//DebugBreak();
		return -1;
	}

    // Initialize the WanInfo structures to access the Data Structures

	// The first list item has no previous list item
	pCurWanInfo->pPreviousWanSxbInfo = NULL;

	while (pCurPortInfo != NULL)
	{
		// Build the first one for PORT ioctl
		strcpy(pCurWanInfo->DeviceName, "\\\\.\\");
		strcat(pCurWanInfo->DeviceName, pCurPortInfo->DeviceName);
		pCurWanInfo->IoctlType = PORT_IOCTL_NDX_PORT_DATA;
		pCurWanInfo->AdapterId = 0;
		pCurWanInfo->PortId = 0;
		pCurWanInfo->Snid = pCurPortInfo->Snid;
		pCurWanInfo->upData.pPortMibData= (PVOID)&(pCurWanInfo->XIoctl.Data);

		//The wan statistics for the port are identified by WAN_PORT_NAME
		StrToWStr(  pCurWanInfo->WanName,
					ID_STR_SXB_WAN_STATS,
					strlen(ID_STR_SXB_WAN_STATS) + 1 );

		// Allocate the first config IOCTL
		pCurWanInfo->pNextWanSxbInfo = SNMP_malloc(sizeof(struct WAN_SXB_INFO));
		if (pCurWanInfo->pNextWanSxbInfo == NULL )
		{
			//DebugBreak();
			return 4;
		}

		// Go ahead and init the previous pointer for the SYNC PORT IOCTL
		pCurWanInfo->pNextWanSxbInfo->pPreviousWanSxbInfo = pCurWanInfo;

		// Build the first one for config
		pCurWanInfo = pCurWanInfo->pNextWanSxbInfo;

		pCurWanInfo->IoctlType = PORT_IOCTL_NDX_SYNC_PORT_DATA;
		strcpy(pCurWanInfo->DeviceName, "\\\\.\\");
		strcat(pCurWanInfo->DeviceName, pCurPortInfo->DeviceName);
		pCurWanInfo->AdapterId = 0;
		pCurWanInfo->PortId = 0;
		pCurWanInfo->Snid = pCurPortInfo->Snid;
		pCurWanInfo->upData.pSyncPortMibData = (PVOID)&(pCurWanInfo->XIoctl.Data);
#ifdef SNMP_DLL_DEBUG
		wsprintf(DbgBuf,
				"***I*** WAN: Initial Port Type Location = 0x%lx\n",
				&(pCurWanInfo->upData.pPortMibData->rs232PortType));
		OutputDebugString(DbgBuf);
#endif

		//The wan statistics for the port are identified by WAN_PORT_NAME
		StrToWStr(  pCurWanInfo->WanName,
					ID_STR_SXB_WAN_STATS,
					strlen(ID_STR_SXB_WAN_STATS) + 1 );

		// Advance to the next Port Info Object after the config IOCTL
		pCurPortInfo = pCurPortInfo->pNextSxbPortInfo;

		if (pCurPortInfo != NULL)
		{
			pCurWanInfo->pNextWanSxbInfo = SNMP_malloc(sizeof(struct WAN_SXB_INFO));
			if (pCurWanInfo->pNextWanSxbInfo == NULL )
			{
				//DebugBreak();
				return 4;
			}

			// Go ahead and init the previous pointer for the port 2 stats IOCTL
			pCurWanInfo->pNextWanSxbInfo->pPreviousWanSxbInfo = pCurWanInfo;
		}
		else
		{
				pCurWanInfo->pNextWanSxbInfo = NULL;
		}

		// Work on the next Stats Ioctl
		pCurWanInfo = pCurWanInfo ->pNextWanSxbInfo; 
	}
	return 0;
} //end rs232_Init_MIB_Data_Structures()

//
// rs232_Init_MIB_Data_Structures
//    Initialize the SXB port information from the registry
//
// Notes:
//      The \\HKEY_LOCAL_MACHINE\Sotware\Microsoft\SNMP\Parameters\WanLinksHDLCMIB\
//  key will be used to enumerate adaters and their ports to collect information
//	needed to build the port info structure list. This list is used to build the 
//	MIB and IOCTL list as well.
//
// Return Codes:
//
// Error Codes:
//
long rs232_Init_Sxb_Port_Info(
		IN PSXB_PORT_INFO pSxbPortInfo
		)
{
	HKEY			hKeyMib;
	HKEY			hKeyAdapter;
	HKEY			hKeyPort;
    DWORD			retCodeAdapter;
	DWORD			retCodePort;
	DWORD			retCodePortValue;
	CHAR			AdapterKeyName[MAX_PATH];
	CHAR			AdapterKeyPathName[MAX_PATH];
	CHAR			PortKeyName[MAX_PATH];
	CHAR			PortKeyPathName[MAX_PATH];
	int				i;
	int				j;
	int				k;
	BYTE *			pbData;
	DWORD			cbData;
	CHAR			ValueName[MAX_VALUE_NAME];
	DWORD			cbValueName = MAX_VALUE_NAME;
	DWORD			dwType;
	BOOL			firstTimeThrough = TRUE;
	PSXB_PORT_INFO	pCurPortInfo = pSxbPortInfo;
	CHAR			WANLinksParamtersPath[MAX_PATH];

	//Build the pathname to the WANLinks SNMP Info
	strcpy(WANLinksParamtersPath, c_pszNTServiceBase);
	strcat(WANLinksParamtersPath,"\\SNMP\\Parameters\\");
	strcat(WANLinksParamtersPath, c_pszSNMP_RS232);


	// Open the key to the LAPB Links SNMP area
	retCodeAdapter = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
							WANLinksParamtersPath,
							0,
							KEY_ENUMERATE_SUB_KEYS |
							KEY_EXECUTE |
							KEY_QUERY_VALUE,
							&hKeyMib);

	if (retCodeAdapter != ERROR_SUCCESS)
	{
		//DebugBreak();
		return -1;
	}

	// Walk the Adapter sub-keys
	for (i=0, retCodeAdapter = ERROR_SUCCESS; retCodeAdapter == ERROR_SUCCESS; i++)
	{
		retCodeAdapter = RegEnumKey (hKeyMib, i, AdapterKeyName, MAX_PATH);
		if (retCodeAdapter == (DWORD)ERROR_SUCCESS)
		{
			// Build the name of the Adapter Key
			strcpy(AdapterKeyPathName, WANLinksParamtersPath);
			strcat(AdapterKeyPathName,"\\");
			strcat(AdapterKeyPathName, AdapterKeyName);

			// Open the key to the Adapter
#ifdef SNMP_DLL_DEBUG
			wsprintf(DbgBuf,"***I*** Opening Registry Key for Adapter%s\n",AdapterKeyName);
			OutputDebugString(DbgBuf);
#endif
			retCodeAdapter = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
									AdapterKeyPathName,
									0,
									KEY_ENUMERATE_SUB_KEYS |
									KEY_EXECUTE |
									KEY_QUERY_VALUE,
									&hKeyAdapter);
			
			if (retCodeAdapter != ERROR_SUCCESS)
			{
				//DebugBreak();
				return -1;
			}

			pbData  = SNMP_malloc(MAX_DATA_LEN);

			// Walk the Port sub-keys
			for (j=0, retCodePort = ERROR_SUCCESS; retCodePort == ERROR_SUCCESS; j++)
			{
				retCodePort = RegEnumKey (hKeyAdapter, j, PortKeyName, MAX_PATH);
				if (retCodePort == (DWORD)ERROR_SUCCESS)
				{
					// Build the name of the Adapter Key
					strcpy(PortKeyPathName, AdapterKeyPathName);
					strcat(PortKeyPathName,"\\");
					strcat(PortKeyPathName, PortKeyName);

					//// If this is the first pass, we have a port info structure,
					//// If not we need to tack a new one on the end of thelist
					if (firstTimeThrough)
					{
						firstTimeThrough = FALSE;
					}
					else
					{
						pCurPortInfo->pNextSxbPortInfo = SNMP_malloc(sizeof(SXB_PORT_INFO));
						pCurPortInfo = pCurPortInfo->pNextSxbPortInfo;
						pCurPortInfo->pNextSxbPortInfo = NULL;
						pCurPortInfo->pCircuitList = NULL;
						pCurPortInfo->ProtocolId = SXB_PROTOCOL_ID_NONE;
					}
					
					// Build the name of the adapter port object for SXB driver IOCTLs
					// It looks like "DigiDxb2"
					strcpy(pCurPortInfo->DeviceName, AdapterKeyName);

					// Open the key to the Adapter
					retCodePort = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
											PortKeyPathName,
											0,
											KEY_ENUMERATE_SUB_KEYS |
											KEY_EXECUTE |
											KEY_QUERY_VALUE,
											&hKeyPort);
					
					if ( retCodePort != ERROR_SUCCESS )
					{
						//DebugBreak();
						return -1;
					}


					for (k=0, retCodePortValue=ERROR_SUCCESS; retCodePortValue==ERROR_SUCCESS; k++)
					{
						cbData = MAX_DATA_LEN;
						cbValueName = MAX_DATA_LEN;
		
						retCodePortValue = RegEnumValue ( hKeyPort,		// Key handle returned from RegOpenKeyEx.
														  k,			// Value index, taken from listbox.
														  ValueName,	// Name of value.
														  &cbValueName,	// Size of value name.
														  NULL,			// Reserved, dword = NULL.
														  &dwType,		// Type of data.
														  pbData,		// Data buffer.
														  &cbData);		// Size of data buffer.

						if ( retCodePortValue != ERROR_SUCCESS )
						{
							if (retCodePortValue != ERROR_NO_MORE_ITEMS) 
							{
								//DebugBreak();
								return -1;
							}
						}
						else
						{
							// Determine the type of key and add it into the port structure
							if (strcmp(ValueName, c_pszSNMP_Circuits) == 0)
							{
								// Parse the ciruits list and add them in

							}
							// Check for protocol identifier registry key
							else if (strcmp(ValueName, c_pszSNMP_ProtocolIdentifier) == 0)
							{
								// Test for frame relay
								if (strcmp(pbData, c_pszValueFRProtocol) == 0)
								{
									pCurPortInfo->ProtocolId = SXB_PROTOCOL_ID_FRAME_RELAY;
								}
								// Test for X.25
								else if (strcmp(pbData, c_pszValueX25Protocol) == 0)
								{
									pCurPortInfo->ProtocolId = SXB_PROTOCOL_ID_X25;
								}
							}
							else if (strcmp(ValueName, DXB_REGVAL_LINE_SNID) == 0)
							{
								PULONG pSnid = (PVOID)pbData;
								if ( dwType == REG_DWORD && cbData >= sizeof *pSnid )
									pCurPortInfo->Snid = *pSnid;
							}
					
						} // end if
					} // end for

					// Close the Port Key
					RegCloseKey (hKeyPort);   // Close the key handle.
				}
			}

			// Free the memory for the key
			SNMP_free(pbData);
		

			// Close the Adapter Key
			RegCloseKey (hKeyAdapter);   // Close the key handle.
		
			// Update the Port Count
			portCount += j-1;
		}
	}

	// Initialize the number of ports available in the MIB
	MIB_rs232NumberStor = portCount;
	RegCloseKey (hKeyMib);   // Close the key handle.
	return 0;
}

// Utilities to play games with unicode strings
int StrToWStr( LPWSTR wszDest, LPSTR szSrc, LONG count )
{
   LONG i;

   for( i = 0; i < count; i++ )
   {
      wszDest[i] = szSrc[i];
   }

   return( i-1 );
}

USHORT WstrLength( IN LPWSTR Wstr )   
/*++

Routine Description:

   Determines the number of bytes used by the passed in Wstr

Arguments:

   Wstr - Pointer to wide character string.

Return Value:

   Length, in bytes.
   
--*/
{
   USHORT Length=0;

   while( *Wstr++ )
   {
      Length += sizeof(WCHAR);
   }
   return( Length );
}  // end DigiWstrLength
