[CRT] Remove useless #undef abort from process.h
[reactos.git] / dll / shellext / netshell / lanstatusui.cpp
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 CLanStatus::CLanStatus() :
13 m_lpNetMan(NULL),
14 m_pHead(NULL)
15 {
16 }
17
18 VOID
19 UpdateLanStatusUiDlg(
20 HWND hwndDlg,
21 MIB_IFROW *IfEntry,
22 LANSTATUSUI_CONTEXT *pContext)
23 {
24 WCHAR szFormat[MAX_PATH] = {0};
25 WCHAR szBuffer[MAX_PATH] = {0};
26 SYSTEMTIME TimeConnected;
27 DWORD DurationSeconds;
28 WCHAR Buffer[100];
29 WCHAR DayBuffer[30];
30 WCHAR LocBuffer[50];
31
32 #if 0
33 ULONGLONG Ticks;
34 #else
35 DWORD Ticks;
36 #endif
37
38 if (IfEntry->dwSpeed < 1000)
39 {
40 if (LoadStringW(netshell_hInstance, IDS_FORMAT_BIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
41 {
42 swprintf(szBuffer, szFormat, IfEntry->dwSpeed);
43 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
44 }
45 }
46 else if (IfEntry->dwSpeed < 1000000)
47 {
48 if (LoadStringW(netshell_hInstance, IDS_FORMAT_KBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
49 {
50 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000);
51 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
52 }
53 }
54 else if (IfEntry->dwSpeed < 1000000000)
55 {
56 if (LoadStringW(netshell_hInstance, IDS_FORMAT_MBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
57 {
58 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000);
59 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
60 }
61 }
62 else
63 {
64 if (LoadStringW(netshell_hInstance, IDS_FORMAT_GBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
65 {
66 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000000);
67 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
68 }
69 }
70
71 if (StrFormatByteSizeW(IfEntry->dwInOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
72 {
73 SendDlgItemMessageW(hwndDlg, IDC_RECEIVED, WM_SETTEXT, 0, (LPARAM)szBuffer);
74 }
75
76 if (StrFormatByteSizeW(IfEntry->dwOutOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
77 {
78 SendDlgItemMessageW(hwndDlg, IDC_SEND, WM_SETTEXT, 0, (LPARAM)szBuffer);
79 }
80
81 #if 0
82 Ticks = GetTickCount64();
83 #else
84 Ticks = GetTickCount();
85 #endif
86
87 DurationSeconds = Ticks / 1000;
88 TimeConnected.wSecond = (DurationSeconds % 60);
89 TimeConnected.wMinute = (DurationSeconds / 60) % 60;
90 TimeConnected.wHour = (DurationSeconds / (60 * 60)) % 24;
91 TimeConnected.wDay = DurationSeconds / (60 * 60 * 24);
92
93 if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &TimeConnected, L"HH':'mm':'ss", LocBuffer, sizeof(LocBuffer) / sizeof(LocBuffer[0])))
94 return;
95
96 if (!TimeConnected.wDay)
97 {
98 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)LocBuffer);
99 }
100 else
101 {
102 if (TimeConnected.wDay == 1)
103 {
104 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAY, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
105 DayBuffer[0] = L'\0';
106 }
107 else
108 {
109 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAYS, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
110 DayBuffer[0] = L'\0';
111 }
112 swprintf(Buffer, DayBuffer, TimeConnected.wDay, LocBuffer);
113 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)Buffer);
114 }
115
116 }
117
118 VOID
119 UpdateLanStatus(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
120 {
121 MIB_IFROW IfEntry;
122 HICON hIcon, hOldIcon = NULL;
123 NOTIFYICONDATAW nid;
124 NETCON_PROPERTIES * pProperties = NULL;
125
126 ZeroMemory(&IfEntry, sizeof(IfEntry));
127 IfEntry.dwIndex = pContext->dwAdapterIndex;
128 if (GetIfEntry(&IfEntry) != NO_ERROR)
129 {
130 return;
131 }
132
133 hIcon = NULL;
134 if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
135 {
136 if (pContext->dwInOctets == IfEntry.dwInOctets && pContext->dwOutOctets == IfEntry.dwOutOctets && pContext->Status != 0)
137 {
138 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 32, 32, LR_SHARED);
139 pContext->Status = 0;
140 }
141 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 1)
142 {
143 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANSREC), IMAGE_ICON, 32, 32, LR_SHARED);
144 pContext->Status = 1;
145 }
146 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->Status != 2)
147 {
148 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_REC), IMAGE_ICON, 32, 32, LR_SHARED);
149 pContext->Status = 2;
150 }
151 else if (pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 3)
152 {
153 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANS), IMAGE_ICON, 32, 32, LR_SHARED);
154 pContext->Status = 3;
155 }
156 }
157 else if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_UNREACHABLE || IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_DISCONNECTED)
158 {
159 if (pContext->Status != 4)
160 {
161 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_SHARED);
162 pContext->Status = 4;
163 }
164 }
165 else if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_NON_OPERATIONAL)
166 {
167 if (pContext->Status != 5)
168 {
169 hIcon = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_SHARED);
170 pContext->Status = 5;
171 }
172 }
173
174 if (hwndDlg && hIcon)
175 {
176 hOldIcon = (HICON)SendDlgItemMessageW(hwndDlg, IDC_NETSTAT, STM_SETICON, (WPARAM)hIcon, 0);
177 if (hOldIcon)
178 DestroyIcon(hOldIcon);
179 }
180
181 ZeroMemory(&nid, sizeof(nid));
182 nid.cbSize = sizeof(nid);
183 nid.uID = pContext->uID;
184 nid.hWnd = pContext->hwndStatusDlg;
185 nid.uVersion = NOTIFYICON_VERSION;
186
187 if (pContext->pNet->GetProperties(&pProperties) == S_OK)
188 {
189 if (pProperties->dwCharacter & NCCF_SHOW_ICON)
190 {
191 if (hwndDlg)
192 nid.hIcon = (HICON)CopyImage(hIcon, IMAGE_ICON, 16, 16, LR_COPYFROMRESOURCE);
193 else
194 nid.hIcon = hIcon;
195
196 if (nid.hIcon)
197 nid.uFlags |= NIF_ICON;
198
199 nid.uFlags |= NIF_STATE;
200 nid.dwState = 0;
201 nid.dwStateMask = NIS_HIDDEN;
202
203 if (pProperties->pszwName)
204 {
205 if (wcslen(pProperties->pszwName) * sizeof(WCHAR) < sizeof(nid.szTip))
206 {
207 nid.uFlags |= NIF_TIP;
208 wcscpy(nid.szTip, pProperties->pszwName);
209 }
210 else
211 {
212 CopyMemory(nid.szTip, pProperties->pszwName, sizeof(nid.szTip) - sizeof(WCHAR));
213 nid.szTip[(sizeof(nid.szTip)/sizeof(WCHAR))-1] = L'\0';
214 nid.uFlags |= NIF_TIP;
215 }
216 }
217 }
218 else
219 {
220 nid.uFlags |= NIF_STATE;
221 nid.dwState = NIS_HIDDEN;
222 nid.dwStateMask = NIS_HIDDEN;
223
224 }
225 NcFreeNetconProperties(pProperties);
226 }
227
228 Shell_NotifyIconW(NIM_MODIFY, &nid);
229
230 if (nid.uFlags & NIF_ICON)
231 DestroyIcon(nid.hIcon);
232
233 pContext->dwInOctets = IfEntry.dwInOctets;
234 pContext->dwOutOctets = IfEntry.dwOutOctets;
235
236 if (hwndDlg)
237 UpdateLanStatusUiDlg(hwndDlg, &IfEntry, pContext);
238 }
239
240
241 VOID
242 InitializeLANStatusUiDlg(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
243 {
244 WCHAR szBuffer[MAX_PATH] = {0};
245 NETCON_PROPERTIES * pProperties;
246
247 if (pContext->pNet->GetProperties(&pProperties) != S_OK)
248 return;
249
250 if (pProperties->Status == NCS_DISCONNECTED)
251 LoadStringW(netshell_hInstance, IDS_STATUS_UNREACHABLE, szBuffer, MAX_PATH);
252 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED)
253 LoadStringW(netshell_hInstance, IDS_STATUS_DISCONNECTED, szBuffer, MAX_PATH);
254 else if (pProperties->Status == NCS_CONNECTING)
255 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTING, szBuffer, MAX_PATH);
256 else if (pProperties->Status == NCS_CONNECTED)
257 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTED, szBuffer, MAX_PATH);
258
259 SendDlgItemMessageW(hwndDlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM)szBuffer);
260
261 pContext->dwInOctets = 0;
262 pContext->dwOutOctets = 0;
263
264 /* update adapter info */
265 pContext->Status = -1;
266 UpdateLanStatus(hwndDlg, pContext);
267 NcFreeNetconProperties(pProperties);
268 }
269
270 static
271 VOID
272 InsertColumnToListView(
273 HWND hDlgCtrl,
274 UINT ResId,
275 UINT SubItem,
276 UINT Size)
277 {
278 WCHAR szBuffer[200];
279 LVCOLUMNW lc;
280
281 if (!LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
282 return;
283
284 memset(&lc, 0, sizeof(LV_COLUMN) );
285 lc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
286 lc.iSubItem = SubItem;
287 lc.fmt = LVCFMT_FIXED_WIDTH;
288 lc.cx = Size;
289 lc.cchTextMax = wcslen(szBuffer);
290 lc.pszText = szBuffer;
291
292 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, SubItem, (LPARAM)&lc);
293 }
294
295 static
296 VOID
297 AddIPAddressToListView(
298 HWND hDlgCtrl,
299 PIP_ADDR_STRING pAddr,
300 INT Index)
301 {
302 LVITEMW li;
303 PIP_ADDR_STRING pCur;
304 WCHAR szBuffer[100];
305 UINT SubIndex;
306
307 ZeroMemory(&li, sizeof(LVITEMW));
308 li.mask = LVIF_TEXT;
309 li.iItem = Index;
310 pCur = pAddr;
311 SubIndex = 0;
312
313 do
314 {
315 if (SubIndex)
316 {
317 ZeroMemory(&li, sizeof(LVITEMW));
318 li.mask = LVIF_TEXT;
319 li.iItem = Index;
320 li.iSubItem = 0;
321 li.pszText = (LPWSTR)L"";
322 li.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
323 }
324
325 if (MultiByteToWideChar(CP_ACP, 0, pCur->IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
326 {
327 li.pszText = szBuffer;
328 li.iSubItem = 1;
329 li.iItem = Index++;
330 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
331 }
332 SubIndex++;
333 pCur = pCur->Next;
334 } while (pCur && pCur->IpAddress.String[0]);
335 }
336
337 static
338 INT
339 InsertItemToListView(
340 HWND hDlgCtrl,
341 UINT ResId)
342 {
343 LVITEMW li;
344 WCHAR szBuffer[100];
345
346 ZeroMemory(&li, sizeof(LVITEMW));
347 li.mask = LVIF_TEXT;
348 li.iItem = ListView_GetItemCount(hDlgCtrl);
349 if (LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
350 {
351 li.pszText = szBuffer;
352 return (INT)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
353 }
354 return -1;
355 }
356
357 static
358 BOOL
359 tmToStr(
360 IN struct tm *pTM,
361 OUT LPWSTR szBuffer,
362 IN UINT nBufferSize)
363 {
364 SYSTEMTIME st;
365 CString strBufferDate;
366 CString strBufferTime;
367 UINT nCharDate, nCharTime;
368 BOOL bResult = FALSE;
369
370 st.wYear = pTM->tm_year + 1900;
371 st.wMonth = pTM->tm_mon + 1;
372 st.wDay = pTM->tm_mday;
373 st.wHour = pTM->tm_hour;
374 st.wMinute = pTM->tm_min;
375 st.wSecond = pTM->tm_sec;
376
377 /* Check required size before cpy/cat */
378 nCharDate = GetDateFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 1;
379 nCharTime = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 1;
380
381 if (GetDateFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, strBufferDate.GetBuffer(nCharDate), nCharDate) &&
382 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, strBufferTime.GetBuffer(nCharTime), nCharTime))
383 {
384 StringCbCopy(szBuffer, nBufferSize, strBufferDate);
385 StringCbCat(szBuffer, nBufferSize, L" ");
386 StringCbCat(szBuffer, nBufferSize, strBufferTime);
387 bResult = TRUE;
388 }
389 strBufferDate.ReleaseBuffer();
390 strBufferTime.ReleaseBuffer();
391
392 return bResult;
393 }
394
395 INT_PTR
396 CALLBACK
397 LANStatusUiDetailsDlg(
398 HWND hwndDlg,
399 UINT uMsg,
400 WPARAM wParam,
401 LPARAM lParam
402 )
403 {
404 LANSTATUSUI_CONTEXT * pContext;
405 LVITEMW li;
406 WCHAR szBuffer[100];
407 PIP_ADAPTER_INFO pAdapterInfo, pCurAdapter;
408 PIP_PER_ADAPTER_INFO pPerAdapter;
409 DWORD dwSize;
410 HWND hDlgCtrl;
411 RECT rect;
412
413 switch (uMsg)
414 {
415 case WM_INITDIALOG:
416 pContext = (LANSTATUSUI_CONTEXT*)lParam;
417
418 hDlgCtrl = GetDlgItem(hwndDlg, IDC_DETAILS);
419
420 /* get client rect */
421 GetClientRect(hDlgCtrl, &rect);
422
423 /* calculate column width */
424 dwSize = rect.right / 2;
425
426 InsertColumnToListView(hDlgCtrl, IDS_PROPERTY, 0, dwSize);
427 InsertColumnToListView(hDlgCtrl, IDS_VALUE, 1, dwSize);
428
429 dwSize = 0;
430 pCurAdapter = NULL;
431 pAdapterInfo = NULL;
432 if (GetAdaptersInfo(NULL, &dwSize) == ERROR_BUFFER_OVERFLOW)
433 {
434 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
435 if (pAdapterInfo)
436 {
437 if (GetAdaptersInfo(pAdapterInfo, &dwSize) == NO_ERROR)
438 {
439 pCurAdapter = pAdapterInfo;
440 while (pCurAdapter && pCurAdapter->Index != pContext->dwAdapterIndex)
441 pCurAdapter = pCurAdapter->Next;
442
443 if (pCurAdapter->Index != pContext->dwAdapterIndex)
444 pCurAdapter = NULL;
445 }
446 }
447 }
448
449 ZeroMemory(&li, sizeof(LVITEMW));
450 li.mask = LVIF_TEXT;
451 li.iSubItem = 1;
452 li.pszText = szBuffer;
453
454 if (pCurAdapter)
455 {
456 li.iItem = InsertItemToListView(hDlgCtrl, IDS_PHYSICAL_ADDRESS);
457 if (li.iItem >= 0)
458 {
459 swprintf(szBuffer, L"%02x-%02x-%02x-%02x-%02x-%02x",pCurAdapter->Address[0], pCurAdapter->Address[1],
460 pCurAdapter->Address[2], pCurAdapter->Address[3], pCurAdapter->Address[4], pCurAdapter->Address[5]);
461 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
462 }
463 li.iItem = InsertItemToListView(hDlgCtrl, IDS_IP_ADDRESS);
464 if (li.iItem >= 0)
465 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
466 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
467
468 li.iItem = InsertItemToListView(hDlgCtrl, IDS_SUBNET_MASK);
469 if (li.iItem >= 0)
470 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpMask.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
471 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
472
473 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DEF_GATEWAY);
474 if (li.iItem >= 0 && pCurAdapter->GatewayList.IpAddress.String[0] != '0')
475 {
476 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->GatewayList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
477 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
478 }
479
480 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DHCP_SERVER);
481 if (li.iItem >= 0 && pCurAdapter->DhcpServer.IpAddress.String[0] != '0')
482 {
483 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->DhcpServer.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
484 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
485 }
486
487 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_OBTAINED);
488 if (li.iItem >= 0 && pCurAdapter->LeaseObtained != NULL)
489 {
490 struct tm *leaseOptained;
491
492 leaseOptained = localtime(&pCurAdapter->LeaseObtained);
493
494 if (tmToStr(leaseOptained, szBuffer, _countof(szBuffer)))
495 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
496 }
497
498 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_EXPIRES);
499 if (li.iItem >= 0 && pCurAdapter->LeaseExpires != NULL)
500 {
501 struct tm *leaseExpire;
502
503 leaseExpire = localtime(&pCurAdapter->LeaseExpires);
504
505 if (tmToStr(leaseExpire, szBuffer, _countof(szBuffer)))
506 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
507 }
508 }
509
510 dwSize = 0;
511 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DNS_SERVERS);
512 if (GetPerAdapterInfo(pContext->dwAdapterIndex, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW)
513 {
514 pPerAdapter = static_cast<PIP_PER_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
515 if (pPerAdapter)
516 {
517 if (GetPerAdapterInfo(pContext->dwAdapterIndex, pPerAdapter, &dwSize) == ERROR_SUCCESS)
518 {
519 if (li.iItem >= 0)
520 AddIPAddressToListView(hDlgCtrl, &pPerAdapter->DnsServerList, li.iItem);
521 }
522 CoTaskMemFree(pPerAdapter);
523 }
524 }
525
526 if (pCurAdapter)
527 {
528 li.iItem = InsertItemToListView(hDlgCtrl, IDS_WINS_SERVERS);
529 if (pCurAdapter->HaveWins)
530 {
531 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->PrimaryWinsServer, li.iItem);
532 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->SecondaryWinsServer, li.iItem+1);
533 }
534 }
535
536 CoTaskMemFree(pAdapterInfo);
537 break;
538
539 case WM_COMMAND:
540 if (LOWORD(wParam) == IDC_CLOSE)
541 {
542 EndDialog(hwndDlg, FALSE);
543 break;
544 }
545 }
546
547 return FALSE;
548 }
549
550 INT_PTR
551 CALLBACK
552 LANStatusUiAdvancedDlg(
553 HWND hwndDlg,
554 UINT uMsg,
555 WPARAM wParam,
556 LPARAM lParam)
557 {
558 WCHAR szBuffer[100] = {0};
559 PROPSHEETPAGE *page;
560 LANSTATUSUI_CONTEXT * pContext;
561 DWORD dwIpAddr;
562
563
564 switch (uMsg)
565 {
566 case WM_INITDIALOG:
567 page = (PROPSHEETPAGE*)lParam;
568 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
569 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
570 if (pContext->DHCPEnabled)
571 LoadStringW(netshell_hInstance, IDS_ASSIGNED_DHCP, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
572 else
573 LoadStringW(netshell_hInstance, IDS_ASSIGNED_MANUAL, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
574
575 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
576 SendDlgItemMessageW(hwndDlg, IDC_DETAILSTYPE, WM_SETTEXT, 0, (LPARAM)szBuffer);
577
578
579 dwIpAddr = ntohl(pContext->IpAddress);
580 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
581 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
582 SendDlgItemMessageW(hwndDlg, IDC_DETAILSIP, WM_SETTEXT, 0, (LPARAM)szBuffer);
583
584 dwIpAddr = ntohl(pContext->SubnetMask);
585 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
586 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
587 SendDlgItemMessageW(hwndDlg, IDC_DETAILSSUBNET, WM_SETTEXT, 0, (LPARAM)szBuffer);
588
589 dwIpAddr = ntohl(pContext->Gateway);
590 if (dwIpAddr)
591 {
592 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
593 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
594 SendDlgItemMessageW(hwndDlg, IDC_DETAILSGATEWAY, WM_SETTEXT, 0, (LPARAM)szBuffer);
595 }
596 return TRUE;
597 case WM_COMMAND:
598 if (LOWORD(wParam) == IDC_DETAILS)
599 {
600 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
601 if (pContext)
602 {
603 DialogBoxParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_LAN_NETSTATUSDETAILS), GetParent(hwndDlg),
604 LANStatusUiDetailsDlg, (LPARAM)pContext);
605 }
606 }
607 break;
608 default:
609 break;
610 }
611 return FALSE;
612 }
613
614 VOID
615 DisableNetworkAdapter(INetConnection * pNet, LANSTATUSUI_CONTEXT * pContext, HWND hwndDlg)
616 {
617 HRESULT hr = pNet->Disconnect();
618 if (FAILED_UNEXPECTEDLY(hr))
619 return;
620
621 NOTIFYICONDATAW nid;
622
623 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_CANCEL);
624 ZeroMemory(&nid, sizeof(nid));
625 nid.cbSize = sizeof(nid);
626 nid.uID = pContext->uID;
627 nid.hWnd = pContext->hwndDlg;
628 nid.uFlags = NIF_STATE;
629 nid.dwState = NIS_HIDDEN;
630 nid.dwStateMask = NIS_HIDDEN;
631
632 Shell_NotifyIconW(NIM_MODIFY, &nid);
633 }
634
635
636 INT_PTR
637 CALLBACK
638 LANStatusUiDlg(
639 HWND hwndDlg,
640 UINT uMsg,
641 WPARAM wParam,
642 LPARAM lParam)
643 {
644 PROPSHEETPAGE *page;
645 LANSTATUSUI_CONTEXT * pContext;
646 LPPSHNOTIFY lppsn;
647
648 switch (uMsg)
649 {
650 case WM_INITDIALOG:
651 page = (PROPSHEETPAGE*)lParam;
652 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
653 pContext->hwndDlg = hwndDlg;
654 InitializeLANStatusUiDlg(hwndDlg, pContext);
655 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
656 return TRUE;
657 case WM_COMMAND:
658 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
659 if (LOWORD(wParam) == IDC_STATUS_PROPERTIES)
660 {
661 if (pContext)
662 {
663 ShowNetConnectionProperties(pContext->pNet, GetParent(pContext->hwndDlg));
664 BringWindowToTop(GetParent(pContext->hwndDlg));
665 }
666 break;
667 }
668 else if (LOWORD(wParam) == IDC_ENDISABLE)
669 {
670 DisableNetworkAdapter(pContext->pNet, pContext, hwndDlg);
671 break;
672 }
673 case WM_NOTIFY:
674 lppsn = (LPPSHNOTIFY) lParam;
675 if (lppsn->hdr.code == PSN_APPLY || lppsn->hdr.code == PSN_RESET)
676 {
677 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
678 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
679 pContext->hwndDlg = NULL;
680 return TRUE;
681 }
682 break;
683 }
684 return FALSE;
685 }
686
687 VOID
688 InitializePropertyDialog(
689 LANSTATUSUI_CONTEXT * pContext,
690 NETCON_PROPERTIES * pProperties)
691 {
692 DWORD dwSize, dwAdapterIndex, dwResult;
693 LPOLESTR pStr;
694 IP_ADAPTER_INFO *pAdapterInfo, *pCurAdapter;
695
696 if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pStr)))
697 {
698 return;
699 }
700
701 /* get the IfTable */
702 dwSize = 0;
703 dwResult = GetAdaptersInfo(NULL, &dwSize);
704 if (dwResult!= ERROR_BUFFER_OVERFLOW)
705 {
706 CoTaskMemFree(pStr);
707 return;
708 }
709
710 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize));
711 if (!pAdapterInfo)
712 {
713 CoTaskMemFree(pAdapterInfo);
714 CoTaskMemFree(pStr);
715 return;
716 }
717
718 if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR)
719 {
720 CoTaskMemFree(pAdapterInfo);
721 CoTaskMemFree(pStr);
722 return;
723 }
724
725 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, pStr, &dwAdapterIndex))
726 {
727 CoTaskMemFree(pAdapterInfo);
728 CoTaskMemFree(pStr);
729 return;
730 }
731
732 pCurAdapter = pAdapterInfo;
733 while (pCurAdapter->Index != dwAdapterIndex)
734 pCurAdapter = pCurAdapter->Next;
735
736
737 pContext->IpAddress = inet_addr(pCurAdapter->IpAddressList.IpAddress.String);
738 pContext->SubnetMask = inet_addr(pCurAdapter->IpAddressList.IpMask.String);
739 pContext->Gateway = inet_addr(pCurAdapter->GatewayList.IpAddress.String);
740 pContext->DHCPEnabled = pCurAdapter->DhcpEnabled;
741 CoTaskMemFree(pStr);
742 CoTaskMemFree(pAdapterInfo);
743 pContext->dwAdapterIndex = dwAdapterIndex;
744 }
745
746 static int CALLBACK
747 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
748 {
749 // NOTE: This callback is needed to set large icon correctly.
750 HICON hIcon;
751 switch (uMsg)
752 {
753 case PSCB_INITIALIZED:
754 {
755 hIcon = LoadIconW(netshell_hInstance, MAKEINTRESOURCEW(IDI_NET_IDLE));
756 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
757 break;
758 }
759 }
760 return 0;
761 }
762
763 VOID
764 ShowStatusPropertyDialog(
765 LANSTATUSUI_CONTEXT *pContext,
766 HWND hwndDlg)
767 {
768 HPROPSHEETPAGE hppages[2];
769 PROPSHEETHEADERW pinfo;
770 NETCON_PROPERTIES * pProperties = NULL;
771
772 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
773 ZeroMemory(hppages, sizeof(hppages));
774 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
775 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW |
776 PSH_USEICONID | PSH_USECALLBACK;
777 pinfo.phpage = hppages;
778 pinfo.hwndParent = hwndDlg;
779 pinfo.hInstance = netshell_hInstance;
780 pinfo.pszIcon = MAKEINTRESOURCEW(IDI_NET_IDLE);
781 pinfo.pfnCallback = PropSheetProc;
782
783 if (pContext->pNet->GetProperties(&pProperties) == S_OK)
784 {
785 if (pProperties->pszwName)
786 {
787 pinfo.pszCaption = pProperties->pszwName;
788 pinfo.dwFlags |= PSH_PROPTITLE;
789 }
790 InitializePropertyDialog(pContext, pProperties);
791 if (pProperties->MediaType == NCM_LAN && pProperties->Status == NCS_CONNECTED)
792 {
793 hppages[0] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUS), LANStatusUiDlg, (LPARAM)pContext, NULL);
794 if (hppages[0])
795 pinfo.nPages++;
796
797 hppages[pinfo.nPages] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUSADVANCED), LANStatusUiAdvancedDlg, (LPARAM)pContext, NULL);
798 if (hppages[pinfo.nPages])
799 pinfo.nPages++;
800
801 if (pinfo.nPages)
802 {
803 PropertySheetW(&pinfo);
804 }
805 }
806 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED ||
807 pProperties->Status == NCS_HARDWARE_DISABLED)
808 {
809 ShowNetConnectionProperties(pContext->pNet, pContext->hwndDlg);
810 }
811
812 NcFreeNetconProperties(pProperties);
813 }
814 }
815
816 INT_PTR
817 CALLBACK
818 LANStatusDlg(
819 HWND hwndDlg,
820 UINT uMsg,
821 WPARAM wParam,
822 LPARAM lParam)
823 {
824 LANSTATUSUI_CONTEXT * pContext;
825
826 switch (uMsg)
827 {
828 case WM_INITDIALOG:
829 pContext = (LANSTATUSUI_CONTEXT *)lParam;
830 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
831 pContext->nIDEvent = SetTimer(hwndDlg, 0xFABC, 1000, NULL);
832 return TRUE;
833 case WM_TIMER:
834 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
835 if (wParam == (WPARAM)pContext->nIDEvent)
836 {
837 UpdateLanStatus(pContext->hwndDlg, pContext);
838 }
839 break;
840 case WM_SHOWSTATUSDLG:
841 if (LOWORD(lParam) == WM_LBUTTONDOWN)
842 {
843 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
844 if (!pContext)
845 break;
846
847 if (pContext->hwndDlg)
848 {
849 ShowWindow(GetParent(pContext->hwndDlg), SW_SHOW);
850 BringWindowToTop(GetParent(pContext->hwndDlg));
851 }
852 else
853 {
854 ShowStatusPropertyDialog(pContext, hwndDlg);
855 }
856 break;
857 }
858 break;
859 }
860 return FALSE;
861 }
862
863 HRESULT
864 CLanStatus::InitializeNetTaskbarNotifications()
865 {
866 NOTIFYICONDATAW nid;
867 HWND hwndDlg;
868 CComPtr<INetConnectionManager> pNetConMan;
869 CComPtr<IEnumNetConnection> pEnumCon;
870 CComPtr<INetConnection> pNetCon;
871 NETCON_PROPERTIES* pProps;
872 HRESULT hr;
873 ULONG Count;
874 ULONG Index;
875 NOTIFICATION_ITEM * pItem, *pLast = NULL;
876 LANSTATUSUI_CONTEXT * pContext;
877
878 TRACE("InitializeNetTaskbarNotifications\n");
879
880 if (m_pHead)
881 {
882 pItem = m_pHead;
883 while (pItem)
884 {
885 hr = pItem->pNet->GetProperties(&pProps);
886 if (SUCCEEDED(hr))
887 {
888 ZeroMemory(&nid, sizeof(nid));
889 nid.cbSize = sizeof(nid);
890 nid.uID = pItem->uID;
891 nid.hWnd = pItem->hwndDlg;
892 nid.uFlags = NIF_STATE;
893 if (pProps->dwCharacter & NCCF_SHOW_ICON)
894 nid.dwState = 0;
895 else
896 nid.dwState = NIS_HIDDEN;
897
898 nid.dwStateMask = NIS_HIDDEN;
899 Shell_NotifyIconW(NIM_MODIFY, &nid);
900 NcFreeNetconProperties(pProps);
901 }
902 pItem = pItem->pNext;
903 }
904 return S_OK;
905 }
906 /* get an instance to of IConnectionManager */
907 hr = CNetConnectionManager_CreateInstance(IID_PPV_ARG(INetConnectionManager, &pNetConMan));
908 if (FAILED_UNEXPECTEDLY(hr))
909 return hr;
910
911 hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
912 if (FAILED_UNEXPECTEDLY(hr))
913 return hr;
914
915 Index = 1;
916 while (TRUE)
917 {
918 pNetCon.Release();
919 hr = pEnumCon->Next(1, &pNetCon, &Count);
920 if (hr != S_OK)
921 break;
922
923 TRACE("new connection\n");
924 pItem = static_cast<NOTIFICATION_ITEM*>(CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM)));
925 if (!pItem)
926 break;
927
928 pContext = static_cast<LANSTATUSUI_CONTEXT*>(CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT)));
929 if (!pContext)
930 {
931 CoTaskMemFree(pItem);
932 break;
933 }
934
935 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT));
936 pContext->uID = Index;
937 pContext->pNet = pNetCon;
938 pItem->uID = Index;
939 pItem->pNext = NULL;
940 pItem->pNet = pNetCon;
941 pNetCon->AddRef();
942 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext);
943 if (!hwndDlg)
944 {
945 ERR("CreateDialogParamW failed\n");
946 continue;
947 }
948
949 ZeroMemory(&nid, sizeof(nid));
950 nid.cbSize = sizeof(nid);
951 nid.uID = Index++;
952 nid.uFlags = NIF_MESSAGE;
953 nid.uVersion = NOTIFYICON_VERSION;
954 nid.uCallbackMessage = WM_SHOWSTATUSDLG;
955 nid.hWnd = hwndDlg;
956
957 hr = pNetCon->GetProperties(&pProps);
958 if (SUCCEEDED(hr))
959 {
960 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID));
961 if (!(pProps->dwCharacter & NCCF_SHOW_ICON))
962 {
963 nid.dwState = NIS_HIDDEN;
964 nid.dwStateMask = NIS_HIDDEN;
965 nid.uFlags |= NIF_STATE;
966 }
967 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED)
968 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF));
969 else if (pProps->Status == NCS_CONNECTED)
970 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE));
971
972 if (nid.hIcon)
973 nid.uFlags |= NIF_ICON;
974
975 wcscpy(nid.szTip, pProps->pszwName);
976 nid.uFlags |= NIF_TIP;
977 }
978 pContext->hwndStatusDlg = hwndDlg;
979 pItem->hwndDlg = hwndDlg;
980
981 if (Shell_NotifyIconW(NIM_ADD, &nid))
982 {
983 if (pLast)
984 pLast->pNext = pItem;
985 else
986 m_pHead = pItem;
987
988 pLast = pItem;
989 Index++;
990 }
991 else
992 {
993 ERR("Shell_NotifyIconW failed\n");
994 CoTaskMemFree(pItem);
995 }
996
997 if (nid.uFlags & NIF_ICON)
998 DestroyIcon(nid.hIcon);
999 }
1000
1001 m_lpNetMan = pNetConMan;
1002 return S_OK;
1003 }
1004
1005 HRESULT
1006 CLanStatus::ShowStatusDialogByCLSID(const GUID *pguidCmdGroup)
1007 {
1008 NOTIFICATION_ITEM *pItem;
1009
1010 pItem = m_pHead;
1011 while (pItem)
1012 {
1013 if (IsEqualGUID(pItem->guidItem, *pguidCmdGroup))
1014 {
1015 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONDOWN);
1016 return S_OK;
1017 }
1018 pItem = pItem->pNext;
1019 }
1020
1021 ERR("not found\n");
1022 return E_FAIL;
1023 }
1024
1025 HRESULT
1026 WINAPI
1027 CLanStatus::QueryStatus(
1028 const GUID *pguidCmdGroup,
1029 ULONG cCmds,
1030 OLECMD *prgCmds,
1031 OLECMDTEXT *pCmdText)
1032 {
1033 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK);
1034 return E_NOTIMPL;
1035 }
1036
1037 HRESULT
1038 WINAPI
1039 CLanStatus::Exec(
1040 const GUID *pguidCmdGroup,
1041 DWORD nCmdID,
1042 DWORD nCmdexecopt,
1043 VARIANT *pvaIn,
1044 VARIANT *pvaOut)
1045 {
1046 if (pguidCmdGroup)
1047 {
1048 if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
1049 {
1050 return InitializeNetTaskbarNotifications();
1051 }
1052 else
1053 {
1054 /* invoke status dialog */
1055 return ShowStatusDialogByCLSID(pguidCmdGroup);
1056 }
1057 }
1058 return S_OK;
1059 }