[INTRIN]
[reactos.git] / reactos / base / shell / 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 :
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 *lpNetMan;
57 LONG ref;
58 NOTIFICATION_ITEM *pHead;
59 };
60
61 CLanStatus::CLanStatus()
62 {
63 ref = 0;
64 lpNetMan = NULL;
65 pHead = NULL;
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 = 3;
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 = (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 = (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 }
637 while(TRUE);
638
639 return FALSE;
640 }
641
642 VOID
643 DisableNetworkAdapter(INetConnection * pNet, LANSTATUSUI_CONTEXT * pContext, HWND hwndDlg)
644 {
645 HKEY hKey;
646 NETCON_PROPERTIES * pProperties;
647 LPOLESTR pDisplayName;
648 WCHAR szPath[200];
649 DWORD dwSize, dwType;
650 LPWSTR pPnp;
651 HDEVINFO hInfo;
652 SP_DEVINFO_DATA DevInfo;
653 SP_PROPCHANGE_PARAMS PropChangeParams;
654 BOOL bClose = FALSE;
655 NOTIFYICONDATAW nid;
656
657 if (FAILED(pNet->GetProperties(&pProperties)))
658 return;
659
660
661 hInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
662 if (!hInfo)
663 {
664 NcFreeNetconProperties(pProperties);
665 return;
666 }
667
668 if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pDisplayName)))
669 {
670 NcFreeNetconProperties(pProperties);
671 SetupDiDestroyDeviceInfoList(hInfo);
672 return;
673 }
674 NcFreeNetconProperties(pProperties);
675
676 if (FindNetworkAdapter(hInfo, &DevInfo, pDisplayName))
677 {
678 PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
679 PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; //;
680 PropChangeParams.StateChange = DICS_DISABLE;
681 PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
682 PropChangeParams.HwProfile = 0;
683
684 if (SetupDiSetClassInstallParams(hInfo, &DevInfo, &PropChangeParams.ClassInstallHeader, sizeof(SP_PROPCHANGE_PARAMS)))
685 {
686 if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hInfo, &DevInfo))
687 bClose = TRUE;
688 }
689 }
690 SetupDiDestroyDeviceInfoList(hInfo);
691
692 swprintf(szPath, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pDisplayName);
693 CoTaskMemFree(pDisplayName);
694
695 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
696 return;
697
698 dwSize = 0;
699 if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_SZ)
700 {
701 RegCloseKey(hKey);
702 return;
703 }
704
705 pPnp = (LPWSTR)CoTaskMemAlloc(dwSize);
706 if (!pPnp)
707 {
708 RegCloseKey(hKey);
709 return;
710 }
711
712 if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, (LPBYTE)pPnp, &dwSize) != ERROR_SUCCESS)
713 {
714 CoTaskMemFree(pPnp);
715 RegCloseKey(hKey);
716 return;
717 }
718 RegCloseKey(hKey);
719
720 swprintf(szPath, L"System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Enum\\%s", pPnp);
721 CoTaskMemFree(pPnp);
722
723 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
724 return;
725
726 dwSize = 1; /* enable = 0, disable = 1 */
727 RegSetValueExW(hKey, L"CSConfigFlags", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD));
728 RegCloseKey(hKey);
729
730 if (!bClose)
731 return;
732
733 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_CANCEL);
734 ZeroMemory(&nid, sizeof(nid));
735 nid.cbSize = sizeof(nid);
736 nid.uID = pContext->uID;
737 nid.hWnd = pContext->hwndDlg;
738 nid.uFlags = NIF_STATE;
739 nid.dwState = NIS_HIDDEN;
740 nid.dwStateMask = NIS_HIDDEN;
741
742 Shell_NotifyIconW(NIM_MODIFY, &nid);
743 }
744
745
746 INT_PTR
747 CALLBACK
748 LANStatusUiDlg(
749 HWND hwndDlg,
750 UINT uMsg,
751 WPARAM wParam,
752 LPARAM lParam)
753 {
754 PROPSHEETPAGE *page;
755 LANSTATUSUI_CONTEXT * pContext;
756 LPPSHNOTIFY lppsn;
757
758 switch(uMsg)
759 {
760 case WM_INITDIALOG:
761 page = (PROPSHEETPAGE*)lParam;
762 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
763 pContext->hwndDlg = hwndDlg;
764 InitializeLANStatusUiDlg(hwndDlg, pContext);
765 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
766 return TRUE;
767 case WM_COMMAND:
768 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
769 if (LOWORD(wParam) == IDC_STATUS_PROPERTIES)
770 {
771 if (pContext)
772 {
773 ShowNetConnectionProperties(pContext->pNet, GetParent(pContext->hwndDlg));
774 BringWindowToTop(GetParent(pContext->hwndDlg));
775 }
776 break;
777 }
778 else if (LOWORD(wParam) == IDC_ENDISABLE)
779 {
780 DisableNetworkAdapter(pContext->pNet, pContext, hwndDlg);
781 break;
782 }
783 case WM_NOTIFY:
784 lppsn = (LPPSHNOTIFY) lParam;
785 if (lppsn->hdr.code == PSN_APPLY || lppsn->hdr.code == PSN_RESET)
786 {
787 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
788 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
789 pContext->hwndDlg = NULL;
790 return TRUE;
791 }
792 break;
793 }
794 return FALSE;
795 }
796
797 VOID
798 InitializePropertyDialog(
799 LANSTATUSUI_CONTEXT * pContext,
800 NETCON_PROPERTIES * pProperties)
801 {
802 DWORD dwSize, dwAdapterIndex, dwResult;
803 LPOLESTR pStr;
804 IP_ADAPTER_INFO *pAdapterInfo, *pCurAdapter;
805
806 if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pStr)))
807 {
808 return;
809 }
810
811 /* get the IfTable */
812 dwSize = 0;
813 dwResult = GetAdaptersInfo(NULL, &dwSize);
814 if (dwResult!= ERROR_BUFFER_OVERFLOW)
815 {
816 CoTaskMemFree(pStr);
817 return;
818 }
819
820 pAdapterInfo = (PIP_ADAPTER_INFO)CoTaskMemAlloc(dwSize);
821 if (!pAdapterInfo)
822 {
823 CoTaskMemFree(pAdapterInfo);
824 CoTaskMemFree(pStr);
825 return;
826 }
827
828 if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR)
829 {
830 CoTaskMemFree(pAdapterInfo);
831 CoTaskMemFree(pStr);
832 return;
833 }
834
835 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, pStr, &dwAdapterIndex))
836 {
837 CoTaskMemFree(pAdapterInfo);
838 CoTaskMemFree(pStr);
839 return;
840 }
841
842 pCurAdapter = pAdapterInfo;
843 while(pCurAdapter->Index != dwAdapterIndex)
844 pCurAdapter = pCurAdapter->Next;
845
846
847 pContext->IpAddress = inet_addr(pCurAdapter->IpAddressList.IpAddress.String);
848 pContext->SubnetMask = inet_addr(pCurAdapter->IpAddressList.IpMask.String);
849 pContext->Gateway = inet_addr(pCurAdapter->GatewayList.IpAddress.String);
850 pContext->DHCPEnabled = pCurAdapter->DhcpEnabled;
851 CoTaskMemFree(pStr);
852 CoTaskMemFree(pAdapterInfo);
853 pContext->dwAdapterIndex = dwAdapterIndex;
854 }
855
856 VOID
857 ShowStatusPropertyDialog(
858 LANSTATUSUI_CONTEXT *pContext,
859 HWND hwndDlg)
860 {
861 HPROPSHEETPAGE hppages[2];
862 PROPSHEETHEADERW pinfo;
863 NETCON_PROPERTIES * pProperties = NULL;
864
865 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
866 ZeroMemory(hppages, sizeof(hppages));
867 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
868 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW;
869 pinfo.phpage = hppages;
870 pinfo.hwndParent = hwndDlg;
871
872 if (pContext->pNet->GetProperties(&pProperties) == S_OK)
873 {
874 if (pProperties->pszwName)
875 {
876 pinfo.pszCaption = pProperties->pszwName;
877 pinfo.dwFlags |= PSH_PROPTITLE;
878 }
879 InitializePropertyDialog(pContext, pProperties);
880 if (pProperties->MediaType == NCM_LAN && pProperties->Status == NCS_CONNECTED)
881 {
882 hppages[0] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUS), LANStatusUiDlg, (LPARAM)pContext, NULL);
883 if (hppages[0])
884 pinfo.nPages++;
885
886 hppages[pinfo.nPages] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUSADVANCED), LANStatusUiAdvancedDlg, (LPARAM)pContext, NULL);
887 if (hppages[pinfo.nPages])
888 pinfo.nPages++;
889
890 if (pinfo.nPages)
891 {
892 PropertySheetW(&pinfo);
893 }
894 }
895 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED ||
896 pProperties->Status == NCS_HARDWARE_DISABLED)
897 {
898 ShowNetConnectionProperties(pContext->pNet, pContext->hwndDlg);
899 }
900
901 NcFreeNetconProperties(pProperties);
902 }
903 }
904
905 INT_PTR
906 CALLBACK
907 LANStatusDlg(
908 HWND hwndDlg,
909 UINT uMsg,
910 WPARAM wParam,
911 LPARAM lParam)
912 {
913 LANSTATUSUI_CONTEXT * pContext;
914
915 switch(uMsg)
916 {
917 case WM_INITDIALOG:
918 pContext = (LANSTATUSUI_CONTEXT *)lParam;
919 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
920 pContext->nIDEvent = SetTimer(hwndDlg, 0xFABC, 1000, NULL);
921 return TRUE;
922 case WM_TIMER:
923 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
924 if (wParam == (WPARAM)pContext->nIDEvent)
925 {
926 UpdateLanStatus(pContext->hwndDlg, pContext);
927 }
928 break;
929 case WM_SHOWSTATUSDLG:
930 if (LOWORD(lParam) == WM_LBUTTONDOWN)
931 {
932 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
933 if (!pContext)
934 break;
935
936 if (pContext->hwndDlg)
937 {
938 ShowWindow(GetParent(pContext->hwndDlg), SW_SHOW);
939 BringWindowToTop(GetParent(pContext->hwndDlg));
940 }
941 else
942 {
943 ShowStatusPropertyDialog(pContext, hwndDlg);
944 }
945 break;
946 }
947 break;
948 }
949 return FALSE;
950 }
951
952 HRESULT
953 CLanStatus::InitializeNetTaskbarNotifications()
954 {
955 NOTIFYICONDATAW nid;
956 HWND hwndDlg;
957 INetConnectionManager *pNetConMan;
958 IEnumNetConnection *pEnumCon;
959 INetConnection *pNetCon;
960 NETCON_PROPERTIES* pProps;
961 HRESULT hr;
962 ULONG Count;
963 ULONG Index;
964 NOTIFICATION_ITEM * pItem, *pLast = NULL;
965 LANSTATUSUI_CONTEXT * pContext;
966
967 TRACE("InitializeNetTaskbarNotifications\n");
968
969 if (pHead)
970 {
971 pItem = pHead;
972 while(pItem)
973 {
974 hr = pItem->pNet->GetProperties(&pProps);
975 if (SUCCEEDED(hr))
976 {
977 ZeroMemory(&nid, sizeof(nid));
978 nid.cbSize = sizeof(nid);
979 nid.uID = pItem->uID;
980 nid.hWnd = pItem->hwndDlg;
981 nid.uFlags = NIF_STATE;
982 if (pProps->dwCharacter & NCCF_SHOW_ICON)
983 nid.dwState = 0;
984 else
985 nid.dwState = NIS_HIDDEN;
986
987 nid.dwStateMask = NIS_HIDDEN;
988 Shell_NotifyIconW(NIM_MODIFY, &nid);
989 NcFreeNetconProperties(pProps);
990 }
991 pItem = pItem->pNext;
992 }
993 return S_OK;
994 }
995 /* get an instance to of IConnectionManager */
996
997 //hr = CoCreateInstance(&CLSID_ConnectionManager, NULL, CLSCTX_INPROC_SERVER, &IID_INetConnectionManager, (LPVOID*)&pNetConMan);
998
999 hr = INetConnectionManager_Constructor(NULL, IID_INetConnectionManager, (LPVOID*)&pNetConMan);
1000 if (FAILED(hr))
1001 {
1002 ERR("INetConnectionManager_Constructor failed\n");
1003 return hr;
1004 }
1005
1006 hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
1007 if (FAILED(hr))
1008 {
1009 ERR("EnumConnections failed\n");
1010 pNetConMan->Release();
1011 return hr;
1012 }
1013
1014 Index = 1;
1015 do
1016 {
1017 hr = pEnumCon->Next(1, &pNetCon, &Count);
1018 if (hr == S_OK)
1019 {
1020 TRACE("new connection\n");
1021 pItem = (NOTIFICATION_ITEM*)CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM));
1022 if (!pItem)
1023 break;
1024
1025 pContext = (LANSTATUSUI_CONTEXT*)CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT));
1026 if (!pContext)
1027 {
1028 CoTaskMemFree(pItem);
1029 break;
1030 }
1031
1032 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT));
1033 pContext->uID = Index;
1034 pContext->pNet = pNetCon;
1035 pItem->uID = Index;
1036 pItem->pNext = NULL;
1037 pItem->pNet = pNetCon;
1038 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext);
1039 if (hwndDlg)
1040 {
1041 ZeroMemory(&nid, sizeof(nid));
1042 nid.cbSize = sizeof(nid);
1043 nid.uID = Index++;
1044 nid.uFlags = NIF_MESSAGE;
1045 nid.uVersion = 3;
1046 nid.uCallbackMessage = WM_SHOWSTATUSDLG;
1047 nid.hWnd = hwndDlg;
1048
1049 hr = pNetCon->GetProperties(&pProps);
1050 if (SUCCEEDED(hr))
1051 {
1052 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID));
1053 if (!(pProps->dwCharacter & NCCF_SHOW_ICON))
1054 {
1055 nid.dwState = NIS_HIDDEN;
1056 nid.dwStateMask = NIS_HIDDEN;
1057 nid.uFlags |= NIF_STATE;
1058 }
1059 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED)
1060 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF));
1061 else if (pProps->Status == NCS_CONNECTED)
1062 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE));
1063
1064 if (nid.hIcon)
1065 nid.uFlags |= NIF_ICON;
1066
1067 wcscpy(nid.szTip, pProps->pszwName);
1068 nid.uFlags |= NIF_TIP;
1069 }
1070 pContext->hwndStatusDlg = hwndDlg;
1071 pItem->hwndDlg = hwndDlg;
1072
1073 if (Shell_NotifyIconW(NIM_ADD, &nid))
1074 {
1075 if (pLast)
1076 pLast->pNext = pItem;
1077 else
1078 pHead = pItem;
1079
1080 pLast = pItem;
1081 Index++;
1082 }
1083 else
1084 {
1085 ERR("Shell_NotifyIconW failed\n");
1086 CoTaskMemFree(pItem);
1087 }
1088
1089 if (nid.uFlags & NIF_ICON)
1090 DestroyIcon(nid.hIcon);
1091 } else
1092 ERR("CreateDialogParamW failed\n");
1093 }
1094 } while(hr == S_OK);
1095
1096 lpNetMan = pNetConMan;
1097 pEnumCon->Release();
1098 return S_OK;
1099 }
1100
1101 HRESULT
1102 CLanStatus::ShowStatusDialogByCLSID(const GUID *pguidCmdGroup)
1103 {
1104 NOTIFICATION_ITEM *pItem;
1105
1106 pItem = pHead;
1107 while(pItem)
1108 {
1109 if (IsEqualGUID(pItem->guidItem, *pguidCmdGroup))
1110 {
1111 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONDOWN);
1112 return S_OK;
1113 }
1114 pItem = pItem->pNext;
1115 }
1116
1117 ERR("not found\n");
1118 return E_FAIL;
1119 }
1120
1121 HRESULT
1122 WINAPI
1123 CLanStatus::QueryInterface(
1124 REFIID iid,
1125 LPVOID *ppvObj)
1126 {
1127 *ppvObj = NULL;
1128
1129 if (IsEqualIID(iid, IID_IUnknown) ||
1130 IsEqualIID(iid, IID_IOleCommandTarget))
1131 {
1132 *ppvObj = this;
1133 AddRef();
1134 return S_OK;
1135 }
1136 MessageBoxW(NULL, L"IOleCommandTarget_fnQueryInterface", NULL, MB_OK);
1137 return E_NOINTERFACE;
1138 }
1139
1140 ULONG
1141 WINAPI
1142 CLanStatus::AddRef()
1143 {
1144 ULONG refCount = InterlockedIncrement(&ref);
1145
1146 return refCount;
1147 }
1148
1149 ULONG
1150 WINAPI
1151 CLanStatus::Release()
1152 {
1153 #if 0 // WTF?!
1154 ULONG refCount = InterlockedDecrement(&ref);
1155
1156 if (!refCount)
1157 delete this;
1158
1159 return refCount;
1160 #else
1161 return 1;
1162 #endif
1163 }
1164
1165 HRESULT
1166 WINAPI
1167 CLanStatus::QueryStatus(
1168 const GUID *pguidCmdGroup,
1169 ULONG cCmds,
1170 OLECMD *prgCmds,
1171 OLECMDTEXT *pCmdText)
1172 {
1173 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK);
1174 return E_NOTIMPL;
1175 }
1176
1177 HRESULT
1178 WINAPI
1179 CLanStatus::Exec(
1180 const GUID *pguidCmdGroup,
1181 DWORD nCmdID,
1182 DWORD nCmdexecopt,
1183 VARIANT *pvaIn,
1184 VARIANT *pvaOut)
1185 {
1186 if (pguidCmdGroup)
1187 {
1188 if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
1189 {
1190 return InitializeNetTaskbarNotifications();
1191 }
1192 else
1193 {
1194 /* invoke status dialog */
1195 return ShowStatusDialogByCLSID(pguidCmdGroup);
1196 }
1197 }
1198 return S_OK;
1199 }
1200
1201 HRESULT WINAPI LanConnectStatusUI_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv)
1202 {
1203 TRACE("LanConnectStatusUI_Constructor\n");
1204
1205 if (!ppv)
1206 return E_POINTER;
1207
1208 if (pUnkOuter)
1209 return CLASS_E_NOAGGREGATION;
1210
1211 CLanStatus *pLanStatus = new CLanStatus;
1212 if (!pLanStatus)
1213 return E_OUTOFMEMORY;
1214
1215 pLanStatus->AddRef();
1216 static volatile CLanStatus *pCachedLanStatus = NULL;
1217 if (InterlockedCompareExchangePointer((void **)&pCachedLanStatus, pLanStatus, NULL) != NULL)
1218 pLanStatus->Release();
1219
1220 return ((CLanStatus*)pCachedLanStatus)->QueryInterface(riid, ppv);
1221 }
1222