/********************************************************************/
/**               Copyright(c) 1995 Microsoft Corporation.	       **/
/********************************************************************/

//***
//
// Filename:    mibapi.c
//
// Description: Contains code to manipulate MIB apis
//
// History:     May 11,1995	    NarenG		Created original version.
//
#include "dimsvcp.h"
#include <dimsvc.h>     // Generated by MIDL

//**
//
// Call:        RMIBEntryCreate
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID or non-zero return code from
//              MIBEntryCreate
//
// Description: Simply called the appropriate router manager to do the real 
//              work.
//
DWORD
RMIBEntryCreate(
    IN  MIB_SERVER_HANDLE           hMibServer,
    IN  DWORD                       dwPid,
    IN  DWORD                       dwRoutingPid,
    IN  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    DWORD dwAccessStatus;
    DWORD dwRetCode        = NO_ERROR;
    DWORD dwTransportIndex = GetTransportIndex( dwPid );

    //
    // Check if caller has access
    //

    if ( DimSecObjAccessCheck( DIMSVC_ALL_ACCESS, &dwAccessStatus) != NO_ERROR)
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwAccessStatus )
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryCreate( 
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry );

    return( dwRetCode );
}

//**
//
// Call:        RMIBEntryDelete
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID or non-zero return code from
//              MIBEntryCreate
//
// Description: Simply called the appropriate router manager to do the real 
//              work.
//
DWORD
RMIBEntryDelete(
    IN  MIB_SERVER_HANDLE           hMibServer,
    IN  DWORD                       dwPid,
    IN  DWORD                       dwRoutingPid,
    IN  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    DWORD dwAccessStatus;
    DWORD dwRetCode        = NO_ERROR;
    DWORD dwTransportIndex = GetTransportIndex( dwPid );

    //
    // Check if caller has access
    //

    if ( DimSecObjAccessCheck( DIMSVC_ALL_ACCESS, &dwAccessStatus) != NO_ERROR)
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwAccessStatus )
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryDelete(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry );

    return( dwRetCode );
}

//**
//
// Call:        RMIBEntrySet
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID or non-zero return code from
//              MIBEntryCreate
//
// Description: Simply called the appropriate router manager to do the real 
//              work.
//
DWORD
RMIBEntrySet(
    IN  MIB_SERVER_HANDLE           hMibServer,
    IN  DWORD                       dwPid,
    IN  DWORD                       dwRoutingPid,
    IN  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    DWORD dwAccessStatus;
    DWORD dwRetCode        = NO_ERROR;
    DWORD dwTransportIndex = GetTransportIndex( dwPid );

    //
    // Check if caller has access
    //

    if ( DimSecObjAccessCheck( DIMSVC_ALL_ACCESS, &dwAccessStatus) != NO_ERROR)
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwAccessStatus )
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntrySet(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry );

    return( dwRetCode );
}

//**
//
// Call:        RMIBEntryGet
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID 
//              ERROR_NOT_ENOUGH_MEMORY
//              non-zero return code from MIBEntryGet
//
// Description: Simply called the appropriate router manager to do the real
//              work.
//
//
DWORD
RMIBEntryGet(
    IN      MIB_SERVER_HANDLE           hMibServer,
    IN      DWORD                       dwPid,
    IN      DWORD                       dwRoutingPid,
    IN OUT  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    LPBYTE pOutputBuf       = NULL;
    DWORD  dwOutputBufSize  = 0;
    DWORD  dwRetCode        = NO_ERROR;
    DWORD  dwTransportIndex = GetTransportIndex( dwPid );

    //
    // We do not do access check for MIB Get apis since these are called
    // by iphlpapi.dll which can be run in the user's context. It is assumed
    // that the various mibs will take care of their own security.
    //

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    //
    // First get the size of the required entry
    //

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryGet(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                NULL );

    if ( dwRetCode != ERROR_INSUFFICIENT_BUFFER )
    {
        return( dwRetCode );
    }

    pOutputBuf = MIDL_user_allocate( dwOutputBufSize );

    if ( pOutputBuf == NULL )
    {
        return( ERROR_NOT_ENOUGH_MEMORY );
    }

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryGet(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                pOutputBuf );
    if ( dwRetCode == NO_ERROR )
    {
        pInfoStruct->dwMibOutEntrySize = dwOutputBufSize;
        pInfoStruct->pMibOutEntry      = pOutputBuf;
    }
    else
    {
        pInfoStruct->dwMibOutEntrySize = 0;
        pInfoStruct->pMibOutEntry      = NULL;
        MIDL_user_free( pOutputBuf );
    }

    return( dwRetCode );
}

