http://www.developer.com/ws/pc/article.php/3424161/Mastering-Windows-Networking-WNet.htm
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: WNet API is compact enough and may be easily overviewed. The following table briefly describes its functions.
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. 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: 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. 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: So, please take a look at the following code snippet: 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. WNet provides several fucntions to establish and to terminate a connection to a network resource. You can use either WNetConnectionDialog1 or WNetAddConnection3 to create a new connection. After a successful call, each one creates a new folder under the '\Network' directory on the device. Notice that the system does not re-connect to mapped resources after a warm reboot. Following are two code snippets to demonstrate the usage of each of these functions. WNetConnectionDialog1 shows a dialog to map the remote name to a local one. WNetAddConnection3 does the same job silently. Both of them may use a pre-defined NETRESOURCE entry to determine what to do. In addition, WNetAddConnection3 allows remembering this connection as persistent; in other words, it'll be remembered after a warm reboot. There are three functions your application may use to cancel the existing connection to network resources: Each function above results in dropping the connection. WNetDisconnectDialog pops up a dialog with all existing connections. The user then can the select desired resource to get disconnected. WNetDisconnectDialog1 and WNetCancelConnection2 do their job silently. The return code indicates the result of the requested operation. Besides, the last two functions may fail depending on existing open files or jobs that use this connection. The user is informed about all errors that occurred. A simple example of this is shown below: And finally, the simplest thing: How can your application conduct I/O operations via WNet? The answer is quite primitive: by using standard file APIs. Once you have detected the UNC name of the network resource and have successfully established a connection to it, you can consider it a 'file' name. Thus, a common flow may look as follows: As a result, the application can handle all required I/O operations on remote hosts. The most obvious usage is printing on network printers. In this case, you can either open the selected resource and then use WriteFile to send data to it or simply call CopyFile. The following sample demonstrates it: This code snippet uses WNet to print on an HP LaserJet printer available somewhere on the network. It uses "Sample.txt" as a test PCL stream to print a cover page of the PCL manual. You may easily create your own printer data by printing some document and choosing the "Print to file" option. As you have seen, WNet under Windows CE is really a simple but useful set of APIs. If your applications work in a networking environment and you want to use network resources, WNet will do its best. Download the accompanying code's zip file here. Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.
Mastering Windows Networking (WNet)
October 20, 2004
A Bit of Theory
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 Foreword for MFC Applications
#undef _WINNETWK_
#include <winnetwk.h>
Enumerating Domain Resources
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;
}
Establishing and Terminating Network Connections
void CWNetSampleDlg::OnButtonAdd()
{
UpdateData();
NETRESOURCE nr;
memset(&nr,0,sizeof(nr));
nr.lpRemoteName = (LPTSTR)(LPCTSTR)m_sRemoteName;
nr.dwType = RESOURCETYPE_DISK;
CONNECTDLGSTRUCT c;
memset(&c,0,sizeof(c));
c.cbStructure = sizeof(CONNECTDLGSTRUCT);
c.hwndOwner = m_hWnd;
c.lpConnRes = &nr;
DWORD dwRes = WNetConnectionDialog1(&c);
CString sErr;
sErr.Format(L"Error = %d",dwRes);
AfxMessageBox(sErr);
}
void CWNetSampleDlg::OnButtonAdd3()
{
UpdateData();
NETRESOURCE nr;
memset(&nr,0,sizeof(nr));
nr.lpRemoteName = (LPTSTR)(LPCTSTR)m_sRemoteName;
nr.lpLocalName = L"MyShareTmp";
nr.dwType = RESOURCETYPE_DISK;
DWORD dwRes = WNetAddConnection3(
m_hWnd,&nr,
NULL,
NULL,
CONNECT_UPDATE_PROFILE);
CString sErr;
sErr.Format(L"Error = %d",dwRes);
AfxMessageBox(sErr);
}
void CWNetSampleDlg::OnButtonDisc()
{
DWORD dwRes = WNetDisconnectDialog(m_hWnd,0);
CString sErr;
sErr.Format(L"Error = %d",dwRes);
AfxMessageBox(sErr);
}
void CWNetSampleDlg::OnButtonDisc1()
{
DISCDLGSTRUCT d;
d.cbStructure = sizeof(DISCDLGSTRUCT);
memset(&d,0,sizeof(d));
d.hwndOwner = m_hWnd;
d.lpLocalName = L"MyShare";
DWORD dwRes = WNetDisconnectDialog1(&d);
CString sErr;
sErr.Format(L"Error = %d",dwRes);
AfxMessageBox(sErr);
}
void CWNetSampleDlg::OnButtonCancel2()
{
DWORD dwRes = WNetCancelConnection2(L"MyShare",
CONNECT_UPDATE_PROFILE,TRUE);
CString sErr;
sErr.Format(L"Error = %d",dwRes);
AfxMessageBox(sErr);
}
Reading and Writing Data
void CWNetSampleDlg::OnButtonPrint()
{
UpdateData();
HANDLE hFile = CreateFile(m_sRemoteName,GENERIC_WRITE,0,0,
OPEN_EXISTING,0,0);
if ( hFile != INVALID_HANDLE_VALUE )
{
CFile f;
if ( f.Open(L"\\Sample.txt",CFile::modeRead) )
{
CByteArray baFile;
baFile.SetSize(f.GetLength() + 1);
f.Read(baFile.GetData(),f.GetLength());
f.Close();
DWORD wb;
WriteFile(hFile,baFile.GetData(),baFile.GetSize()
- 1,&wb,0);
AfxMessageBox(L"Sent data to " + m_sRemoteName);
}
else
{
AfxMessageBox(L"Failed to open local file");
}
CloseHandle(hFile);
}
else
{
AfxMessageBox(L"Failed to open " + m_sRemoteName);
}
}
void CWNetSampleDlg::OnButtonPrintCopy()
{
UpdateData();
CopyFile(L"\\Sample.txt",m_sRemoteName,FALSE);
}
Conclusion
Download
About the Author