You can configure two types of connection settings using the Connection Manager: Internet and Work. Both maintain connection parameters for the type of resource you are trying to access.
The Internet connection setting is used for a straightforward dial-up or network connection to the Internet when attempting to access an Internet-style dot-address (such as XX.XX.XX.XX or name.domain.com).
The Work connection setting offers a variety of connection options, including support for proxy servers, virtual private networks (VPNs), and ActiveSync synchronization. This option also supports the capability to address a WINS network address on a private LAN.
So, what does this mean for you as an application developer? Basically, depending on the type of resource you are requesting, the Connection Manager will choose which connection to use in order to get you access to the network resource. If you are attempting to get something with a fully qualified Internet URL, the Connection Manager will use the Internet setting; otherwise, it will choose Work. Figure 7.2 shows the Work setting configuration dialog box.
It is generally recommended that a user set all three of the Connection Manager's configuration drop-down options (Internet, Work, and Network card) for the Work connection setting. By doing this, the device can easily connect to the Internet, use a VPN connection, synchronize with ActiveSync, and use local resources without having to reconfigure Connection Manager whenever the environment changes.
Before you can use the Connection Manager to manage your network communications, you must first make sure that it is available to be used. This is done by simply calling the ConnMgrApiReadyEvent() API, which is defined as follows:
HANDLE WINAPI ConnMgrApiReadyEvent();
The function takes no parameters, but returns a handle to an event that will become signaled when the Connection Manager is ready. Remember that you need to call the CloseHandle() function for the event that is returned.
Confirming that the Connection Manager is available is relatively straightforward:
// Make sure Connection Manager is ready HANDLE hConnMgr = NULL; BOOL bAvailable = FALSE; hConnMgr = ConnMgrApiReadyEvent(); if(!hConnMgr) return FALSE; // Wait for 1 second to see if Connection Manager has // signaled the event DWORD dwResult = WaitForSingleObject(hConnMgr, 1000); if(dwResult == WAIT_OBJECT_0) bAvailable = TRUE; // Close the event handle if(hConnMgr) CloseHandle(hConnMgr); // Did it connect ok? if(!bAvailable) return FALSE; // Do something now that Connection Manager is ready
The next thing you need to do before you can make a network request is to determine the globally unique identifier (GUID) for the type of object you are requesting, based on its Uniform Resource Locator (URL). The GUID you are returned has been deemed the best network connection to use for the destination that you passed to the function, based on the connection cost, latency, and so on. You then use the identifier when you eventually establish your connection.
To determine the best network connection to use, you need to call the ConnMgrMapURL() function, which is defined as follows:
HRESULT WINAPI ConnMgrMapURL(LPCTSTR pwszURL, GUID *pguid, DWORD *pdwIndex);
The first parameter, pwszURL, is the location of the object you are requesting, and should be in standard Internet format (for example, http://www.furrygoat.com/index.html). You can also use the URL functions described in Chapter 2, such as InternetCreateUrl(), to correctly build a resource locator.
The next parameter, pguid, is a pointer that receives the GUID of the destination network. Finally, you have pdwIndex, which is an optional parameter that serves as a pointer to a DWORD index variable. The index is used if there were more than one network mapping for the destination resource. The first time you call the function, you should set the value of the index to 0. If there are additional mappings, then ConnMgrMapURL() will increment the index value, which should be passed into each additional call into ConnMgrMapURL().
The following example determines the best network connection to use for a particular URL:
// Map a local and remote URL TCHAR tchLocalUrl[256] = TEXT("\0"); TCHAR tchRemoteUrl[256] = TEXT("\0"); HRESULT hResult = S_OK; wsprintf(tchLocalUrl, TEXT("http://fifi/report.txt")); wsprintf(tchRemoteUrl, TEXT("http://fifi.someserver. com/report.txt")); // Map a local URL {a1182988-0d73-439e-87ad-2a5b369f808b} GUID guidNetworkObject; DWORD dwIndex = 0; if(ConnMgrMapURL(tchLocalUrl, &guidNetworkObject, &dwIndex) == E_FAIL) { OutputDebugString(TEXT("Could not map a local request to a network identifier")); return FALSE; } // Map a remote URL {436ef144-b4fb-4863-a041-8f905a62c572} dwIndex = 0; if(ConnMgrMapURL(tchRemoteUrl, &guidNetworkObject, &dwIndex) == E_FAIL) { OutputDebugString(TEXT("Could not map a remote request to a network identifier")); return FALSE; }
If you want to get more information about a particular network identifier, or just enumerate the available identifiers that are on the device, you can use the ConnMgrEnumDestinations() function, which is defined as follows:
HRESULT WINAPI ConnMgrEnumDestinations(int nIndex, CONNMGR_DESTINATION_INFO *pDestInfo);
The first parameter is the index value of the identifier for which you want to get more information. If you want to enumerate all of the available identifiers, this should be set to 0 the first time the function is called, and incremented for each additional time you call the function. The other parameter, pDestInfo, is a pointer to a CONNMGR_DESTINATION_INFO structure, which contains the network information for the index specified.
The function will return an S_OK value if it is successful; otherwise, you will be returned an E_FAIL value.
The CONNMGR_DESTINATION_INFO structure looks like the following:
typedef struct _CONNMGR_DESTINATION_INFO { GUID guid; TCHAR szDescription[CONNMGR_MAX_DESC]; } CONNMGR_DESTINATION_INFO;
The structure contains only two pieces of information: the GUID that is associated with the network connection, and a null-terminated string containing the description of the network.
To enumerate all of the available network identifiers, you could do the following:
// Enumerate the available network identifiers DWORD dwEnumIndex = 0; BOOL fLoop = TRUE; TCHAR tchNetNameInfo[256] = TEXT("\0"); CONNMGR_DESTINATION_INFO networkDestInfo; // Walk through the list of Networks do{ memset(&networkDestInfo, 0, sizeof(CONNMGR_DESTINATION_INFO)); if(ConnMgrEnumDestinations(dwEnumIndex, &networkDestInfo) == E_FAIL) { fLoop = FALSE; break; } // If we got a network ID's information, show the // description wsprintf(tchNetNameInfo, TEXT("Network Name:%s"), networkDestInfo.szDescription); MessageBox(NULL, tchNetNameInfo, TEXT("Available Networks"), MB_OK|MB_ICONINFORMATION); dwEnumIndex++; } while(fLoop);