//**
//
// Call:        RMIBEntryGetFirst
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID
//              ERROR_NOT_ENOUGH_MEMORY
//              non-zero return code from MIBEntryGetFirst
//
// Description: Simply called the appropriate router manager to do the real
//              work.
//
//
DWORD
RMIBEntryGetFirst(
    IN      MIB_SERVER_HANDLE           hMibServer,
    IN      DWORD                       dwPid,
    IN      DWORD                       dwRoutingPid,
    IN OUT  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    LPBYTE pOutputBuf       = NULL;
    DWORD  dwOutputBufSize  = 0;
    DWORD  dwRetCode        = NO_ERROR;
    DWORD  dwTransportIndex = GetTransportIndex( dwPid );

    //
    // We do not do access check for MIB Get apis since these are called
    // by iphlpapi.dll which can be run in the user's context. It is assumed
    // that the various mibs will take care of their own security.
    //

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    //
    // First get the size of the required entry
    //

    dwRetCode=gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryGetFirst(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                NULL );

    if ( dwRetCode != ERROR_INSUFFICIENT_BUFFER )
    {
        return( dwRetCode );
    }

    pOutputBuf = MIDL_user_allocate( dwOutputBufSize );

    if ( pOutputBuf == NULL )
    {
        return( ERROR_NOT_ENOUGH_MEMORY );
    }

    dwRetCode=gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryGetFirst(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                pOutputBuf );

    if ( dwRetCode == NO_ERROR )
    {
        pInfoStruct->dwMibOutEntrySize = dwOutputBufSize;
        pInfoStruct->pMibOutEntry      = pOutputBuf;
    }
    else
    {
        pInfoStruct->dwMibOutEntrySize = 0;
        pInfoStruct->pMibOutEntry      = NULL;
        MIDL_user_free( pOutputBuf );
    }

    return( dwRetCode );
}

//**
//
// Call:        RMIBEntryGetNext
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID
//              ERROR_NOT_ENOUGH_MEMORY
//              non-zero return code from MIBEntryGetNext
//
// Description: Simply called the appropriate router manager to do the real
//              work.
//
DWORD
RMIBEntryGetNext(
    IN      MIB_SERVER_HANDLE           hMibServer,
    IN      DWORD                       dwPid,
    IN      DWORD                       dwRoutingPid,
    IN OUT  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    LPBYTE pOutputBuf       = NULL;
    DWORD  dwOutputBufSize  = 0;
    DWORD  dwRetCode        = NO_ERROR;
    DWORD  dwTransportIndex = GetTransportIndex( dwPid );

    //
    // We do not do access check for MIB Get apis since these are called
    // by iphlpapi.dll which can be run in the user's context. It is assumed
    // that the various mibs will take care of their own security.
    //

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    //
    // First get the size of the required entry
    //

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryGetNext(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                NULL );

    if ( dwRetCode != ERROR_INSUFFICIENT_BUFFER )
    {
        return( dwRetCode );
    }

    pOutputBuf = MIDL_user_allocate( dwOutputBufSize );

    if ( pOutputBuf == NULL )
    {
        return( ERROR_NOT_ENOUGH_MEMORY );
    }

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBEntryGetNext(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                pOutputBuf );

    if ( dwRetCode == NO_ERROR )
    {
        pInfoStruct->dwMibOutEntrySize = dwOutputBufSize;
        pInfoStruct->pMibOutEntry      = pOutputBuf;
    }
    else
    {
        pInfoStruct->dwMibOutEntrySize = 0;
        pInfoStruct->pMibOutEntry      = NULL;
        MIDL_user_free( pOutputBuf ); 
    }

    return( dwRetCode );
}

//**
//
// Call:        RMIBGetTrapInfo
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID
//              ERROR_NOT_ENOUGH_MEMORY
//              non-zero return code from MIBGetTrapInfo
//
// Description: Simply called the appropriate router manager to do the real
//              work.
//
DWORD
RMIBGetTrapInfo(
    IN      MIB_SERVER_HANDLE           hMibServer,
    IN      DWORD                       dwPid,
    IN      DWORD                       dwRoutingPid,
    IN OUT  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    LPBYTE pOutputBuf       = NULL;
    DWORD  dwOutputBufSize  = 0;
    DWORD  dwRetCode        = NO_ERROR;
    DWORD  dwTransportIndex = GetTransportIndex( dwPid );

    //
    // We do not do access check for MIB Get apis since these are called
    // by iphlpapi.dll which can be run in the user's context. It is assumed
    // that the various mibs will take care of their own security.
    //

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    //
    // First get the size of the required entry
    //

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBGetTrapInfo(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                NULL );

    if ( dwRetCode != ERROR_INSUFFICIENT_BUFFER )
    {
        return( dwRetCode );
    }

    pOutputBuf = MIDL_user_allocate( dwOutputBufSize );

    if ( pOutputBuf == NULL )
    {
        return( ERROR_NOT_ENOUGH_MEMORY );
    }

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBGetTrapInfo(
                                                dwRoutingPid,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                pOutputBuf );

    if ( dwRetCode == NO_ERROR )
    {
        pInfoStruct->dwMibOutEntrySize = dwOutputBufSize;
        pInfoStruct->pMibOutEntry      = pOutputBuf;
    }
    else
    {
        pInfoStruct->dwMibOutEntrySize = 0;
        pInfoStruct->pMibOutEntry      = NULL;
        MIDL_user_free( pOutputBuf ); 
    }

    return( dwRetCode );
}

