- Implement CM_Locate_DevNode_ExW, CM_Get_Device_ID_Size[_Ex] and CM_Get_Device_ID...
[reactos.git] / rosapps / winfile / network.c
1 /*
2 * ReactOS winfile
3 *
4 * network.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <stdlib.h>
27 #include <malloc.h>
28 #include <memory.h>
29 #include <tchar.h>
30 #include <process.h>
31 #include <stdio.h>
32
33 #include "main.h"
34 #include "network.h"
35
36 #include "trace.h"
37
38
39 ////////////////////////////////////////////////////////////////////////////////
40 // Global Variables:
41 //
42
43 static HANDLE hNetworkMonitorThreadEvent = NULL; // When this event becomes signaled then we run the monitor thread
44
45 static HMODULE hMPR;
46 static BOOL bNetAvailable = FALSE;
47
48 typedef DWORD (WINAPI *WNetCloseEnum_Ptr)(HANDLE);
49 typedef DWORD (WINAPI *WNetConnectionDialog_Ptr)(HWND, DWORD);
50 typedef DWORD (WINAPI *WNetDisconnectDialog_Ptr)(HWND, DWORD);
51 typedef DWORD (WINAPI *WNetConnectionDialog1_Ptr)(LPCONNECTDLGSTRUCT);
52 typedef DWORD (WINAPI *WNetDisconnectDialog1_Ptr)(LPDISCDLGSTRUCT);
53 typedef DWORD (WINAPI *WNetEnumResourceA_Ptr)(HANDLE, LPDWORD, LPVOID, LPDWORD);
54 typedef DWORD (WINAPI *WNetOpenEnumA_Ptr)(DWORD, DWORD, DWORD, LPNETRESOURCE, LPHANDLE);
55
56 static WNetCloseEnum_Ptr pWNetCloseEnum;
57 static WNetConnectionDialog_Ptr pWNetConnectionDialog;
58 static WNetDisconnectDialog_Ptr pWNetDisconnectDialog;
59 static WNetConnectionDialog1_Ptr pWNetConnectionDialog1;
60 static WNetDisconnectDialog1_Ptr pWNetDisconnectDialog1;
61 static WNetEnumResourceA_Ptr pWNetEnumResource;
62 static WNetOpenEnumA_Ptr pWNetOpenEnum;
63
64
65 ////////////////////////////////////////////////////////////////////////////////
66 // Local module support methods
67 //
68
69 static BOOL CheckNetworkAvailable(void)
70 {
71
72 hMPR = LoadLibrary(_T("MPR.DLL"));
73 if (hMPR) {
74 pWNetCloseEnum = (WNetCloseEnum_Ptr)(FARPROC)GetProcAddress(hMPR, "WNetCloseEnum");
75 pWNetConnectionDialog = (WNetConnectionDialog_Ptr)(FARPROC)GetProcAddress(hMPR, "WNetConnectionDialog");
76 pWNetDisconnectDialog = (WNetDisconnectDialog_Ptr)(FARPROC)GetProcAddress(hMPR, "WNetDisconnectDialog");
77 pWNetConnectionDialog1 = (WNetConnectionDialog1_Ptr)(FARPROC)GetProcAddress(hMPR, "WNetConnectionDialog1");
78 pWNetDisconnectDialog1 = (WNetDisconnectDialog1_Ptr)(FARPROC)GetProcAddress(hMPR, "WNetDisconnectDialog1");
79 pWNetEnumResource = (WNetEnumResourceA_Ptr)(FARPROC)GetProcAddress(hMPR, "WNetEnumResourceA");
80 pWNetOpenEnum = (WNetOpenEnumA_Ptr)(FARPROC)GetProcAddress(hMPR, "WNetOpenEnumA");
81 // FreeLibrary(hMPR);
82 bNetAvailable = TRUE;
83 }
84 return (hMPR != NULL);
85 }
86
87
88 static LRESULT CALLBACK EnumNetConnectionsProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
89 {
90 return 0;
91 }
92
93 /*
94 DWORD WNetOpenEnum(
95 DWORD dwScope, // scope of enumeration
96 DWORD dwType, // resource types to list
97 DWORD dwUsage, // resource usage to list
98 LPNETRESOURCE lpNetResource, // resource structure
99 LPHANDLE lphEnum // enumeration handle buffer
100 );
101
102 result = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_DISK, RESOURCEUSAGE_ALL, NULL, &EnumNetConnectionsProc);
103
104 */
105 DWORD MapNetworkDrives(HWND hWnd, BOOL connect)
106 {
107 DWORD result = 0L;
108
109 if (!bNetAvailable) return result;
110 #if 1
111 if (connect) {
112 pWNetConnectionDialog(hWnd, RESOURCETYPE_DISK);
113 } else {
114 pWNetDisconnectDialog(hWnd, RESOURCETYPE_DISK);
115 }
116 #else
117 if (connect) {
118 NETRESOURCE netResouce;
119 CONNECTDLGSTRUCT connectDlg;
120
121 //netResouce.dwScope;
122 //netResouce.dwType;
123 netResouce.dwDisplayType = 0;
124 //netResouce.dwUsage;
125 //netResouce.lpLocalName;
126 //netResouce.lpRemoteName;
127 //netResouce.lpComment;
128 //netResouce.lpProvider;
129
130 //connectDlg.cbStructure;
131 connectDlg.hwndOwner = hWnd;
132 connectDlg.lpConnRes = &netResouce;
133 //connectDlg.dwFlags;
134 //connectDlg.dwDevNum;
135
136 result = WNetConnectionDialog1(&connectDlg);
137 } else {
138 DISCDLGSTRUCT disconnectDlg;
139 //disconnectDlg.cbStructure;
140 disconnectDlg.hwndOwner = hWnd;
141 //disconnectDlg.lpLocalName;
142 //disconnectDlg.lpRemoteName;
143 //disconnectDlg.dwFlags;
144 result = pWNetDisconnectDialog1(&disconnectDlg);
145 }
146 #endif
147 return result;
148 }
149
150 ////////////////////////////////////
151 static void NetErrorHandler(HWND hwnd, DWORD dwResult, LPTSTR str)
152 {
153 TRACE(_T("NetErrorHandler(0x%08X) %s\n"), dwResult, str);
154 }
155
156 static void DisplayStruct(HDC hdc, LPNETRESOURCE lpnrLocal)
157 {
158 LPTSTR str = NULL;
159 //TRACE(_T("DisplayStruct(%p)\n"), lpnrLocal);
160
161 switch (lpnrLocal->dwScope) {
162 case RESOURCE_CONNECTED: str = _T("Enumerate currently connected resources. The dwUsage member cannot be specified."); break;
163 case RESOURCE_GLOBALNET: str = _T("Enumerate all resources on the network. The dwUsage member is specified."); break;
164 case RESOURCE_REMEMBERED: str = _T("Enumerate remembered (persistent) connections. The dwUsage member cannot be specified."); break;
165 default: str = _T("Unknown Scope."); break;
166 }
167 //TRACE(_T(" %s\n"), str);
168
169 switch (lpnrLocal->dwType) {
170 case RESOURCETYPE_ANY: str = _T("All resources."); break;
171 case RESOURCETYPE_DISK: str = _T("Disk resources."); break;
172 case RESOURCETYPE_PRINT: str = _T("Print resources."); break;
173 default: str = _T("Unknown Type."); break;
174 }
175 //TRACE(_T(" %s\n"), str);
176
177 switch (lpnrLocal->dwDisplayType) {
178 case RESOURCEDISPLAYTYPE_DOMAIN: str = _T("The object should be displayed as a domain."); break;
179 case RESOURCEDISPLAYTYPE_SERVER: str = _T("The object should be displayed as a server."); break;
180 case RESOURCEDISPLAYTYPE_SHARE: str = _T("The object should be displayed as a share."); break;
181 case RESOURCEDISPLAYTYPE_GENERIC: str = _T("The method used to display the object does not matter."); break;
182 default: str = _T("Unknown DisplayType."); break;
183 }
184 //TRACE(_T(" %s\n"), str);
185
186 // switch (lpnrLocal->dwUsage ) {
187 // case RESOURCEUSAGE_CONNECTABLE: str = _T("The resource is a connectable resource; the name pointed to by the lpRemoteName member can be passed to the WNetAddConnection function to make a network connection."); break;
188 // case RESOURCEUSAGE_CONTAINER: str = _T("The resource is a container resource; the name pointed to by the lpRemoteName member can be passed to the WNetOpenEnum function to enumerate the resources in the container."); break;
189 // default: str = _T("Unknown Usage."); break;
190 // }
191 //TRACE(_T("\tLocalName: %s\tRemoteName: %s"), lpnrLocal->lpLocalName, lpnrLocal->lpRemoteName);
192 //TRACE(_T("\tComment: %s\tProvider: %s\n"), lpnrLocal->lpComment, lpnrLocal->lpProvider);
193 }
194
195 ////////////////////////////////////
196
197 static BOOL WINAPI EnumerateFunc(HWND hwnd, HDC hdc, LPNETRESOURCE lpnr)
198 {
199 DWORD dwResult;
200 DWORD dwResultEnum;
201 HANDLE hEnum;
202 DWORD cbBuffer = 16384; // 16K is a good size
203 DWORD cEntries = -1; // enumerate all possible entries
204 LPNETRESOURCE lpnrLocal; // pointer to enumerated structures
205 DWORD i;
206
207 if (!bNetAvailable) return FALSE;
208
209 // Call the WNetOpenEnum function to begin the enumeration.
210 dwResult = pWNetOpenEnum(RESOURCE_GLOBALNET, // all network resources
211 // RESOURCETYPE_ANY, // all resources
212 RESOURCETYPE_DISK, // disk resources only, exlude printers
213 0, // enumerate all resources
214 lpnr, // NULL first time the function is called
215 &hEnum); // handle to the resource
216
217 if (dwResult != NO_ERROR) {
218 // Process errors with an application-defined error handler.
219 NetErrorHandler(hwnd, dwResult, (LPTSTR)_T("WNetOpenEnum"));
220 return FALSE;
221 }
222
223 // Call the GlobalAlloc function to allocate resources.
224 lpnrLocal = (LPNETRESOURCE)GlobalAlloc(GPTR, cbBuffer);
225
226 do {
227 // Initialize the buffer.
228 ZeroMemory(lpnrLocal, cbBuffer);
229
230 // Call the WNetEnumResource function to continue the enumeration.
231 dwResultEnum = pWNetEnumResource(hEnum, // resource handle
232 &cEntries, // defined locally as -1
233 lpnrLocal, // LPNETRESOURCE
234 &cbBuffer); // buffer size
235
236 // If the call succeeds, loop through the structures.
237 if (dwResultEnum == NO_ERROR) {
238 for (i = 0; i < cEntries; i++) {
239 // Call an application-defined function to display the contents of the NETRESOURCE structures.
240 DisplayStruct(hdc, &lpnrLocal[i]);
241
242 // If the NETRESOURCE structure represents a container resource, call the EnumerateFunc function recursively.
243 if (RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER))
244 if (!EnumerateFunc(hwnd, hdc, &lpnrLocal[i])) {
245 //TextOut(hdc, 10, 10, _T("EnumerateFunc returned FALSE."), 29);
246 TRACE(_T("EnumerateFunc returned FALSE.\n"));
247 }
248 }
249 }
250 // Process errors.
251 else if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
252 NetErrorHandler(hwnd, dwResultEnum, (LPTSTR)_T("WNetEnumResource"));
253 break;
254 }
255 }
256 // End do.
257
258 while (dwResultEnum != ERROR_NO_MORE_ITEMS);
259
260 // Call the GlobalFree function to free the memory.
261 GlobalFree((HGLOBAL)lpnrLocal);
262
263 // Call WNetCloseEnum to end the enumeration.
264 dwResult = pWNetCloseEnum(hEnum);
265
266 if (dwResult != NO_ERROR) {
267 // Process errors.
268 NetErrorHandler(hwnd, dwResult, (LPTSTR)_T("WNetCloseEnum"));
269 return FALSE;
270 }
271 return TRUE;
272 }
273
274 /*
275
276 DWORD WNetConnectionDialog(
277 HWND hwnd, // handle to window owning dialog box
278 DWORD dwType // resource type
279 );
280
281
282 DWORD WNetAddConnection(
283 LPCTSTR lpRemoteName, // network device name
284 LPCTSTR lpPassword, // password
285 LPCTSTR lpLocalName // local device name
286 );
287
288
289 DWORD WNetOpenEnum(
290 DWORD dwScope, // scope of enumeration
291 DWORD dwType, // resource types to list
292 DWORD dwUsage, // resource usage to list
293 LPNETRESOURCE lpNetResource, // resource structure
294 LPHANDLE lphEnum // enumeration handle buffer
295 );
296 */
297
298 ////////////////////////////////////////////////////////////////////////////////
299
300 void NetworkMonitorThreadProc(void *lpParameter)
301 {
302 // ULONG OldProcessorUsage = 0;
303 // ULONG OldProcessCount = 0;
304 HWND hWnd = (HWND)lpParameter;
305
306 // Create the event
307 hNetworkMonitorThreadEvent = CreateEvent(NULL, TRUE, TRUE, _T("Winfile Network Monitor Event"));
308
309 // If we couldn't create the event then exit the thread
310 if (!hNetworkMonitorThreadEvent)
311 return;
312
313 while (1) {
314 DWORD dwWaitVal;
315
316 // Wait on the event
317 dwWaitVal = WaitForSingleObject(hNetworkMonitorThreadEvent, INFINITE);
318
319 // If the wait failed then the event object must have been
320 // closed and the task manager is exiting so exit this thread
321 if (dwWaitVal == WAIT_FAILED) {
322 // CloseHandle(hNetworkMonitorThreadEvent); // Should we close the event object handle or not ???
323 // hNetworkMonitorThreadEvent = NULL; // if we do then check what happens when main thread tries to delete it also....
324 return;
325 }
326
327 if (dwWaitVal == WAIT_OBJECT_0) {
328 // Reset our event
329 ResetEvent(hNetworkMonitorThreadEvent);
330
331
332 if ( EnumerateFunc(hWnd, NULL, NULL) ) {
333
334 }
335
336 #if 0
337 TCHAR text[260];
338 if ((ULONG)SendMessage(hProcessPageListCtrl, LVM_GETITEMCOUNT, 0, 0) != PerfDataGetProcessCount())
339 SendMessage(hProcessPageListCtrl, LVM_SETITEMCOUNT, PerfDataGetProcessCount(), /*LVSICF_NOINVALIDATEALL|*/LVSICF_NOSCROLL);
340 if (IsWindowVisible(hProcessPage))
341 InvalidateRect(hProcessPageListCtrl, NULL, FALSE);
342 if (OldProcessorUsage != PerfDataGetProcessorUsage()) {
343 OldProcessorUsage = PerfDataGetProcessorUsage();
344 wsprintf(text, _T("CPU Usage: %3d%%"), OldProcessorUsage);
345 SendMessage(hStatusWnd, SB_SETTEXT, 1, (LPARAM)text);
346 }
347 if (OldProcessCount != PerfDataGetProcessCount()) {
348 OldProcessCount = PerfDataGetProcessCount();
349 wsprintf(text, _T("Processes: %d"), OldProcessCount);
350 SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text);
351 }
352 #endif
353 }
354 }
355 }
356
357 BOOL CreateNetworkMonitorThread(HWND hWnd)
358 {
359 CheckNetworkAvailable();
360 _beginthread(NetworkMonitorThreadProc, 0, hWnd);
361 return TRUE;
362 }
363
364 void SignalNetworkMonitorEvent(void)
365 {
366 SetEvent(hNetworkMonitorThreadEvent);
367 }
368
369 BOOL DestryNetworkMonitorThread(void)
370 {
371 CloseHandle(hNetworkMonitorThreadEvent);
372 hNetworkMonitorThreadEvent = NULL;
373 return TRUE;
374 }
375