[NETSHELL] Don't use hardcoded values.
[reactos.git] / dll / shellext / netshell / lanstatusui.cpp
1 #include "precomp.h"
2
3 #include <winsock.h>
4
5 /// CLSID
6 /// HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{7007ACCF-3202-11D1-AAD2-00805FC1270E}
7 // IID B722BCCB-4E68-101B-A2BC-00AA00404770
8
9 #define WM_SHOWSTATUSDLG (WM_USER+10)
10
11 typedef struct tagNotificationItem
12 {
13 struct tagNotificationItem *pNext;
14 CLSID guidItem;
15 UINT uID;
16 HWND hwndDlg;
17 INetConnection *pNet;
18 } NOTIFICATION_ITEM;
19
20 typedef struct
21 {
22 INetConnection *pNet;
23 HWND hwndStatusDlg; /* LanStatusDlg window */
24 HWND hwndDlg; /* status dialog window */
25 DWORD dwAdapterIndex;
26 UINT_PTR nIDEvent;
27 UINT DHCPEnabled;
28 DWORD dwInOctets;
29 DWORD dwOutOctets;
30 DWORD IpAddress;
31 DWORD SubnetMask;
32 DWORD Gateway;
33 UINT uID;
34 UINT Status;
35 } LANSTATUSUI_CONTEXT;
36
37 class CLanStatus final :
38 public IOleCommandTarget
39 {
40 public:
41 CLanStatus();
42
43 // IUnknown
44 virtual HRESULT WINAPI QueryInterface(REFIID riid, LPVOID *ppvOut);
45 virtual ULONG WINAPI AddRef();
46 virtual ULONG WINAPI Release();
47
48 // IOleCommandTarget
49 virtual HRESULT WINAPI QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText);
50 virtual HRESULT WINAPI Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
51
52 private:
53 HRESULT InitializeNetTaskbarNotifications();
54 HRESULT ShowStatusDialogByCLSID(const GUID *pguidCmdGroup);
55
56 INetConnectionManager *m_lpNetMan;
57 LONG m_ref;
58 NOTIFICATION_ITEM *m_pHead;
59 };
60
61 CLanStatus::CLanStatus() :
62 m_lpNetMan(NULL),
63 m_ref(0),
64 m_pHead(NULL)
65 {
66 }
67
68 VOID
69 UpdateLanStatusUiDlg(
70 HWND hwndDlg,
71 MIB_IFROW *IfEntry,
72 LANSTATUSUI_CONTEXT *pContext)
73 {
74 WCHAR szFormat[MAX_PATH] = {0};
75 WCHAR szBuffer[MAX_PATH] = {0};
76 SYSTEMTIME TimeConnected;
77 DWORD DurationSeconds;
78 WCHAR Buffer[100];
79 WCHAR DayBuffer[30];
80 WCHAR LocBuffer[50];
81
82 #if 0
83 ULONGLONG Ticks;
84 #else
85 DWORD Ticks;
86 #endif
87
88 if (IfEntry->dwSpeed < 1000)
89 {
90 if (LoadStringW(netshell_hInstance, IDS_FORMAT_BIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
91 {
92 swprintf(szBuffer, szFormat, IfEntry->dwSpeed);
93 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
94 }
95 }
96 else if (IfEntry->dwSpeed < 1000000)
97 {
98 if (LoadStringW(netshell_hInstance, IDS_FORMAT_KBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
99 {
100 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000);
101 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
102 }
103 }
104 else if (IfEntry->dwSpeed < 1000000000)
105 {
106 if (LoadStringW(netshell_hInstance, IDS_FORMAT_MBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
107 {
108 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000);
109 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
110 }
111 }
112 else
113 {
114 if (LoadStringW(netshell_hInstance, IDS_FORMAT_GBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
115 {
116 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000000);
117 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
118 }
119 }
120
121 if (StrFormatByteSizeW(IfEntry->dwInOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
122 {
123 SendDlgItemMessageW(hwndDlg, IDC_RECEIVED, WM_SETTEXT, 0, (LPARAM)szBuffer);
124 }
125
126 if (StrFormatByteSizeW(IfEntry->dwOutOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
127 {
128 SendDlgItemMessageW(hwndDlg, IDC_SEND, WM_SETTEXT, 0, (LPARAM)szBuffer);
129 }
130
131 #if 0
132 Ticks = GetTickCount64();
133 #else
134 Ticks = GetTickCount();
135 #endif
136
137 DurationSeconds = Ticks / 1000;
138 TimeConnected.wSecond = (DurationSeconds % 60);
139 TimeConnected.wMinute = (DurationSeconds / 60) % 60;
140 TimeConnected.wHour = (DurationSeconds / (60 * 60)) % 24;
141 TimeConnected.wDay = DurationSeconds / (60 * 60 * 24);
142
143 if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &TimeConnected, L"HH':'mm':'ss", LocBuffer, sizeof(LocBuffer) / sizeof(LocBuffer[0])))
144 return;
145
146 if (!TimeConnected.wDay)
147 {
148 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)LocBuffer);
149 }
150 else
151 {
152 if (TimeConnected.wDay == 1)
153 {
154 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAY, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
155 DayBuffer[0] = L'\0';
156 }
157 else
158 {
159 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAYS, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
160 DayBuffer[0] = L'\0';
161 }
162 swprintf(Buffer, DayBuffer, TimeConnected.wDay, LocBuffer);
163 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)Buffer);
164 }
165
166 }
167
168 VOID
169 UpdateLanStatus(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
170 {
171 MIB_IFROW IfEntry;
172 HICON hIcon, hOldIcon = NULL;
173 NOTIFYICONDATAW nid;
174 NETCON_PROPERTIES * pProperties = NULL;
175
176 ZeroMemory(&IfEntry, sizeof(IfEntry));
177 IfEntry.dwIndex = pContext->dwAdapterIndex;
178 if (GetIfEntry(&IfEntry) != NO_ERROR)
179 {
180 return;
181 }
182
183 hIcon = NULL;
184 if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
185 {
186 if (pContext->dwInOctets == IfEntry.dwInOctets && pContext->dwOutOctets == IfEntry.dwOutOctets && pContext->Status != 0)
187 {
188 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 32, 32, LR_SHARED);
189 pContext->Status = 0;
190 }
191 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 1)
192 {
193 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANSREC), IMAGE_ICON, 32, 32, LR_SHARED);
194 pContext->Status = 1;
195 }
196 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->Status != 2)
197 {
198 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_REC), IMAGE_ICON, 32, 32, LR_SHARED);
199 pContext->Status = 2;
200 }
201 else if (pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 3)
202 {
203 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANS), IMAGE_ICON, 32, 32, LR_SHARED);
204 pContext->Status = 3;
205 }
206 }
207 else if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_UNREACHABLE || IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_DISCONNECTED)
208 {
209 if (pContext->Status != 4)
210 {
211 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_SHARED);
212 pContext->Status = 4;
213 }
214 }
215 else if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_NON_OPERATIONAL)
216 {
217 if (pContext->Status != 5)
218 {
219 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_SHARED);
220 pContext->Status = 5;
221 }
222 }
223
224 if (hwndDlg && hIcon)
225 {
226 hOldIcon = (HICON)SendDlgItemMessageW(hwndDlg, IDC_NETSTAT, STM_SETICON, (WPARAM)hIcon, 0);
227 if (hOldIcon)
228 DestroyIcon(hOldIcon);
229 }
230
231 ZeroMemory(&nid, sizeof(nid));
232 nid.cbSize = sizeof(nid);
233 nid.uID = pContext->uID;
234 nid.hWnd = pContext->hwndStatusDlg;
235 nid.uVersion = NOTIFYICON_VERSION;
236
237 if (pContext->pNet->GetProperties(&pProperties) == S_OK)
238 {
239 if (pProperties->dwCharacter & NCCF_SHOW_ICON)
240 {
241 if (hwndDlg)
242 nid.hIcon = (HICON)CopyImage(hIcon, IMAGE_ICON, 16, 16, LR_COPYFROMRESOURCE);
243 else
244 nid.hIcon = hIcon;
245
246 if (nid.hIcon)
247 nid.uFlags |= NIF_ICON;
248
249 nid.uFlags |= NIF_STATE;
250 nid.dwState = 0;
251 nid.dwStateMask = NIS_HIDDEN;
252
253 if (pProperties->pszwName)
254 {
255 if (wcslen(pProperties->pszwName) * sizeof(WCHAR) < sizeof(nid.szTip))
256 {
257 nid.uFlags |= NIF_TIP;
258 wcscpy(nid.szTip, pProperties->pszwName);
259 }
260 else
261 {
262 CopyMemory(nid.szTip, pProperties->pszwName, sizeof(nid.szTip) - sizeof(WCHAR));
263 nid.szTip[(sizeof(nid.szTip)/sizeof(WCHAR))-1] = L'\0';
264 nid.uFlags |= NIF_TIP;
265 }
266 }
267 }
268 else
269 {
270 nid.uFlags |= NIF_STATE;
271 nid.dwState = NIS_HIDDEN;
272 nid.dwStateMask = NIS_HIDDEN;
273
274 }
275 NcFreeNetconProperties(pProperties);
276 }
277
278 Shell_NotifyIconW(NIM_MODIFY, &nid);
279
280 if (nid.uFlags & NIF_ICON)
281 DestroyIcon(nid.hIcon);
282
283 pContext->dwInOctets = IfEntry.dwInOctets;
284 pContext->dwOutOctets = IfEntry.dwOutOctets;
285
286 if (hwndDlg)
287 UpdateLanStatusUiDlg(hwndDlg, &IfEntry, pContext);
288 }
289
290
291 VOID
292 InitializeLANStatusUiDlg(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
293 {
294 WCHAR szBuffer[MAX_PATH] = {0};
295 NETCON_PROPERTIES * pProperties;
296
297 if (pContext->pNet->GetProperties(&pProperties) != S_OK)
298 return;
299
300 if (pProperties->Status == NCS_DISCONNECTED)
301 LoadStringW(netshell_hInstance, IDS_STATUS_UNREACHABLE, szBuffer, MAX_PATH);
302 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED)
303 LoadStringW(netshell_hInstance, IDS_STATUS_DISCONNECTED, szBuffer, MAX_PATH);
304 else if (pProperties->Status == NCS_CONNECTING)
305 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTING, szBuffer, MAX_PATH);
306 else if (pProperties->Status == NCS_CONNECTED)
307 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTED, szBuffer, MAX_PATH);
308
309 SendDlgItemMessageW(hwndDlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM)szBuffer);
310
311 pContext->dwInOctets = 0;
312 pContext->dwOutOctets = 0;
313
314 /* update adapter info */
315 pContext->Status = -1;
316 UpdateLanStatus(hwndDlg, pContext);
317 NcFreeNetconProperties(pProperties);
318 }
319
320 static
321 VOID
322 InsertColumnToListView(
323 HWND hDlgCtrl,
324 UINT ResId,
325 UINT SubItem,
326 UINT Size)
327 {
328 WCHAR szBuffer[200];
329 LVCOLUMNW lc;
330
331 if (!LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
332 return;
333
334 memset(&lc, 0, sizeof(LV_COLUMN) );
335 lc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
336 lc.iSubItem = SubItem;
337 lc.fmt = LVCFMT_FIXED_WIDTH;
338 lc.cx = Size;
339 lc.cchTextMax = wcslen(szBuffer);
340 lc.pszText = szBuffer;
341
342 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, SubItem, (LPARAM)&lc);
343 }
344
345 static
346 VOID
347 AddIPAddressToListView(
348 HWND hDlgCtrl,
349 PIP_ADDR_STRING pAddr,
350 INT Index)
351 {
352 LVITEMW li;
353 PIP_ADDR_STRING pCur;
354 WCHAR szBuffer[100];
355 UINT SubIndex;
356
357 ZeroMemory(&li, sizeof(LVITEMW));
358 li.mask = LVIF_TEXT;
359 li.iItem = Index;
360 pCur = pAddr;
361 SubIndex = 0;
362
363 do
364 {
365 if (SubIndex)
366 {
367 ZeroMemory(&li, sizeof(LVITEMW));
368 li.mask = LVIF_TEXT;
369 li.iItem = Index;
370 li.iSubItem = 0;
371 li.pszText = (LPWSTR)L"";
372 li.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
373 }
374
375 if (MultiByteToWideChar(CP_ACP, 0, pCur->IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
376 {
377 li.pszText = szBuffer;
378 li.iSubItem = 1;
379 li.iItem = Index++;
380 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
381 }
382 SubIndex++;
383 pCur = pCur->Next;
384 } while (pCur && pCur->IpAddress.String[0]);
385 }
386
387 static
388 INT
389 InsertItemToListView(
390 HWND hDlgCtrl,
391 UINT ResId)
392 {
393 LVITEMW li;
394 WCHAR szBuffer[100];
395
396 ZeroMemory(&li, sizeof(LVITEMW));
397 li.mask = LVIF_TEXT;
398 li.iItem = ListView_GetItemCount(hDlgCtrl);
399 if (LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
400 {
401 li.pszText = szBuffer;
402 return (INT)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
403 }
404 return -1;
405 }
406
407
408 INT_PTR
409 CALLBACK
410 LANStatusUiDetailsDlg(
411 HWND hwndDlg,
412 UINT uMsg,
413 WPARAM wParam,
414 LPARAM lParam
415 )
416 {
417 LANSTATUSUI_CONTEXT * pContext;
418 LVITEMW li;
419 WCHAR szBuffer[100];
420 PIP_ADAPTER_INFO pAdapterInfo, pCurAdapter;
421 PIP_PER_ADAPTER_INFO pPerAdapter;
422 DWORD dwSize;
423 HWND hDlgCtrl;
424 RECT rect;
425
426 switch (uMsg)
427 {
428 case WM_INITDIALOG:
429 pContext = (LANSTATUSUI_CONTEXT*)lParam;
430
431 hDlgCtrl = GetDlgItem(hwndDlg, IDC_DETAILS);
432
433 /* get client rect */
434 GetClientRect(hDlgCtrl, &rect);
435
436 /* calculate column width */
437 dwSize = rect.right / 2;
438
439 InsertColumnToListView(hDlgCtrl, IDS_PROPERTY, 0, dwSize);
440 InsertColumnToListView(hDlgCtrl, IDS_VALUE, 1, dwSize);
441
442 dwSize = 0;
443 pCurAdapter = NULL;
444 pAdapterInfo = NULL;
445 if (GetAdaptersInfo(NULL, &dwSize) == ERROR_BUFFER_OVERFLOW)
446 {
447 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
448 if (pAdapterInfo)
449 {
450 if (GetAdaptersInfo(pAdapterInfo, &dwSize) == NO_ERROR)
451 {
452 pCurAdapter = pAdapterInfo;
453 while (pCurAdapter && pCurAdapter->Index != pContext->dwAdapterIndex)
454 pCurAdapter = pCurAdapter->Next;
455
456 if (pCurAdapter->Index != pContext->dwAdapterIndex)
457 pCurAdapter = NULL;
458 }
459 }
460 }
461
462 ZeroMemory(&li, sizeof(LVITEMW));
463 li.mask = LVIF_TEXT;
464 li.iSubItem = 1;
465 li.pszText = szBuffer;
466
467 if (pCurAdapter)
468 {
469 li.iItem = InsertItemToListView(hDlgCtrl, IDS_PHYSICAL_ADDRESS);
470 if (li.iItem >= 0)
471 {
472 swprintf(szBuffer, L"%02x-%02x-%02x-%02x-%02x-%02x",pCurAdapter->Address[0], pCurAdapter->Address[1],
473 pCurAdapter->Address[2], pCurAdapter->Address[3], pCurAdapter->Address[4], pCurAdapter->Address[5]);
474 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
475 }
476 li.iItem = InsertItemToListView(hDlgCtrl, IDS_IP_ADDRESS);
477 if (li.iItem >= 0)
478 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
479 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
480
481 li.iItem = InsertItemToListView(hDlgCtrl, IDS_SUBNET_MASK);
482 if (li.iItem >= 0)
483 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpMask.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
484 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
485
486 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DEF_GATEWAY);
487 if (li.iItem >= 0 && pCurAdapter->GatewayList.IpAddress.String[0] != '0')
488 {
489 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->GatewayList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
490 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
491 }
492 #if 0
493 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_OBTAINED);
494 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_EXPIRES);
495 #endif
496 }
497
498 dwSize = 0;
499 if (GetPerAdapterInfo(pContext->dwAdapterIndex, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW)
500 {
501 pPerAdapter = static_cast<PIP_PER_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
502 if (pPerAdapter)
503 {
504 if (GetPerAdapterInfo(pContext->dwAdapterIndex, pPerAdapter, &dwSize) == ERROR_SUCCESS)
505 {
506 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DNS_SERVERS);
507 if (li.iItem >= 0)
508 AddIPAddressToListView(hDlgCtrl, &pPerAdapter->DnsServerList, li.iItem);
509 }
510 CoTaskMemFree(pPerAdapter);
511 }
512 }
513 #if 0
514 if (pCurAdapter)
515 {
516 li.iItem = InsertItemToListView(hDlgCtrl, IDS_WINS_SERVERS);
517 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->PrimaryWinsServer, li.iItem);
518 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->SecondaryWinsServer, li.iItem+1);
519 }
520 #endif
521 CoTaskMemFree(pAdapterInfo);
522 break;
523 case WM_COMMAND:
524 if (LOWORD(wParam) == IDC_CLOSE)
525 {
526 EndDialog(hwndDlg, FALSE);
527 break;
528 }
529 }
530 return FALSE;
531 }
532
533 INT_PTR
534 CALLBACK
535 LANStatusUiAdvancedDlg(
536 HWND hwndDlg,
537 UINT uMsg,
538 WPARAM wParam,
539 LPARAM lParam)
540 {
541 WCHAR szBuffer[100] = {0};
542 PROPSHEETPAGE *page;
543 LANSTATUSUI_CONTEXT * pContext;
544 DWORD dwIpAddr;
545
546
547 switch (uMsg)
548 {
549 case WM_INITDIALOG:
550 page = (PROPSHEETPAGE*)lParam;
551 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
552 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
553 if (pContext->DHCPEnabled)
554 LoadStringW(netshell_hInstance, IDS_ASSIGNED_DHCP, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
555 else
556 LoadStringW(netshell_hInstance, IDS_ASSIGNED_MANUAL, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
557
558 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
559 SendDlgItemMessageW(hwndDlg, IDC_DETAILSTYPE, WM_SETTEXT, 0, (LPARAM)szBuffer);
560
561
562 dwIpAddr = ntohl(pContext->IpAddress);
563 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
564 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
565 SendDlgItemMessageW(hwndDlg, IDC_DETAILSIP, WM_SETTEXT, 0, (LPARAM)szBuffer);
566
567 dwIpAddr = ntohl(pContext->SubnetMask);
568 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
569 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
570 SendDlgItemMessageW(hwndDlg, IDC_DETAILSSUBNET, WM_SETTEXT, 0, (LPARAM)szBuffer);
571
572 dwIpAddr = ntohl(pContext->Gateway);
573 if (dwIpAddr)
574 {
575 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
576 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
577 SendDlgItemMessageW(hwndDlg, IDC_DETAILSGATEWAY, WM_SETTEXT, 0, (LPARAM)szBuffer);
578 }
579 return TRUE;
580 case WM_COMMAND:
581 if (LOWORD(wParam) == IDC_DETAILS)
582 {
583 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
584 if (pContext)
585 {
586 DialogBoxParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_LAN_NETSTATUSDETAILS), GetParent(hwndDlg),
587 LANStatusUiDetailsDlg, (LPARAM)pContext);
588 }
589 }
590 break;
591 default:
592 break;
593 }
594 return FALSE;
595 }
596
597 BOOL
598 FindNetworkAdapter(HDEVINFO hInfo, SP_DEVINFO_DATA *pDevInfo, LPWSTR pGuid)
599 {
600 DWORD dwIndex, dwSize;
601 HKEY hSubKey;
602 WCHAR szNetCfg[50];
603 WCHAR szDetail[200] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\";
604
605 dwIndex = 0;
606 do
607 {
608
609 ZeroMemory(pDevInfo, sizeof(SP_DEVINFO_DATA));
610 pDevInfo->cbSize = sizeof(SP_DEVINFO_DATA);
611
612 /* get device info */
613 if (!SetupDiEnumDeviceInfo(hInfo, dwIndex++, pDevInfo))
614 break;
615
616 /* get device software registry path */
617 if (!SetupDiGetDeviceRegistryPropertyW(hInfo, pDevInfo, SPDRP_DRIVER, NULL, (LPBYTE)&szDetail[39], sizeof(szDetail)/sizeof(WCHAR) - 40, &dwSize))
618 break;
619
620 /* open device registry key */
621 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szDetail, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
622 break;
623
624 /* query NetCfgInstanceId for current device */
625 dwSize = sizeof(szNetCfg);
626 if (RegQueryValueExW(hSubKey, L"NetCfgInstanceId", NULL, NULL, (LPBYTE)szNetCfg, &dwSize) != ERROR_SUCCESS)
627 {
628 RegCloseKey(hSubKey);
629 break;
630 }
631 RegCloseKey(hSubKey);
632 if (!_wcsicmp(pGuid, szNetCfg))
633 {
634 return TRUE;
635 }
636 } while (TRUE);
637
638 return FALSE;
639 }
640
641 VOID
642 DisableNetworkAdapter(INetConnection * pNet, LANSTATUSUI_CONTEXT * pContext, HWND hwndDlg)
643 {
644 HKEY hKey;
645 NETCON_PROPERTIES * pProperties;
646 LPOLESTR pDisplayName;
647 WCHAR szPath[200];
648 DWORD dwSize, dwType;
649 LPWSTR pPnp;
650 HDEVINFO hInfo;
651 SP_DEVINFO_DATA DevInfo;
652 SP_PROPCHANGE_PARAMS PropChangeParams;
653 BOOL bClose = FALSE;
654 NOTIFYICONDATAW nid;
655
656 if (FAILED(pNet->GetProperties(&pProperties)))
657 return;
658
659
660 hInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
661 if (!hInfo)
662 {
663 NcFreeNetconProperties(pProperties);
664 return;
665 }
666
667 if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pDisplayName)))
668 {
669 NcFreeNetconProperties(pProperties);
670 SetupDiDestroyDeviceInfoList(hInfo);
671 return;
672 }
673 NcFreeNetconProperties(pProperties);
674
675 if (FindNetworkAdapter(hInfo, &DevInfo, pDisplayName))
676 {
677 PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
678 PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; //;
679 PropChangeParams.StateChange = DICS_DISABLE;
680 PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
681 PropChangeParams.HwProfile = 0;
682
683 if (SetupDiSetClassInstallParams(hInfo, &DevInfo, &PropChangeParams.ClassInstallHeader, sizeof(SP_PROPCHANGE_PARAMS)))
684 {
685 if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hInfo, &DevInfo))
686 bClose = TRUE;
687 }
688 }
689 SetupDiDestroyDeviceInfoList(hInfo);
690
691 swprintf(szPath, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pDisplayName);
692 CoTaskMemFree(pDisplayName);
693
694 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
695 return;
696
697 dwSize = 0;
698 if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_SZ)
699 {
700 RegCloseKey(hKey);
701 return;
702 }
703
704 pPnp = static_cast<PWSTR>(CoTaskMemAlloc(dwSize));
705 if (!pPnp)
706 {
707 RegCloseKey(hKey);
708 return;
709 }
710
711 if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, (LPBYTE)pPnp, &dwSize) != ERROR_SUCCESS)
712 {
713 CoTaskMemFree(pPnp);
714 RegCloseKey(hKey);
715 return;
716 }
717 RegCloseKey(hKey);
718
719 swprintf(szPath, L"System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Enum\\%s", pPnp);
720 CoTaskMemFree(pPnp);
721
722 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
723 return;
724
725 dwSize = 1; /* enable = 0, disable = 1 */
726 RegSetValueExW(hKey, L"CSConfigFlags", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD));
727 RegCloseKey(hKey);
728
729 if (!bClose)
730 return;
731
732 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_CANCEL);
733 ZeroMemory(&nid, sizeof(nid));
734 nid.cbSize = sizeof(nid);
735 nid.uID = pContext->uID;
736 nid.hWnd = pContext->hwndDlg;
737 nid.uFlags = NIF_STATE;
738 nid.dwState = NIS_HIDDEN;
739 nid.dwStateMask = NIS_HIDDEN;
740
741 Shell_NotifyIconW(NIM_MODIFY, &nid);
742 }
743
744
745 INT_PTR
746 CALLBACK
747 LANStatusUiDlg(
748 HWND hwndDlg,
749 UINT uMsg,
750 WPARAM wParam,
751 LPARAM lParam)
752 {
753 PROPSHEETPAGE *page;
754 LANSTATUSUI_CONTEXT * pContext;
755 LPPSHNOTIFY lppsn;
756
757 switch (uMsg)
758 {
759 case WM_INITDIALOG:
760 page = (PROPSHEETPAGE*)lParam;
761 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
762 pContext->hwndDlg = hwndDlg;
763 InitializeLANStatusUiDlg(hwndDlg, pContext);
764 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
765 return TRUE;
766 case WM_COMMAND:
767 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
768 if (LOWORD(wParam) == IDC_STATUS_PROPERTIES)
769 {
770 if (pContext)
771 {
772 ShowNetConnectionProperties(pContext->pNet, GetParent(pContext->hwndDlg));
773 BringWindowToTop(GetParent(pContext->hwndDlg));
774 }
775 break;
776 }
777 else if (LOWORD(wParam) == IDC_ENDISABLE)
778 {
779 DisableNetworkAdapter(pContext->pNet, pContext, hwndDlg);
780 break;
781 }
782 case WM_NOTIFY:
783 lppsn = (LPPSHNOTIFY) lParam;
784 if (lppsn->hdr.code == PSN_APPLY || lppsn->hdr.code == PSN_RESET)
785 {
786 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
787 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
788 pContext->hwndDlg = NULL;
789 return TRUE;
790 }
791 break;
792 }
793 return FALSE;
794 }
795
796 VOID
797 InitializePropertyDialog(
798 LANSTATUSUI_CONTEXT * pContext,
799 NETCON_PROPERTIES * pProperties)
800 {
801 DWORD dwSize, dwAdapterIndex, dwResult;
802 LPOLESTR pStr;
803 IP_ADAPTER_INFO *pAdapterInfo, *pCurAdapter;
804
805 if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pStr)))
806 {
807 return;
808 }
809
810 /* get the IfTable */
811 dwSize = 0;
812 dwResult = GetAdaptersInfo(NULL, &dwSize);
813 if (dwResult!= ERROR_BUFFER_OVERFLOW)
814 {
815 CoTaskMemFree(pStr);
816 return;
817 }
818
819 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
820 if (!pAdapterInfo)
821 {
822 CoTaskMemFree(pAdapterInfo);
823 CoTaskMemFree(pStr);
824 return;
825 }
826
827 if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR)
828 {
829 CoTaskMemFree(pAdapterInfo);
830 CoTaskMemFree(pStr);
831 return;
832 }
833
834 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, pStr, &dwAdapterIndex))
835 {
836 CoTaskMemFree(pAdapterInfo);
837 CoTaskMemFree(pStr);
838 return;
839 }
840
841 pCurAdapter = pAdapterInfo;
842 while (pCurAdapter->Index != dwAdapterIndex)
843 pCurAdapter = pCurAdapter->Next;
844
845
846 pContext->IpAddress = inet_addr(pCurAdapter->IpAddressList.IpAddress.String);
847 pContext->SubnetMask = inet_addr(pCurAdapter->IpAddressList.IpMask.String);
848 pContext->Gateway = inet_addr(pCurAdapter->GatewayList.IpAddress.String);
849 pContext->DHCPEnabled = pCurAdapter->DhcpEnabled;
850 CoTaskMemFree(pStr);
851 CoTaskMemFree(pAdapterInfo);
852 pContext->dwAdapterIndex = dwAdapterIndex;
853 }
854
855 VOID
856 ShowStatusPropertyDialog(
857 LANSTATUSUI_CONTEXT *pContext,
858 HWND hwndDlg)
859 {
860 HPROPSHEETPAGE hppages[2];
861 PROPSHEETHEADERW pinfo;
862 NETCON_PROPERTIES * pProperties = NULL;
863
864 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
865 ZeroMemory(hppages, sizeof(hppages));
866 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
867 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW;
868 pinfo.phpage = hppages;
869 pinfo.hwndParent = hwndDlg;
870
871 if (pContext->pNet->GetProperties(&pProperties) == S_OK)
872 {
873 if (pProperties->pszwName)
874 {
875 pinfo.pszCaption = pProperties->pszwName;
876 pinfo.dwFlags |= PSH_PROPTITLE;
877 }
878 InitializePropertyDialog(pContext, pProperties);
879 if (pProperties->MediaType == NCM_LAN && pProperties->Status == NCS_CONNECTED)
880 {
881 hppages[0] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUS), LANStatusUiDlg, (LPARAM)pContext, NULL);
882 if (hppages[0])
883 pinfo.nPages++;
884
885 hppages[pinfo.nPages] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUSADVANCED), LANStatusUiAdvancedDlg, (LPARAM)pContext, NULL);
886 if (hppages[pinfo.nPages])
887 pinfo.nPages++;
888
889 if (pinfo.nPages)
890 {
891 PropertySheetW(&pinfo);
892 }
893 }
894 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED ||
895 pProperties->Status == NCS_HARDWARE_DISABLED)
896 {
897 ShowNetConnectionProperties(pContext->pNet, pContext->hwndDlg);
898 }
899
900 NcFreeNetconProperties(pProperties);
901 }
902 }
903
904 INT_PTR
905 CALLBACK
906 LANStatusDlg(
907 HWND hwndDlg,
908 UINT uMsg,
909 WPARAM wParam,
910 LPARAM lParam)
911 {
912 LANSTATUSUI_CONTEXT * pContext;
913
914 switch (uMsg)
915 {
916 case WM_INITDIALOG:
917 pContext = (LANSTATUSUI_CONTEXT *)lParam;
918 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
919 pContext->nIDEvent = SetTimer(hwndDlg, 0xFABC, 1000, NULL);
920 return TRUE;
921 case WM_TIMER:
922 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
923 if (wParam == (WPARAM)pContext->nIDEvent)
924 {
925 UpdateLanStatus(pContext->hwndDlg, pContext);
926 }
927 break;
928 case WM_SHOWSTATUSDLG:
929 if (LOWORD(lParam) == WM_LBUTTONDOWN)
930 {
931 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
932 if (!pContext)
933 break;
934
935 if (pContext->hwndDlg)
936 {
937 ShowWindow(GetParent(pContext->hwndDlg), SW_SHOW);
938 BringWindowToTop(GetParent(pContext->hwndDlg));
939 }
940 else
941 {
942 ShowStatusPropertyDialog(pContext, hwndDlg);
943 }
944 break;
945 }
946 break;
947 }
948 return FALSE;
949 }
950
951 HRESULT
952 CLanStatus::InitializeNetTaskbarNotifications()
953 {
954 NOTIFYICONDATAW nid;
955 HWND hwndDlg;
956 INetConnectionManager *pNetConMan;
957 IEnumNetConnection *pEnumCon;
958 INetConnection *pNetCon;
959 NETCON_PROPERTIES* pProps;
960 HRESULT hr;
961 ULONG Count;
962 ULONG Index;
963 NOTIFICATION_ITEM * pItem, *pLast = NULL;
964 LANSTATUSUI_CONTEXT * pContext;
965
966 TRACE("InitializeNetTaskbarNotifications\n");
967
968 if (m_pHead)
969 {
970 pItem = m_pHead;
971 while (pItem)
972 {
973 hr = pItem->pNet->GetProperties(&pProps);
974 if (SUCCEEDED(hr))
975 {
976 ZeroMemory(&nid, sizeof(nid));
977 nid.cbSize = sizeof(nid);
978 nid.uID = pItem->uID;
979 nid.hWnd = pItem->hwndDlg;
980 nid.uFlags = NIF_STATE;
981 if (pProps->dwCharacter & NCCF_SHOW_ICON)
982 nid.dwState = 0;
983 else
984 nid.dwState = NIS_HIDDEN;
985
986 nid.dwStateMask = NIS_HIDDEN;
987 Shell_NotifyIconW(NIM_MODIFY, &nid);
988 NcFreeNetconProperties(pProps);
989 }
990 pItem = pItem->pNext;
991 }
992 return S_OK;
993 }
994 /* get an instance to of IConnectionManager */
995
996 //hr = CoCreateInstance(&CLSID_ConnectionManager, NULL, CLSCTX_INPROC_SERVER, &IID_INetConnectionManager, (LPVOID*)&pNetConMan);
997
998 hr = INetConnectionManager_Constructor(NULL, IID_INetConnectionManager, (LPVOID*)&pNetConMan);
999 if (FAILED(hr))
1000 {
1001 ERR("INetConnectionManager_Constructor failed\n");
1002 return hr;
1003 }
1004
1005 hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
1006 if (FAILED(hr))
1007 {
1008 ERR("EnumConnections failed\n");
1009 pNetConMan->Release();
1010 return hr;
1011 }
1012
1013 Index = 1;
1014 do
1015 {
1016 hr = pEnumCon->Next(1, &pNetCon, &Count);
1017 if (hr == S_OK)
1018 {
1019 TRACE("new connection\n");
1020 pItem = static_cast<NOTIFICATION_ITEM*>(CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM)));
1021 if (!pItem)
1022 break;
1023
1024 pContext = static_cast<LANSTATUSUI_CONTEXT*>(CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT)));
1025 if (!pContext)
1026 {
1027 CoTaskMemFree(pItem);
1028 break;
1029 }
1030
1031 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT));
1032 pContext->uID = Index;
1033 pContext->pNet = pNetCon;
1034 pItem->uID = Index;
1035 pItem->pNext = NULL;
1036 pItem->pNet = pNetCon;
1037 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext);
1038 if (hwndDlg)
1039 {
1040 ZeroMemory(&nid, sizeof(nid));
1041 nid.cbSize = sizeof(nid);
1042 nid.uID = Index++;
1043 nid.uFlags = NIF_MESSAGE;
1044 nid.uVersion = NOTIFYICON_VERSION;
1045 nid.uCallbackMessage = WM_SHOWSTATUSDLG;
1046 nid.hWnd = hwndDlg;
1047
1048 hr = pNetCon->GetProperties(&pProps);
1049 if (SUCCEEDED(hr))
1050 {
1051 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID));
1052 if (!(pProps->dwCharacter & NCCF_SHOW_ICON))
1053 {
1054 nid.dwState = NIS_HIDDEN;
1055 nid.dwStateMask = NIS_HIDDEN;
1056 nid.uFlags |= NIF_STATE;
1057 }
1058 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED)
1059 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF));
1060 else if (pProps->Status == NCS_CONNECTED)
1061 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE));
1062
1063 if (nid.hIcon)
1064 nid.uFlags |= NIF_ICON;
1065
1066 wcscpy(nid.szTip, pProps->pszwName);
1067 nid.uFlags |= NIF_TIP;
1068 }
1069 pContext->hwndStatusDlg = hwndDlg;
1070 pItem->hwndDlg = hwndDlg;
1071
1072 if (Shell_NotifyIconW(NIM_ADD, &nid))
1073 {
1074 if (pLast)
1075 pLast->pNext = pItem;
1076 else
1077 m_pHead = pItem;
1078
1079 pLast = pItem;
1080 Index++;
1081 }
1082 else
1083 {
1084 ERR("Shell_NotifyIconW failed\n");
1085 CoTaskMemFree(pItem);
1086 }
1087
1088 if (nid.uFlags & NIF_ICON)
1089 DestroyIcon(nid.hIcon);
1090 } else
1091 ERR("CreateDialogParamW failed\n");
1092 }
1093 } while (hr == S_OK);
1094
1095 m_lpNetMan = pNetConMan;
1096 pEnumCon->Release();
1097 return S_OK;
1098 }
1099
1100 HRESULT
1101 CLanStatus::ShowStatusDialogByCLSID(const GUID *pguidCmdGroup)
1102 {
1103 NOTIFICATION_ITEM *pItem;
1104
1105 pItem = m_pHead;
1106 while (pItem)
1107 {
1108 if (IsEqualGUID(pItem->guidItem, *pguidCmdGroup))
1109 {
1110 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONDOWN);
1111 return S_OK;
1112 }
1113 pItem = pItem->pNext;
1114 }
1115
1116 ERR("not found\n");
1117 return E_FAIL;
1118 }
1119
1120 HRESULT
1121 WINAPI
1122 CLanStatus::QueryInterface(
1123 REFIID iid,
1124 LPVOID *ppvObj)
1125 {
1126 *ppvObj = NULL;
1127
1128 if (IsEqualIID(iid, IID_IUnknown) ||
1129 IsEqualIID(iid, IID_IOleCommandTarget))
1130 {
1131 *ppvObj = this;
1132 AddRef();
1133 return S_OK;
1134 }
1135
1136 return E_NOINTERFACE;
1137 }
1138
1139 ULONG
1140 WINAPI
1141 CLanStatus::AddRef()
1142 {
1143 ULONG refCount = InterlockedIncrement(&m_ref);
1144
1145 return refCount;
1146 }
1147
1148 ULONG
1149 WINAPI
1150 CLanStatus::Release()
1151 {
1152 ULONG refCount = InterlockedDecrement(&m_ref);
1153
1154 if (!refCount)
1155 delete this;
1156
1157 return refCount;
1158 }
1159
1160 HRESULT
1161 WINAPI
1162 CLanStatus::QueryStatus(
1163 const GUID *pguidCmdGroup,
1164 ULONG cCmds,
1165 OLECMD *prgCmds,
1166 OLECMDTEXT *pCmdText)
1167 {
1168 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK);
1169 return E_NOTIMPL;
1170 }
1171
1172 HRESULT
1173 WINAPI
1174 CLanStatus::Exec(
1175 const GUID *pguidCmdGroup,
1176 DWORD nCmdID,
1177 DWORD nCmdexecopt,
1178 VARIANT *pvaIn,
1179 VARIANT *pvaOut)
1180 {
1181 if (pguidCmdGroup)
1182 {
1183 if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
1184 {
1185 return InitializeNetTaskbarNotifications();
1186 }
1187 else
1188 {
1189 /* invoke status dialog */
1190 return ShowStatusDialogByCLSID(pguidCmdGroup);
1191 }
1192 }
1193 return S_OK;
1194 }
1195
1196 HRESULT WINAPI LanConnectStatusUI_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv)
1197 {
1198 TRACE("LanConnectStatusUI_Constructor\n");
1199
1200 if (!ppv)
1201 return E_POINTER;
1202
1203 if (pUnkOuter)
1204 return CLASS_E_NOAGGREGATION;
1205
1206 CLanStatus *pLanStatus = new CLanStatus;
1207 if (!pLanStatus)
1208 return E_OUTOFMEMORY;
1209
1210 pLanStatus->AddRef();
1211 static volatile CLanStatus *pCachedLanStatus = NULL;
1212 if (InterlockedCompareExchangePointer((void **)&pCachedLanStatus, pLanStatus, NULL) != NULL)
1213 pLanStatus->Release();
1214
1215 return ((CLanStatus*)pCachedLanStatus)->QueryInterface(riid, ppv);
1216 }
1217