//**
//
// Call:        RMIBSetTrapInfo
//
// Returns:     NO_ERROR - Success
//              ERROR_UNKNOWN_PROTOCOL_ID
//              ERROR_NOT_ENOUGH_MEMORY
//              non-zero return code from MIBSetTrapInfo
//              Failures from OpenProcess
//              Failures from DuplicateHandle
//
// Description: Simply called the appropriate router manager to do the real
//              work.
//
DWORD
RMIBSetTrapInfo(
    IN      MIB_SERVER_HANDLE           hMibServer,
    IN      DWORD                       dwPid,
    IN      DWORD                       dwRoutingPid,
    IN      ULONG_PTR                   hEvent,
    IN      DWORD                       dwClientProcessId,
    IN OUT  PDIM_MIB_ENTRY_CONTAINER    pInfoStruct
)
{
    DWORD  dwAccessStatus;
    LPBYTE pOutputBuf       = NULL;
    DWORD  dwOutputBufSize  = 0;
    DWORD  dwRetCode        = NO_ERROR;
    HANDLE hDuplicatedEvent;
    HANDLE hClientProcess;
    DWORD  dwTransportIndex = GetTransportIndex( dwPid );

    //
    // Check if caller has access
    //

    if ( DimSecObjAccessCheck( DIMSVC_ALL_ACCESS, &dwAccessStatus) != NO_ERROR)
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwAccessStatus )
    {
        return( ERROR_ACCESS_DENIED );
    }

    if ( dwTransportIndex == (DWORD)-1 )
    {
        return( ERROR_UNKNOWN_PROTOCOL_ID );
    }

    //
    // Get process handle of the caller of this API
    //

    hClientProcess = OpenProcess(
                            STANDARD_RIGHTS_REQUIRED | SPECIFIC_RIGHTS_ALL,
                            FALSE, 
                            dwClientProcessId);

    if ( hClientProcess == NULL )
    {
        return( GetLastError() );
    }

    //
    // Duplicate the handle to the event
    //

    if ( !DuplicateHandle(  hClientProcess, 
                            (HANDLE)hEvent, 
                            GetCurrentProcess(), 
                            &hDuplicatedEvent,
                            0, 
                            FALSE, 
                            DUPLICATE_SAME_ACCESS ) )
    {
        CloseHandle( hClientProcess );

        return( GetLastError() );
    }

    CloseHandle( hClientProcess );

    //
    // First get the size of the required entry
    //

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBSetTrapInfo(
                                                dwRoutingPid,
                                                hDuplicatedEvent,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                NULL );

    if ( dwRetCode != ERROR_INSUFFICIENT_BUFFER )
    {
        CloseHandle( hDuplicatedEvent );

        return( dwRetCode );
    }

    pOutputBuf = MIDL_user_allocate( dwOutputBufSize );

    if ( pOutputBuf == NULL )
    {
        CloseHandle( hDuplicatedEvent );

        return( ERROR_NOT_ENOUGH_MEMORY );
    }

    dwRetCode = gblRouterManagers[dwTransportIndex].DdmRouterIf.MIBSetTrapInfo(
                                                dwRoutingPid,
                                                hDuplicatedEvent,
                                                pInfoStruct->dwMibInEntrySize,
                                                pInfoStruct->pMibInEntry,
                                                &dwOutputBufSize,
                                                pOutputBuf );

    if ( dwRetCode == NO_ERROR )
    {
        pInfoStruct->dwMibOutEntrySize = dwOutputBufSize;
        pInfoStruct->pMibOutEntry      = pOutputBuf;
    }
    else
    {
        pInfoStruct->dwMibOutEntrySize = 0;
        pInfoStruct->pMibOutEntry      = NULL;
        MIDL_user_free( pOutputBuf ); 
        CloseHandle( hDuplicatedEvent );
    }

    return( dwRetCode );
}
