Reactos
1/*
2 * PROJECT: ReactOS Shell
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: CLanStatus: Lan connection status dialog
5 * COPYRIGHT: Copyright 2008 Johannes Anderwald (johannes.anderwald@reactos.org)
6 */
7
8#include "precomp.h"
9
10#include <winsock.h>
11
12#define NETTIMERID 0xFABC
13
14CLanStatus::CLanStatus() :
15 m_lpNetMan(NULL),
16 m_pHead(NULL)
17{
18}
19
20VOID
21UpdateLanStatusUiDlg(
22 HWND hwndDlg,
23 MIB_IFROW *IfEntry,
24 LANSTATUSUI_CONTEXT *pContext)
25{
26 WCHAR szFormat[MAX_PATH] = {0};
27 WCHAR szBuffer[MAX_PATH] = {0};
28 SYSTEMTIME TimeConnected;
29 DWORD DurationSeconds;
30 WCHAR Buffer[100];
31 WCHAR DayBuffer[30];
32 WCHAR LocBuffer[50];
33
34#if 0
35 ULONGLONG Ticks;
36#else
37 DWORD Ticks;
38#endif
39
40 if (IfEntry->dwSpeed < 1000)
41 {
42 if (LoadStringW(netshell_hInstance, IDS_FORMAT_BIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
43 {
44 swprintf(szBuffer, szFormat, IfEntry->dwSpeed);
45 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
46 }
47 }
48 else if (IfEntry->dwSpeed < 1000000)
49 {
50 if (LoadStringW(netshell_hInstance, IDS_FORMAT_KBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
51 {
52 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000);
53 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
54 }
55 }
56 else if (IfEntry->dwSpeed < 1000000000)
57 {
58 if (LoadStringW(netshell_hInstance, IDS_FORMAT_MBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
59 {
60 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000);
61 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
62 }
63 }
64 else
65 {
66 if (LoadStringW(netshell_hInstance, IDS_FORMAT_GBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
67 {
68 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000000);
69 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
70 }
71 }
72
73 if (StrFormatByteSizeW(IfEntry->dwInOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
74 {
75 SendDlgItemMessageW(hwndDlg, IDC_RECEIVED, WM_SETTEXT, 0, (LPARAM)szBuffer);
76 }
77
78 if (StrFormatByteSizeW(IfEntry->dwOutOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
79 {
80 SendDlgItemMessageW(hwndDlg, IDC_SEND, WM_SETTEXT, 0, (LPARAM)szBuffer);
81 }
82
83#if 0
84 Ticks = GetTickCount64();
85#else
86 Ticks = GetTickCount();
87#endif
88
89 DurationSeconds = Ticks / 1000;
90 TimeConnected.wSecond = (DurationSeconds % 60);
91 TimeConnected.wMinute = (DurationSeconds / 60) % 60;
92 TimeConnected.wHour = (DurationSeconds / (60 * 60)) % 24;
93 TimeConnected.wDay = DurationSeconds / (60 * 60 * 24);
94
95 if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &TimeConnected, L"HH':'mm':'ss", LocBuffer, sizeof(LocBuffer) / sizeof(LocBuffer[0])))
96 return;
97
98 if (!TimeConnected.wDay)
99 {
100 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)LocBuffer);
101 }
102 else
103 {
104 if (TimeConnected.wDay == 1)
105 {
106 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAY, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
107 DayBuffer[0] = L'\0';
108 }
109 else
110 {
111 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAYS, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
112 DayBuffer[0] = L'\0';
113 }
114 swprintf(Buffer, DayBuffer, TimeConnected.wDay, LocBuffer);
115 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)Buffer);
116 }
117
118}
119
120VOID
121UpdateLanStatus(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
122{
123 MIB_IFROW IfEntry;
124 HICON hIcon, hOldIcon = NULL;
125 NOTIFYICONDATAW nid;
126 NETCON_PROPERTIES * pProperties = NULL;
127
128 ZeroMemory(&IfEntry, sizeof(IfEntry));
129 IfEntry.dwIndex = pContext->dwAdapterIndex;
130 if (GetIfEntry(&IfEntry) != NO_ERROR)
131 {
132 return;
133 }
134
135 if (pContext->Status == (UINT)-1)
136 {
137 /*
138 * On first execution, pContext->dw[In|Out]Octets will be zero while
139 * the interface info is already refreshed with non-null data, so a
140 * gap is normal and does not correspond to an effective TX or RX packet.
141 */
142 pContext->dwInOctets = IfEntry.dwInOctets;
143 pContext->dwOutOctets = IfEntry.dwOutOctets;
144 }
145
146 hIcon = NULL;
147 if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
148 {
149 if (pContext->dwInOctets == IfEntry.dwInOctets && pContext->dwOutOctets == IfEntry.dwOutOctets && pContext->Status != 0)
150 {
151 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 32, 32, LR_SHARED);
152 pContext->Status = 0;
153 }
154 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 1)
155 {
156 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANSREC), IMAGE_ICON, 32, 32, LR_SHARED);
157 pContext->Status = 1;
158 }
159 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->Status != 2)
160 {
161 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_REC), IMAGE_ICON, 32, 32, LR_SHARED);
162 pContext->Status = 2;
163 }
164 else if (pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 3)
165 {
166 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANS), IMAGE_ICON, 32, 32, LR_SHARED);
167 pContext->Status = 3;
168 }
169 }
170 else if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_UNREACHABLE || IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_DISCONNECTED)
171 {
172 if (pContext->Status != 4)
173 {
174 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_SHARED);
175 pContext->Status = 4;
176 }
177 }
178 else if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_NON_OPERATIONAL)
179 {
180 if (pContext->Status != 5)
181 {
182 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_SHARED);
183 pContext->Status = 5;
184 }
185 }
186
187 if (hwndDlg && hIcon)
188 {
189 hOldIcon = (HICON)SendDlgItemMessageW(hwndDlg, IDC_NETSTAT, STM_SETICON, (WPARAM)hIcon, 0);
190 if (hOldIcon)
191 DestroyIcon(hOldIcon);
192 }
193
194 ZeroMemory(&nid, sizeof(nid));
195 nid.cbSize = sizeof(nid);
196 nid.uID = pContext->uID;
197 nid.hWnd = pContext->hwndStatusDlg;
198 nid.uVersion = NOTIFYICON_VERSION;
199
200 if (pContext->pNet->GetProperties(&pProperties) == S_OK)
201 {
202 if (pProperties->dwCharacter & NCCF_SHOW_ICON)
203 {
204 if (hwndDlg)
205 nid.hIcon = (HICON)CopyImage(hIcon, IMAGE_ICON, 16, 16, LR_COPYFROMRESOURCE);
206 else
207 nid.hIcon = hIcon;
208
209 if (nid.hIcon)
210 nid.uFlags |= NIF_ICON;
211
212 nid.uFlags |= NIF_STATE;
213 nid.dwState = 0;
214 nid.dwStateMask = NIS_HIDDEN;
215
216 if (pProperties->pszwName)
217 {
218 if (wcslen(pProperties->pszwName) * sizeof(WCHAR) < sizeof(nid.szTip))
219 {
220 nid.uFlags |= NIF_TIP;
221 wcscpy(nid.szTip, pProperties->pszwName);
222 }
223 else
224 {
225 CopyMemory(nid.szTip, pProperties->pszwName, sizeof(nid.szTip) - sizeof(WCHAR));
226 nid.szTip[(sizeof(nid.szTip)/sizeof(WCHAR))-1] = L'\0';
227 nid.uFlags |= NIF_TIP;
228 }
229 }
230 }
231 else
232 {
233 nid.uFlags |= NIF_STATE;
234 nid.dwState = NIS_HIDDEN;
235 nid.dwStateMask = NIS_HIDDEN;
236
237 }
238 NcFreeNetconProperties(pProperties);
239 }
240
241 Shell_NotifyIconW(NIM_MODIFY, &nid);
242
243 if (nid.uFlags & NIF_ICON)
244 DestroyIcon(nid.hIcon);
245
246 pContext->dwInOctets = IfEntry.dwInOctets;
247 pContext->dwOutOctets = IfEntry.dwOutOctets;
248
249 if (hwndDlg)
250 UpdateLanStatusUiDlg(hwndDlg, &IfEntry, pContext);
251}
252
253
254VOID
255InitializeLANStatusUiDlg(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
256{
257 WCHAR szBuffer[MAX_PATH] = {0};
258 NETCON_PROPERTIES * pProperties;
259
260 if (pContext->pNet->GetProperties(&pProperties) != S_OK)
261 return;
262
263 if (pProperties->Status == NCS_DISCONNECTED)
264 LoadStringW(netshell_hInstance, IDS_STATUS_UNREACHABLE, szBuffer, MAX_PATH);
265 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED)
266 LoadStringW(netshell_hInstance, IDS_STATUS_DISCONNECTED, szBuffer, MAX_PATH);
267 else if (pProperties->Status == NCS_CONNECTING)
268 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTING, szBuffer, MAX_PATH);
269 else if (pProperties->Status == NCS_CONNECTED)
270 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTED, szBuffer, MAX_PATH);
271
272 SendDlgItemMessageW(hwndDlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM)szBuffer);
273
274 pContext->dwInOctets = 0;
275 pContext->dwOutOctets = 0;
276
277 /* update adapter info */
278 pContext->Status = -1;
279 UpdateLanStatus(hwndDlg, pContext);
280 NcFreeNetconProperties(pProperties);
281}
282
283static
284VOID
285InsertColumnToListView(
286 HWND hDlgCtrl,
287 UINT ResId,
288 UINT SubItem,
289 UINT Size)
290{
291 WCHAR szBuffer[200];
292 LVCOLUMNW lc;
293
294 if (!LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
295 return;
296
297 memset(&lc, 0, sizeof(LV_COLUMN) );
298 lc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
299 lc.iSubItem = SubItem;
300 lc.fmt = LVCFMT_FIXED_WIDTH;
301 lc.cx = Size;
302 lc.cchTextMax = wcslen(szBuffer);
303 lc.pszText = szBuffer;
304
305 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, SubItem, (LPARAM)&lc);
306}
307
308static
309VOID
310AddIPAddressToListView(
311 HWND hDlgCtrl,
312 PIP_ADDR_STRING pAddr,
313 INT Index)
314{
315 LVITEMW li;
316 PIP_ADDR_STRING pCur;
317 WCHAR szBuffer[100];
318 UINT SubIndex;
319
320 ZeroMemory(&li, sizeof(LVITEMW));
321 li.mask = LVIF_TEXT;
322 li.iItem = Index;
323 pCur = pAddr;
324 SubIndex = 0;
325
326 do
327 {
328 if (SubIndex)
329 {
330 ZeroMemory(&li, sizeof(LVITEMW));
331 li.mask = LVIF_TEXT;
332 li.iItem = Index;
333 li.iSubItem = 0;
334 li.pszText = (LPWSTR)L"";
335 li.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
336 }
337
338 if (MultiByteToWideChar(CP_ACP, 0, pCur->IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
339 {
340 li.pszText = szBuffer;
341 li.iSubItem = 1;
342 li.iItem = Index++;
343 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
344 }
345 SubIndex++;
346 pCur = pCur->Next;
347 } while (pCur && pCur->IpAddress.String[0]);
348}
349
350static
351INT
352InsertItemToListView(
353 HWND hDlgCtrl,
354 UINT ResId)
355{
356 LVITEMW li;
357 WCHAR szBuffer[100];
358
359 ZeroMemory(&li, sizeof(LVITEMW));
360 li.mask = LVIF_TEXT;
361 li.iItem = ListView_GetItemCount(hDlgCtrl);
362 if (LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
363 {
364 li.pszText = szBuffer;
365 return (INT)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
366 }
367 return -1;
368}
369
370static
371BOOL
372tmToStr(
373 IN struct tm *pTM,
374 OUT LPWSTR szBuffer,
375 IN UINT nBufferSize)
376{
377 SYSTEMTIME st;
378 CString strBufferDate;
379 CString strBufferTime;
380 UINT nCharDate, nCharTime;
381 BOOL bResult = FALSE;
382
383 st.wYear = pTM->tm_year + 1900;
384 st.wMonth = pTM->tm_mon + 1;
385 st.wDay = pTM->tm_mday;
386 st.wHour = pTM->tm_hour;
387 st.wMinute = pTM->tm_min;
388 st.wSecond = pTM->tm_sec;
389
390 /* Check required size before cpy/cat */
391 nCharDate = GetDateFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 1;
392 nCharTime = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 1;
393
394 if (GetDateFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, strBufferDate.GetBuffer(nCharDate), nCharDate) &&
395 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, strBufferTime.GetBuffer(nCharTime), nCharTime))
396 {
397 StringCbCopy(szBuffer, nBufferSize, strBufferDate);
398 StringCbCat(szBuffer, nBufferSize, L" ");
399 StringCbCat(szBuffer, nBufferSize, strBufferTime);
400 bResult = TRUE;
401 }
402 strBufferDate.ReleaseBuffer();
403 strBufferTime.ReleaseBuffer();
404
405 return bResult;
406}
407
408INT_PTR
409CALLBACK
410LANStatusUiDetailsDlg(
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
493 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DHCP_SERVER);
494 if (li.iItem >= 0 && pCurAdapter->DhcpServer.IpAddress.String[0] != '0')
495 {
496 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->DhcpServer.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
497 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
498 }
499
500 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_OBTAINED);
501 if (li.iItem >= 0 && pCurAdapter->LeaseObtained != NULL)
502 {
503 struct tm *leaseOptained;
504
505 leaseOptained = localtime(&pCurAdapter->LeaseObtained);
506
507 if (tmToStr(leaseOptained, szBuffer, _countof(szBuffer)))
508 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
509 }
510
511 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_EXPIRES);
512 if (li.iItem >= 0 && pCurAdapter->LeaseExpires != NULL)
513 {
514 struct tm *leaseExpire;
515
516 leaseExpire = localtime(&pCurAdapter->LeaseExpires);
517
518 if (tmToStr(leaseExpire, szBuffer, _countof(szBuffer)))
519 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
520 }
521 }
522
523 dwSize = 0;
524 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DNS_SERVERS);
525 if (GetPerAdapterInfo(pContext->dwAdapterIndex, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW)
526 {
527 pPerAdapter = static_cast<PIP_PER_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
528 if (pPerAdapter)
529 {
530 if (GetPerAdapterInfo(pContext->dwAdapterIndex, pPerAdapter, &dwSize) == ERROR_SUCCESS)
531 {
532 if (li.iItem >= 0)
533 AddIPAddressToListView(hDlgCtrl, &pPerAdapter->DnsServerList, li.iItem);
534 }
535 CoTaskMemFree(pPerAdapter);
536 }
537 }
538
539 if (pCurAdapter)
540 {
541 li.iItem = InsertItemToListView(hDlgCtrl, IDS_WINS_SERVERS);
542 if (pCurAdapter->HaveWins)
543 {
544 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->PrimaryWinsServer, li.iItem);
545 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->SecondaryWinsServer, li.iItem+1);
546 }
547 }
548
549 CoTaskMemFree(pAdapterInfo);
550 break;
551
552 case WM_COMMAND:
553 if (LOWORD(wParam) == IDC_CLOSE)
554 {
555 EndDialog(hwndDlg, FALSE);
556 break;
557 }
558 }
559
560 return FALSE;
561}
562
563INT_PTR
564CALLBACK
565LANStatusUiAdvancedDlg(
566 HWND hwndDlg,
567 UINT uMsg,
568 WPARAM wParam,
569 LPARAM lParam)
570{
571 WCHAR szBuffer[100] = {0};
572 PROPSHEETPAGE *page;
573 LANSTATUSUI_CONTEXT * pContext;
574 DWORD dwIpAddr;
575
576
577 switch (uMsg)
578 {
579 case WM_INITDIALOG:
580 page = (PROPSHEETPAGE*)lParam;
581 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
582 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
583 if (pContext->DHCPEnabled)
584 LoadStringW(netshell_hInstance, IDS_ASSIGNED_DHCP, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
585 else
586 LoadStringW(netshell_hInstance, IDS_ASSIGNED_MANUAL, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
587
588 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
589 SendDlgItemMessageW(hwndDlg, IDC_DETAILSTYPE, WM_SETTEXT, 0, (LPARAM)szBuffer);
590
591
592 dwIpAddr = ntohl(pContext->IpAddress);
593 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
594 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
595 SendDlgItemMessageW(hwndDlg, IDC_DETAILSIP, WM_SETTEXT, 0, (LPARAM)szBuffer);
596
597 dwIpAddr = ntohl(pContext->SubnetMask);
598 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
599 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
600 SendDlgItemMessageW(hwndDlg, IDC_DETAILSSUBNET, WM_SETTEXT, 0, (LPARAM)szBuffer);
601
602 dwIpAddr = ntohl(pContext->Gateway);
603 if (dwIpAddr)
604 {
605 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
606 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
607 SendDlgItemMessageW(hwndDlg, IDC_DETAILSGATEWAY, WM_SETTEXT, 0, (LPARAM)szBuffer);
608 }
609 return TRUE;
610 case WM_COMMAND:
611 if (LOWORD(wParam) == IDC_DETAILS)
612 {
613 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
614 if (pContext)
615 {
616 DialogBoxParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_LAN_NETSTATUSDETAILS), GetParent(hwndDlg),
617 LANStatusUiDetailsDlg, (LPARAM)pContext);
618 }
619 }
620 break;
621 default:
622 break;
623 }
624 return FALSE;
625}
626
627VOID
628DisableNetworkAdapter(INetConnection * pNet, LANSTATUSUI_CONTEXT * pContext, HWND hwndDlg)
629{
630 HRESULT hr = pNet->Disconnect();
631 if (FAILED_UNEXPECTEDLY(hr))
632 return;
633
634 NOTIFYICONDATAW nid;
635
636 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_CANCEL);
637 ZeroMemory(&nid, sizeof(nid));
638 nid.cbSize = sizeof(nid);
639 nid.uID = pContext->uID;
640 nid.hWnd = pContext->hwndDlg;
641 nid.uFlags = NIF_STATE;
642 nid.dwState = NIS_HIDDEN;
643 nid.dwStateMask = NIS_HIDDEN;
644
645 Shell_NotifyIconW(NIM_MODIFY, &nid);
646}
647
648
649INT_PTR
650CALLBACK
651LANStatusUiDlg(
652 HWND hwndDlg,
653 UINT uMsg,
654 WPARAM wParam,
655 LPARAM lParam)
656{
657 PROPSHEETPAGE *page;
658 LANSTATUSUI_CONTEXT * pContext;
659 LPPSHNOTIFY lppsn;
660
661 switch (uMsg)
662 {
663 case WM_INITDIALOG:
664 page = (PROPSHEETPAGE*)lParam;
665 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
666 pContext->hwndDlg = hwndDlg;
667 InitializeLANStatusUiDlg(hwndDlg, pContext);
668 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
669 return TRUE;
670 case WM_COMMAND:
671 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
672 if (LOWORD(wParam) == IDC_STATUS_PROPERTIES)
673 {
674 if (pContext)
675 {
676 ShowNetConnectionProperties(pContext->pNet, GetParent(pContext->hwndDlg));
677 BringWindowToTop(GetParent(pContext->hwndDlg));
678 }
679 break;
680 }
681 else if (LOWORD(wParam) == IDC_ENDISABLE)
682 {
683 DisableNetworkAdapter(pContext->pNet, pContext, hwndDlg);
684 break;
685 }
686 case WM_NOTIFY:
687 lppsn = (LPPSHNOTIFY) lParam;
688 if (lppsn->hdr.code == PSN_APPLY || lppsn->hdr.code == PSN_RESET)
689 {
690 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
691 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
692 pContext->hwndDlg = NULL;
693 return TRUE;
694 }
695 break;
696 }
697 return FALSE;
698}
699
700VOID
701InitializePropertyDialog(
702 LANSTATUSUI_CONTEXT * pContext,
703 NETCON_PROPERTIES * pProperties)
704{
705 DWORD dwSize, dwAdapterIndex, dwResult;
706 LPOLESTR pStr;
707 IP_ADAPTER_INFO *pAdapterInfo, *pCurAdapter;
708
709 if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pStr)))
710 {
711 return;
712 }
713
714 /* get the IfTable */
715 dwSize = 0;
716 dwResult = GetAdaptersInfo(NULL, &dwSize);
717 if (dwResult!= ERROR_BUFFER_OVERFLOW)
718 {
719 CoTaskMemFree(pStr);
720 return;
721 }
722
723 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
724 if (!pAdapterInfo)
725 {
726 CoTaskMemFree(pAdapterInfo);
727 CoTaskMemFree(pStr);
728 return;
729 }
730
731 if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR)
732 {
733 CoTaskMemFree(pAdapterInfo);
734 CoTaskMemFree(pStr);
735 return;
736 }
737
738 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, pStr, &dwAdapterIndex))
739 {
740 CoTaskMemFree(pAdapterInfo);
741 CoTaskMemFree(pStr);
742 return;
743 }
744
745 pCurAdapter = pAdapterInfo;
746 while (pCurAdapter->Index != dwAdapterIndex)
747 pCurAdapter = pCurAdapter->Next;
748
749
750 pContext->IpAddress = inet_addr(pCurAdapter->IpAddressList.IpAddress.String);
751 pContext->SubnetMask = inet_addr(pCurAdapter->IpAddressList.IpMask.String);
752 pContext->Gateway = inet_addr(pCurAdapter->GatewayList.IpAddress.String);
753 pContext->DHCPEnabled = pCurAdapter->DhcpEnabled;
754 CoTaskMemFree(pStr);
755 CoTaskMemFree(pAdapterInfo);
756 pContext->dwAdapterIndex = dwAdapterIndex;
757}
758
759static int CALLBACK
760PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
761{
762 // NOTE: This callback is needed to set large icon correctly.
763 HICON hIcon;
764 switch (uMsg)
765 {
766 case PSCB_INITIALIZED:
767 {
768 hIcon = LoadIconW(netshell_hInstance, MAKEINTRESOURCEW(IDI_NET_IDLE));
769 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
770 break;
771 }
772 }
773 return 0;
774}
775
776VOID
777ShowStatusPropertyDialog(
778 LANSTATUSUI_CONTEXT *pContext,
779 HWND hwndDlg)
780{
781 HPROPSHEETPAGE hppages[2];
782 PROPSHEETHEADERW pinfo;
783 NETCON_PROPERTIES * pProperties = NULL;
784
785 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
786 ZeroMemory(hppages, sizeof(hppages));
787 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
788 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW |
789 PSH_USEICONID | PSH_USECALLBACK;
790 pinfo.phpage = hppages;
791 pinfo.hwndParent = hwndDlg;
792 pinfo.hInstance = netshell_hInstance;
793 pinfo.pszIcon = MAKEINTRESOURCEW(IDI_NET_IDLE);
794 pinfo.pfnCallback = PropSheetProc;
795
796 if (pContext->pNet->GetProperties(&pProperties) == S_OK)
797 {
798 if (pProperties->pszwName)
799 {
800 pinfo.pszCaption = pProperties->pszwName;
801 pinfo.dwFlags |= PSH_PROPTITLE;
802 }
803 InitializePropertyDialog(pContext, pProperties);
804 if (pProperties->MediaType == NCM_LAN && pProperties->Status == NCS_CONNECTED)
805 {
806 hppages[0] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUS), LANStatusUiDlg, (LPARAM)pContext, NULL);
807 if (hppages[0])
808 pinfo.nPages++;
809
810 hppages[pinfo.nPages] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUSADVANCED), LANStatusUiAdvancedDlg, (LPARAM)pContext, NULL);
811 if (hppages[pinfo.nPages])
812 pinfo.nPages++;
813
814 if (pinfo.nPages)
815 {
816 PropertySheetW(&pinfo);
817 }
818 }
819 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED ||
820 pProperties->Status == NCS_HARDWARE_DISABLED)
821 {
822 ShowNetConnectionProperties(pContext->pNet, pContext->hwndDlg);
823 }
824
825 NcFreeNetconProperties(pProperties);
826 }
827}
828
829VOID ShowNetworkIconContextMenu(
830 _In_ HWND hwndOwner,
831 _In_ LANSTATUSUI_CONTEXT *pContext)
832{
833 if (!pContext || !pContext->pNet)
834 return;
835
836 HMENU hMenu = CreatePopupMenu();
837 if (!hMenu)
838 return;
839
840 POINT pt;
841 GetCursorPos(&pt);
842
843 SetForegroundWindow(hwndOwner);
844
845 // The context menu items, set to their default values.
846 struct
847 {
848 UINT uID;
849 UINT uFlags;
850 UINT_PTR uIDNewItem;
851 } MenuItems[] =
852 {
853 {IDS_NET_ACTIVATE, MF_GRAYED, IDM_NETICON_ENABLE},
854 {IDS_NET_STATUS, MF_GRAYED, IDM_NETICON_STATUS},
855 {IDS_NET_REPAIR, MF_GRAYED, IDM_NETICON_REPAIR},
856 {UINT_MAX, 0, 0}, // Separator
857 {IDS_NET_OPEN_CONNECTIONS, MF_ENABLED, IDM_NETICON_OPEN_CONNECTIONS},
858 {IDS_NET_PROPERTIES, MF_ENABLED | MFS_DEFAULT, IDM_NETICON_PROPERTIES},
859 };
860
861 NETCON_PROPERTIES *pProps = NULL;
862 HRESULT hr = pContext->pNet->GetProperties(&pProps);
863 if (SUCCEEDED(hr) && pProps)
864 {
865 if (pProps->Status == NCS_HARDWARE_DISABLED ||
866 pProps->Status == NCS_MEDIA_DISCONNECTED ||
867 pProps->Status == NCS_DISCONNECTED)
868 {
869 MenuItems[0].uID = IDS_NET_ACTIVATE;
870 MenuItems[0].uFlags = MF_ENABLED | MFS_DEFAULT;
871 MenuItems[0].uIDNewItem = IDM_NETICON_ENABLE;
872 MenuItems[5].uFlags = MF_ENABLED;
873 }
874 else
875 {
876 MenuItems[0].uID = IDS_NET_DEACTIVATE;
877 MenuItems[0].uFlags = MF_ENABLED;
878 MenuItems[0].uIDNewItem = IDM_NETICON_DISABLE;
879 }
880
881 if (pProps->Status == NCS_CONNECTED)
882 {
883 MenuItems[1].uFlags = MF_ENABLED;
884 MenuItems[2].uFlags = MF_ENABLED;
885 }
886 else if (pProps->Status == NCS_CONNECTING)
887 {
888 MenuItems[1].uFlags = MF_ENABLED;
889 MenuItems[2].uFlags = MF_GRAYED;
890 }
891 else
892 {
893 MenuItems[1].uFlags = MF_GRAYED;
894 MenuItems[2].uFlags = MF_GRAYED;
895 }
896
897 NcFreeNetconProperties(pProps);
898 pProps = NULL;
899 }
900 else
901 {
902 MenuItems[0].uFlags = MF_GRAYED;
903 MenuItems[1].uFlags = MF_GRAYED;
904 MenuItems[2].uFlags = MF_GRAYED;
905 MenuItems[5].uFlags = MF_GRAYED;
906 }
907
908 // Set the "Properties" item as default, if the Network "Enable/Disable" item isn't.
909 if (!(MenuItems[0].uFlags & MFS_DEFAULT))
910 MenuItems[5].uFlags |= MFS_DEFAULT;
911
912 WCHAR szMenuItem[128];
913
914 for (USHORT i = 0; i < _countof(MenuItems); ++i)
915 {
916 if (MenuItems[i].uID != UINT_MAX)
917 {
918 if (LoadStringW(netshell_hInstance, MenuItems[i].uID, szMenuItem, _countof(szMenuItem)))
919 AppendMenuW(hMenu, MF_STRING | MenuItems[i].uFlags, MenuItems[i].uIDNewItem, szMenuItem);
920 }
921 else
922 {
923 AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
924 }
925 }
926
927 TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, hwndOwner, NULL);
928
929 PostMessage(hwndOwner, WM_NULL, 0, 0);
930
931 DestroyMenu(hMenu);
932}
933
934HRESULT RepairConnection(INetConnection *pNet, HWND hwndOwner)
935{
936 SHELL_ErrorBox(hwndOwner, HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
937
938 return E_NOTIMPL;
939}
940
941INT_PTR
942CALLBACK
943LANStatusDlg(
944 HWND hwndDlg,
945 UINT uMsg,
946 WPARAM wParam,
947 LPARAM lParam)
948{
949 LANSTATUSUI_CONTEXT * pContext;
950
951 switch (uMsg)
952 {
953 case WM_INITDIALOG:
954 pContext = (LANSTATUSUI_CONTEXT *)lParam;
955 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
956 pContext->hwndStatusDlg = hwndDlg;
957 pContext->nIDEvent = SetTimer(hwndDlg, NETTIMERID, 1000, NULL);
958 return TRUE;
959
960 case WM_DESTROY:
961 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
962 if (pContext && pContext->nIDEvent)
963 {
964 KillTimer(hwndDlg, pContext->nIDEvent);
965 pContext->nIDEvent = 0;
966 }
967 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)NULL);
968 break;
969
970 case WM_TIMER:
971 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
972 if (wParam == (WPARAM)pContext->nIDEvent)
973 {
974 UpdateLanStatus(pContext->hwndDlg, pContext);
975 }
976 break;
977
978 case WM_SHOWSTATUSDLG:
979 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
980 if (!pContext)
981 break;
982
983 switch (LOWORD(lParam))
984 {
985 case WM_LBUTTONUP:
986 if (pContext->hwndDlg)
987 {
988 HWND hwndSheet = GetParent(pContext->hwndDlg);
989 if (hwndSheet)
990 {
991 ShowWindow(hwndSheet, SW_RESTORE);
992 SetForegroundWindow(hwndSheet);
993 BringWindowToTop(hwndSheet);
994 }
995 }
996 else
997 {
998 ShowStatusPropertyDialog(pContext, hwndDlg);
999 }
1000 break;
1001
1002 if (pContext->hwndDlg)
1003 {
1004 ShowWindow(GetParent(pContext->hwndDlg), SW_SHOW);
1005 BringWindowToTop(GetParent(pContext->hwndDlg));
1006 }
1007 else
1008 {
1009 ShowStatusPropertyDialog(pContext, hwndDlg);
1010 }
1011 break;
1012
1013 case WM_RBUTTONUP:
1014 case WM_CONTEXTMENU:
1015 ShowNetworkIconContextMenu(hwndDlg, pContext);
1016 break;
1017 }
1018 break;
1019
1020 case WM_COMMAND:
1021 {
1022 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
1023 if (!pContext || !pContext->pNet)
1024 break;
1025
1026 switch (LOWORD(wParam))
1027 {
1028 case IDM_NETICON_ENABLE:
1029 pContext->pNet->Connect();
1030 UpdateLanStatus(NULL, pContext);
1031 break;
1032
1033 case IDM_NETICON_DISABLE:
1034 pContext->pNet->Disconnect();
1035 UpdateLanStatus(NULL, pContext);
1036 break;
1037
1038 case IDM_NETICON_STATUS:
1039 if (pContext->hwndDlg)
1040 {
1041 HWND hwndSheet = GetParent(pContext->hwndDlg);
1042 if (hwndSheet)
1043 {
1044 ShowWindow(hwndSheet, SW_RESTORE);
1045 SetForegroundWindow(hwndSheet);
1046 BringWindowToTop(hwndSheet);
1047 }
1048 }
1049 else
1050 {
1051 ShowStatusPropertyDialog(pContext, hwndDlg);
1052 }
1053 break;
1054
1055 case IDM_NETICON_REPAIR:
1056 RepairConnection(pContext->pNet, hwndDlg);
1057 break;
1058
1059 case IDM_NETICON_PROPERTIES:
1060 ShowNetConnectionProperties(pContext->pNet, hwndDlg);
1061 break;
1062
1063 case IDM_NETICON_OPEN_CONNECTIONS:
1064 ShellExecuteW(hwndDlg, NULL, L"control", L"netconnections", NULL, SW_SHOWNORMAL);
1065 break;
1066 }
1067 break;
1068 }
1069 }
1070 return FALSE;
1071}
1072
1073HRESULT
1074CLanStatus::InitializeNetTaskbarNotifications()
1075{
1076 NOTIFYICONDATAW nid;
1077 HWND hwndDlg;
1078 CComPtr<INetConnectionManager> pNetConMan;
1079 CComPtr<IEnumNetConnection> pEnumCon;
1080 CComPtr<INetConnection> pNetCon;
1081 NETCON_PROPERTIES* pProps;
1082 HRESULT hr;
1083 ULONG Count;
1084 ULONG Index;
1085 NOTIFICATION_ITEM * pItem, *pLast = NULL;
1086 LANSTATUSUI_CONTEXT * pContext;
1087
1088 TRACE("InitializeNetTaskbarNotifications\n");
1089
1090 if (m_pHead)
1091 {
1092 pItem = m_pHead;
1093 while (pItem)
1094 {
1095 hr = pItem->pNet->GetProperties(&pProps);
1096 if (SUCCEEDED(hr))
1097 {
1098 ZeroMemory(&nid, sizeof(nid));
1099 nid.cbSize = sizeof(nid);
1100 nid.uID = pItem->uID;
1101 nid.hWnd = pItem->hwndDlg;
1102 nid.uFlags = NIF_STATE;
1103 if (pProps->dwCharacter & NCCF_SHOW_ICON)
1104 nid.dwState = 0;
1105 else
1106 nid.dwState = NIS_HIDDEN;
1107
1108 nid.dwStateMask = NIS_HIDDEN;
1109 Shell_NotifyIconW(NIM_MODIFY, &nid);
1110 NcFreeNetconProperties(pProps);
1111 }
1112 pItem = pItem->pNext;
1113 }
1114 return S_OK;
1115 }
1116 /* get an instance to of IConnectionManager */
1117 hr = CNetConnectionManager_CreateInstance(IID_PPV_ARG(INetConnectionManager, &pNetConMan));
1118 if (FAILED_UNEXPECTEDLY(hr))
1119 return hr;
1120
1121 hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
1122 if (FAILED_UNEXPECTEDLY(hr))
1123 return hr;
1124
1125 Index = 1;
1126 while (TRUE)
1127 {
1128 pNetCon.Release();
1129 hr = pEnumCon->Next(1, &pNetCon, &Count);
1130 if (hr != S_OK)
1131 break;
1132
1133 TRACE("new connection\n");
1134 pItem = static_cast<NOTIFICATION_ITEM*>(CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM)));
1135 if (!pItem)
1136 break;
1137
1138 pContext = static_cast<LANSTATUSUI_CONTEXT*>(CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT)));
1139 if (!pContext)
1140 {
1141 CoTaskMemFree(pItem);
1142 break;
1143 }
1144
1145 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT));
1146 pContext->uID = Index;
1147 pContext->pNet = pNetCon;
1148 pContext->Status = -1;
1149 pContext->dwAdapterIndex = Index;
1150 pItem->uID = Index;
1151 pItem->pNext = NULL;
1152 pItem->pNet = pNetCon;
1153 pItem->pNet->AddRef();
1154 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext);
1155 if (!hwndDlg)
1156 {
1157 ERR("CreateDialogParamW failed\n");
1158 continue;
1159 }
1160
1161 ZeroMemory(&nid, sizeof(nid));
1162 nid.cbSize = sizeof(nid);
1163 nid.uID = Index++;
1164 nid.uFlags = NIF_MESSAGE;
1165 nid.uVersion = NOTIFYICON_VERSION;
1166 nid.uCallbackMessage = WM_SHOWSTATUSDLG;
1167 nid.hWnd = hwndDlg;
1168
1169 hr = pNetCon->GetProperties(&pProps);
1170 if (SUCCEEDED(hr))
1171 {
1172 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID));
1173 if (!(pProps->dwCharacter & NCCF_SHOW_ICON))
1174 {
1175 nid.dwState = NIS_HIDDEN;
1176 nid.dwStateMask = NIS_HIDDEN;
1177 nid.uFlags |= NIF_STATE;
1178 }
1179 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED)
1180 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF));
1181 else if (pProps->Status == NCS_CONNECTED)
1182 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE));
1183
1184 if (nid.hIcon)
1185 nid.uFlags |= NIF_ICON;
1186
1187 wcscpy(nid.szTip, pProps->pszwName);
1188 nid.uFlags |= NIF_TIP;
1189 }
1190 pContext->hwndStatusDlg = hwndDlg;
1191 pItem->hwndDlg = hwndDlg;
1192
1193 if (Shell_NotifyIconW(NIM_ADD, &nid))
1194 {
1195 if (pLast)
1196 pLast->pNext = pItem;
1197 else
1198 m_pHead = pItem;
1199
1200 pLast = pItem;
1201 Index++;
1202 }
1203 else
1204 {
1205 ERR("Shell_NotifyIconW failed\n");
1206 CoTaskMemFree(pItem);
1207 }
1208
1209 if (nid.uFlags & NIF_ICON)
1210 DestroyIcon(nid.hIcon);
1211 }
1212
1213 m_lpNetMan = pNetConMan;
1214 return S_OK;
1215}
1216
1217HRESULT
1218CLanStatus::ShowStatusDialogByCLSID(const GUID *pguidCmdGroup)
1219{
1220 NOTIFICATION_ITEM *pItem;
1221
1222 pItem = m_pHead;
1223 while (pItem)
1224 {
1225 if (IsEqualGUID(pItem->guidItem, *pguidCmdGroup))
1226 {
1227 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONUP);
1228 return S_OK;
1229 }
1230 pItem = pItem->pNext;
1231 }
1232
1233 ERR("not found\n");
1234 return E_FAIL;
1235}
1236
1237HRESULT
1238WINAPI
1239CLanStatus::QueryStatus(
1240 const GUID *pguidCmdGroup,
1241 ULONG cCmds,
1242 OLECMD *prgCmds,
1243 OLECMDTEXT *pCmdText)
1244{
1245 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK);
1246 return E_NOTIMPL;
1247}
1248
1249HRESULT
1250WINAPI
1251CLanStatus::Exec(
1252 const GUID *pguidCmdGroup,
1253 DWORD nCmdID,
1254 DWORD nCmdexecopt,
1255 VARIANT *pvaIn,
1256 VARIANT *pvaOut)
1257{
1258 if (pguidCmdGroup)
1259 {
1260 if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
1261 {
1262 return InitializeNetTaskbarNotifications();
1263 }
1264 else
1265 {
1266 /* invoke status dialog */
1267 return ShowStatusDialogByCLSID(pguidCmdGroup);
1268 }
1269 }
1270 return S_OK;
1271}