GetInterfaceConfigInfo Sample

[This is preliminary documentation and subject to change.]

DWORD
APIENTRY
GetInterfaceConfigInfo(
    IN     DWORD  dwIndex,
    IN OUT PVOID  pvConfig,
    IN OUT PDWORD pdwSize
    )
/*++
  Routine Description
      Called by the IP Router Manager to retrieve an
      interface's configuration. Usually this is because an admin
      utility is displaying this information. The Router Manager calls
      us with a NULL config and ZERO size. We return the required size
      to it. It then allocates the needed memory and calls us a second
      time with a valid buffer.  We validate parameters each time and
      copy out our config if we can

  Arguments
      dwIndex   Index of the interface being queried
      pvConfig  Pointer to buffer to store the config
      pdwSize   Size of the buffer

  Return Value
      ERROR_INSUFFICIENT_BUFFER If the size of the buffer is too small
      ERROR_INVALID_PARAMETER
      ERROR_INVALID_DATA
      NO_ERROR

--*/
{
    PNT_IF      pIf;
    PLIST_ENTRY pleNode;
    PINTRNL_IF  pBind;
    ULONG       i;
    
    PSAMPLE_PROTOCOL_INTERFACE_INFO pIfInfo;

    
    EnterProtocolApi();

    TraceEnter("GetInterfaceConfigInfo");
    
    if(pdwSize == NULL)
    {
        Trace0(ERR,
               "GetInterfaceConfigInfo: Router Manager called us with NULL size");

        TraceLeave("GetInterfaceConfigInfo");

        ExitProtocolApi();

        return ERROR_INVALID_PARAMETER;
    }

    EnterCriticalSection(&g_csIfListLock);

    pIf = GetIfBlockGivenIndex(dwIndex);

    if(pIf == NULL)
    {
        LeaveCriticalSection(&g_csIfListLock);
        
        Trace1(ERR,
               "GetInterfaceConfigInfo: Interface %d does not exist",
               dwIndex);

        TraceLeave("GetInterfaceConfigInfo");

        ExitProtocolApi();

        return ERROR_INVALID_PARAMETER;
    }

    if(*pdwSize < SIZEOF_PROTO_IF_INFO(pIf->ulNumBindings))
    {
        *pdwSize = SIZEOF_PROTO_IF_INFO(pIf->ulNumBindings);

        LeaveCriticalSection(&g_csIfListLock);

        TraceLeave("GetInterfaceConfigInfo");

        ExitProtocolApi();

        return ERROR_INSUFFICIENT_BUFFER;
    }

    *pdwSize = SIZEOF_PROTO_IF_INFO(pIf->ulNumBindings);
    
    if(pvConfig == NULL)
    {
        LeaveCriticalSection(&g_csIfListLock);
        
        Trace0(ERR,
               "GetInterfaceConfigInfo: Router Manager called us with NULL config buffer");

        TraceLeave("GetInterfaceConfigInfo");

        ExitProtocolApi();

        return ERROR_INVALID_PARAMETER;
    }

    //
    // So we have a good buffer of the right size
    // Copy out the info
    //

            
    pIfInfo = (PSAMPLE_PROTOCOL_INTERFACE_INFO)pvConfig;

    pIfInfo->ulNumBindings = pIf->ulNumBindings;

    for(pleNode  = pIf->leInternalIfHead.Flink, i = 0;
        pleNode != &pIf->leInternalIfHead;
        pleNode  = pleNode->Flink, i++)
    {
        pBind = CONTAINING_RECORD(pleNode, INTRNL_IF, leInternalIfLink);

        pIfInfo->rgbiInfo[i].dwAddress  = pBind->dwAddress;
        pIfInfo->rgbiInfo[i].dwMask     = pBind->dwMask;
        pIfInfo->rgbiInfo[i].bEnabled   = pBind->bEnabled;
    }

    ASSERT(i == pIf->ulNumBindings);

    //
    // If we had only one address we will return 0.0.0.0 as the address
    // even if we know what the current address is
    //
    
    if(pIf->ulNumBindings == 1)
    {
        pIfInfo->rgbiInfo[0].dwAddress  = 0x00000000;
        pIfInfo->rgbiInfo[0].dwMask     = 0x00000000;
    }

    LeaveCriticalSection(&g_csIfListLock);

    TraceLeave("GetInterfaceConfigInfo");

    ExitProtocolApi();

    return NO_ERROR;
}