isEnetOnline: a tool to detect ethernet connect on Windows Mobile

isEnetOnline

During some testing of the event notifcation interface on a PocketPC device, I found that some essential events are declared but will never be fired. Two of these unsupported events are: NOTIFICATIONEVENTNETCONNECT and NOTIFICATIONEVENTNETDISCONNECT. So I started a small eVC4 workspace for ITC Pocket PC with Windows Mobile 2003 with one simple test application to play with the mibInterface.dwOperStatus. Then I got an app, that will start another process (given by the command line). This tool is now called iRunOnNet.exe and will launch an exe (ie call “iRunOnNet.exe \windows\calc.exe” to have the caculator come up on ethernet connect), if an ethernet connection (the ITC device designed for has a dock ethernet connector) comes up. You can stop the hidden tool by launching it again with the argument -stop.

As a second goal, I would like to get a simple DLL that will export the status of an ethernet connection. Additionally I made a tool (isOnlineDLLtest.exe) that is used to test the functionallity of the DLL. The DLL only exports one function fnIsEnetOnline(). This will give a 0, if ethernet is offline and 1, if ethernet is online. A second export is the variable nIsEnetOnline which will hold the last status. The isOnlineDllTest uses the function fnIsEnetOnline() in a timer and simply shows a text with the last result of this call.

iRunOnNet is a stand-alone app and does not need isEnetOnline.dll. You can either directly use iRunOnNet to have an application launch on a ethernet network connection or you have your own apllication use isEnetOnline.dll in a timer to check for an ethernet connect. The sources for all this is attached.

Here is the central online check function code:

//isNetworkAlive.h

#include "Iphlpapi.h"
#pragma comment (lib, "Iphlpapi.lib")

int isEnetAlive(void)
{
 TCHAR str[256] = TEXT("\0");
 TCHAR *InterfaceTypes[]={
 L"MIB_IF_TYPE_OTHER",
 L"MIB_IF_TYPE_OTHER",        //1
 L"MIB_IF_TYPE_OTHER",
 L"MIB_IF_TYPE_OTHER",
 L"MIB_IF_TYPE_OTHER",
 L"MIB_IF_TYPE_OTHER",
 L"MIB_IF_TYPE_ETHERNET",    //6
 L"MIB_IF_TYPE_ETHERNET",
 L"MIB_IF_TYPE_ETHERNET",
 L"MIB_IF_TYPE_TOKENRING",    //9
 L"MIB_IF_TYPE_TOKENRING",
 L"MIB_IF_TYPE_TOKENRING",
 L"MIB_IF_TYPE_TOKENRING",
 L"MIB_IF_TYPE_TOKENRING",
 L"MIB_IF_TYPE_TOKENRING",
 L"MIB_IF_TYPE_FDDI",        //15
 L"MIB_IF_TYPE_FDDI",
 L"MIB_IF_TYPE_FDDI",
 L"MIB_IF_TYPE_FDDI",
 L"MIB_IF_TYPE_FDDI",
 L"MIB_IF_TYPE_FDDI",
 L"MIB_IF_TYPE_FDDI",
 L"MIB_IF_TYPE_FDDI",
 L"MIB_IF_TYPE_PPP",            //23
 L"MIB_IF_TYPE_LOOPBACK",    //24
 L"MIB_IF_TYPE_LOOPBACK",
 L"MIB_IF_TYPE_LOOPBACK",
 L"MIB_IF_TYPE_LOOPBACK",
 L"MIB_IF_TYPE_LOOPBACK",
 L"MIB_IF_TYPE_SLIP"            //28
 };
 TCHAR *OperStatus[]={
 L"IF_OPER_STATUS_NON_OPERATIONAL",//0
 L"IF_OPER_STATUS_UNREACHABLE",//1
 L"IF_OPER_STATUS_DISCONNECTED",//2
 L"IF_OPER_STATUS_CONNECTING",//3
 L"IF_OPER_STATUS_CONNECTED",//4
 L"IF_OPER_STATUS_OPERATIONAL"//5
 };

 // Interface name enumeration
 IP_INTERFACE_INFO *pIpInterface = NULL;
 DWORD dwInterfaceSize = 0;

 // Find out the size of the interface table
 if(GetInterfaceInfo(NULL, &dwInterfaceSize) !=
 ERROR_INSUFFICIENT_BUFFER)
 return FALSE;

 pIpInterface = (IP_INTERFACE_INFO *)LocalAlloc(LPTR,
 dwInterfaceSize);
 if(!pIpInterface)
 return FALSE;

 if(GetInterfaceInfo(pIpInterface, &dwInterfaceSize) !=
 NO_ERROR) {
 LocalFree(pIpInterface);
 return FALSE;
 }

 // Walk through the available interfaces
 TCHAR tchInterfaceBuffer[256] = TEXT("\0");
 for(int nInterface = 0; nInterface < pIpInterface->NumAdapters; nInterface++) {
 IP_ADAPTER_INDEX_MAP *pIpAdapterMapEntry = NULL;

 pIpAdapterMapEntry = (IP_ADAPTER_INDEX_MAP *)&pIpInterface->Adapter[nInterface];
 wsprintf(tchInterfaceBuffer, TEXT("Interface Name: %s Interface Index: %d"),
 pIpAdapterMapEntry->Name,
 pIpAdapterMapEntry->Index); 

 if (TRUE) //(wcsicmp (pIpAdapterMapEntry->Name, L"PRISMNDS1") == 0)
 {
 MIB_IFROW mibInterface;
 memset(&mibInterface, 0, sizeof(MIB_IFROW));

 // To get a specific interface entry, just set the dwIndex
 // field before calling the GetIfEntry function
 mibInterface.dwIndex = pIpAdapterMapEntry->Index;
 if(GetIfEntry(&mibInterface) != NO_ERROR)
 return FALSE;
 // look if it is Ethernet and is Operational
 if ( (mibInterface.dwType == 0x06) && (mibInterface.dwOperStatus == 0x05) )
 return TRUE;
 }
 }
 return FALSE;
}

Download source and binaries: [Download not found]

2 Comments

  1. JL says:

    While I have not played with GetIfEntry recently, your interaction with the adapters returned by GetInterfaceInfo presumes that there is only one Ethernet adapter in the system. I would not be surprised to find that the Wi-Fi NIC is also classified as an ethernet adapter in that API; it is in several others. So, isEnetAlive may tell you that Ethernet is alive when the terminal is un-docked but has a Wi-Fi connection.

  2. admin says:

    Yes, you are right. One cannot be sure, that the interfaces are typed correctly. Although the code is looking for ethernet only, a adapter that identifies as an ethernet adapter will also trigger the true condition.

    We find such ugly incomplete incorrect implementations often, but this is not part of the code and discussion here.

    regards and thanks for the comment

    Josef

Leave a Reply