The Winamp Remote Control suite
a remote control client and plugin for Winamp 2.x, 5.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ServerEnumerator.cpp
Go to the documentation of this file.
1 /*
2  * ServerEnumerator.cpp
3  *
4  * Created on: 29 Jan 2012
5  * Author: Patrick
6  */
7 
8 #include <vcl.h>
9 #pragma hdrstop
10 
11 #include <iostream.h>
12 
13 #include "ServerEnumerator.h"
14 #include "remotestrs.h"
15 
16 #include "IPAddressResolver.h"
17 
18 using std::cout;
19 using std::endl;
20 
21 ServerEnumerator::ServerEnumerator() : FMessageEvent(NULL), OnMessage(NULL),
22  FProgressEvent(NULL), OnProgress(NULL),
23  FServerEvent(NULL), OnServer(NULL),
24  resourceTotal_(0),
25  resourcesProcessed_(0){
26  // nothing explicit here
27 
28 }
29 
31  // nothing explicit here
32 }
33 
35  // begin enumeration
36  enumerateFunc(NULL);
37 }
38 
39 void ServerEnumerator::debugOutput(const AnsiString & operation, const AnsiString & message)
40 {
41 // cout << operation.c_str() << " " << message.c_str() << endl;
42 }
43 
44 void ServerEnumerator::addMessage(const AnsiString& message, const int level) {
45  debugOutput("Message", message);
46  if (FMessageEvent != NULL)
47  FMessageEvent(message, level);
48 }
49 
50 void ServerEnumerator::addServer(const AnsiString& remoteName, const AnsiString& comment) {
51  debugOutput("Server", remoteName + " \"" + comment + " \"");
52  if (FServerEvent != NULL)
53  {
54  string lRemoteName = remoteName.c_str();
55  WinampRemote::Net::IPAddressResolver ipr(lRemoteName);
56  //TODO - some stuff here with the results
57 
58 // GetIPAddress(remoteName.c_str(), resolvedName, Addresses, Aliases);
59 // FServerEvent(remoteName, comment, Addresses->Strings[0]);
60 // addMessage(eip->Message, 2);
61 
62  }
63 }
64 
65 void ServerEnumerator::updateProgress(const float complete) {
66  debugOutput("Progress", AnsiString().sprintf("%.0f", complete * 100));
67  if (FProgressEvent != NULL)
68  FProgressEvent(complete);
69 }
70 
71 void ServerEnumerator::handleResource(const NETRESOURCE& resource) {
72 
73  if (resource.dwDisplayType == RESOURCEDISPLAYTYPE_SERVER)
74  {
75  AnsiString remoteName = resource.lpRemoteName;
76  if (1 == remoteName.Pos(AnsiString("\\\\")))
77  remoteName.Delete(1, 2);
78  addServer(remoteName, resource.lpComment);
79  addMessage(AnsiString().sprintf("\tFound node %s", remoteName.c_str()), 0);
80  }
81 }
82 
83 void ServerEnumerator::netErrorHandler(const DWORD dwErrorCode, const AnsiString& errorFunction) {
84  DWORD dwWNetResult, dwLastError;
85  char szDescription[256];
86  char szProvider[256];
87  AnsiString MessageStr;
88  int MessageSeverity;
89 
90  // The following code performs standard error-handling.
91 
92  if (dwErrorCode != ERROR_EXTENDED_ERROR)
93  {
94  // warning
95  addMessage(errorFunction, 2);
96  MessageStr = SysErrorMessage(dwErrorCode) + ".";
97  MessageSeverity = 0;
98  } else {
99  dwWNetResult = WNetGetLastError(&dwLastError, (LPSTR) szDescription,
100  sizeof(szDescription), (LPSTR) szProvider, sizeof(szProvider));
101 
102  if (dwWNetResult != NO_ERROR)
103  {
104  // error
105  MessageStr = AnsiString().sprintf(
106  sWNetGetLastErrorFailedFmt.c_str(), dwWNetResult);
107  }
108  // warning
109 
110  MessageSeverity = 3;
111  MessageStr = AnsiString().sprintf(sWNetFailedFmt.c_str(), szProvider,
112  dwLastError, szDescription);
113  }
114 
115  // there are new lines
116  StringReplace(MessageStr, "\r\n", " ", TReplaceFlags() << rfReplaceAll);
117 
118  addMessage(MessageStr, MessageSeverity);
119 
120 }
121 
122 BOOL ServerEnumerator::enumerateFunc(const LPNETRESOURCE lpnr) {
123  DWORD dwResult, dwResultEnum;
124  HANDLE hEnum;
125  DWORD cbBuffer = 16384; // 16K is a good size
126  DWORD cEntries = 0xFFFFFFFF; // enumerate all possible entries
127  LPNETRESOURCE lpnrLocal; // pointer to enumerated structures
128  DWORD i;
129 
130  // first time case
131  if (lpnr == NULL)
132  {
133  // so far
134  resourcesProcessed_ = 0;
135  // the whole net
136  resourceTotal_ = 1;
137 
138  addMessage(sStartEnumerateNetwork, 1);
139  }
140 
141  // update
142  updateProgress(((float) resourcesProcessed_ / (float) resourceTotal_));
143 
144  resourcesProcessed_++;
145 
146  dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY,
147 
148  0, // enumerate all resources
149  lpnr, // NULL first time this function is called
150  &hEnum); // handle to resource
151 
152  if ((dwResult != NO_ERROR )) {
153 
154  // An application-defined error handler is demonstrated in the
155  // section titled "Retrieving Network Errors."
156 
157  return FALSE;
158  }
159 
160  do {
161 
162  // Allocate memory for NETRESOURCE structures.
163 
164  lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
165 
166  dwResultEnum = WNetEnumResource(hEnum, // resource handle
167  &cEntries, // defined locally as 0xFFFFFFFF
168  lpnrLocal, // LPNETRESOURCE
169  &cbBuffer); // buffer size
170 
171  if (dwResultEnum == NO_ERROR) {
172  resourceTotal_ += cEntries;
173  for (i = 0; i < cEntries; i++) {
174  handleResource(lpnrLocal[i]);
175  // recurse if it is a container of interest
176  // would like a way to avoid Terminal Services and Web Client...
177  if ((RESOURCEUSAGE_CONTAINER
178  == (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER))
179  && !(lpnrLocal[i].dwDisplayType
180  == RESOURCEDISPLAYTYPE_SERVER)) {
181 
182  AnsiString ObjectName;
183 
184  if (lpnrLocal[i].lpRemoteName)
185  ObjectName = lpnrLocal[i].lpRemoteName;
186  else
187  ObjectName = lpnrLocal[i].lpProvider;
188 
189  addMessage(
190  AnsiString().sprintf(sEnumeratingContainer.c_str(),
191  ObjectName.c_str()), 1);
192 
193 
194  enumerateFunc(&lpnrLocal[i]);
195  }
196  }
197  } else if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
198  netErrorHandler(dwResultEnum, "WNetEnumResource");
199  break;
200  }
201  GlobalFree((HGLOBAL) lpnrLocal);
202  } while (dwResultEnum != ERROR_NO_MORE_ITEMS);
203 
204  dwResult = WNetCloseEnum(hEnum);
205 
206  if (dwResult != NO_ERROR) {
207  netErrorHandler(dwResult, "WNetCloseEnum");
208 
209  return FALSE;
210  }
211 
212  return TRUE;
213 }
214