Mastering Windows Networking (WNet)
A Bit of Theory
Windows CE, being a little brother of its desktop counterpart, now exposes most PC communications capabilities. In many cases, they are just a subset of desktop versions, but still may be quite useful. In this article, we will discuss Windows Networking API (WNet).
Mobile applications may access a remote host's file system and other resources via WNet. Your program can establish and terminate network connections, retrieve configuration information, and so forth. Similar to the desktop, WNet communicates to the outer world via CIFS—Common Internet File System redirector—a module, through which one computer can access another one. Network resources are named using Usiversal Naming Convention (UNC).
As noted above, Windows CE supports only some restricted subsets of WNet API. The main limitations are:
- Microsoft Windows Network is the only network provider currently supported
- No connections are restored during a warm boot. A persistent connection is stored in the Registry and then may be enumerated and retrieved by calling the WNetOpenEnum function with the dwScope parameter set to RESOURCE_REMEMBERED
- You can't use any drive letters to map network resources
- No Mail slots or Named Pipes are supported
- No LaN Manager functions are supported
- Windows CE does not support the concept of a computer or device belonging to a specific network context
- WNet API doesn't communicate over ActiveSync connection
WNet API is compact enough and may be easily overviewed. The following table briefly describes its functions.
| Function | Description |
| Enumeration Functions | |
| WNetOpenEnum | Starts an enumeration of network resources or existing connections |
| WNetEnumResource | Continues a network enumeration started by WNetOpenEnum |
| WNetCloseEnum | Ends a network enumeration started by WNetOpenEnum |
| Connection-related Functions | |
| WNetAddConnection3 | Makes a connection to a network resource and can specify a local name for the resource |
| WNetCancelConnection2 | Terminates an existing network connection |
| WNetConnectionDialog1 | Displays a general browsing dialog box for connecting to a network |
| WNetDisconnectDialog | Displays a dialog box listing all currently connected resources and permits the user to select which resources to disconnect |
| WNetDisconnectDialog1 | Attempts to disconnect from a network; notifies the user of any errors |
| Network Information Functions | |
| WNetGetConnection | Retrieves the remote name of a network resource associated with a local name |
| WNetGetUniversalName | Maps a local path for a network resource to a data structure containing the UNC-based name |
| WNetGetUser | Retrieves user name used to establish a network connection |
Keeping all this stuff in mind, you nevertheless can use WNet pretty effectively for different data transmission tasks. The basic idea here is that, once you know network resource name, you can treat this resource in terms of standard file I/O. The next sections will illustrate some common scenarios your applications may need to implement.
Foreword for MFC Applications
The recent implementation of MFC for Windows CE does not allow using WNet in MFC-based applications. This is a strange fact, but that's how it is. To work around this issue, add the following lines to stdafx.h:
#undef _WINNETWK_ #include <winnetwk.h>
The origin of all this stuff comes from wce.h header files under the MFC Include folder, where you can find that many API are stored even though there are appropriate headers in the SDK folder. But all in all, WNet is easy to revive by such a simple trick.
Enumerating Domain Resources
The first sample we will discuss produces the list of domain network resources. It recursively surfs through domain entries and puts them into the listbox for simplicity. The basic points of this process are listed below:
- Call WNetOpenEnum to open the enumeration
- Sequentually call WNetEnumResource until it returns ERROR_NO_MORE_ITEMS
- On each successful call of WNetEnumResource process, receive NETRESOURCE data
- If the current node is of the RESOURCEUSAGE_CONTAINER type, you can use it as a starting point for nested enumeration
- Close the enumeration handle by using a WNetCloseEnum call
So, please take a look at the following code snippet:
BOOL EnumerateDomainResources(LPNETRESOURCE lpnrStartFrom,
CListBox& ListBox)
{
DWORD dwResult, dwResultEnum, i;
LPNETRESOURCE lpNRBuffer;
DWORD dwBufferSize = 16384;
DWORD dwNumEntries = (DWORD)-1;
HANDLE hEnum;
CString sErr;
dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY,
0, lpnrStartFrom, &hEnum);
if(dwResult != NO_ERROR)
{
sErr.Format(L"WNetOpenEnum err = %d",dwResult);
AfxMessageBox(sErr);
return FALSE;
}
// allocate a buffer
lpNRBuffer = (LPNETRESOURCE) new BYTE[dwBufferSize];
// loop through all the stuff
do
{
dwBufferSize = 16384;
dwNumEntries = (DWORD)-1;
// Get resources
dwResultEnum = WNetEnumResource(hEnum, &dwNumEntries,
lpNRBuffer, &dwBufferSize);
if(dwResultEnum == NO_ERROR)
{
// loop through each of the entries
for(i = 0; i < dwNumEntries; i++)
{
sErr.Format(L"%s",lpNRBuffer[i].lpRemoteName);
ListBox.AddString(sErr);
if( (lpNRBuffer[i].dwUsage & RESOURCEUSAGE_CONTAINER)
== RESOURCEUSAGE_CONTAINER )
{
if( !EnumerateDomainResources(&lpNRBuffer[i],
ListBox) )
{
AfxMessageBox(L"Enumeration Failed");
continue;
}
}
}
}
else if(dwResultEnum != ERROR_NO_MORE_ITEMS)
{
sErr.Format(L"WNetEnumResource err = %d",dwResultEnum);
AfxMessageBox(sErr);
break;
}
}
while(dwResultEnum != ERROR_NO_MORE_ITEMS);
delete lpNRBuffer;
dwResult = WNetCloseEnum(hEnum);
if(dwResult != NO_ERROR)
{
sErr.Format(L"WNetCloseEnum err = %d",dwResult);
AfxMessageBox(sErr);
return FALSE;
}
return TRUE;
}
Let's briefly overview this sample. As we have said before, a call to WNetOpenEnum opens a new enumeration. The first parameter, dwScope, controls what should be enumerated. The sample uses a RESOURCE_GLOBALNET value to get all resources on the network. RESOURCE_CONNECTED and RESOURCE_REMEMBERED will give us active connections and previously stored resources respectively. After enumeration has been initiated, the application sequentually calls WNetEnumResource to achieve the next resource data. You are free to do all required processing of this data depending on resource type and usage. The code snippet takes the simplest way—proceeds nested enumerations. This loop ends up when WNetEnumResource returns ERROR_NO_MORE_ITEMS. And finally, WNetCloseEnum releases the enumeration handle.
