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 358 INT_PTR 359 CALLBACK 360 LANStatusUiDetailsDlg( 361 HWND hwndDlg, 362 UINT uMsg, 363 WPARAM wParam, 364 LPARAM lParam 365 ) 366 { 367 LANSTATUSUI_CONTEXT * pContext; 368 LVITEMW li; 369 WCHAR szBuffer[100]; 370 PIP_ADAPTER_INFO pAdapterInfo, pCurAdapter; 371 PIP_PER_ADAPTER_INFO pPerAdapter; 372 DWORD dwSize; 373 HWND hDlgCtrl; 374 RECT rect; 375 376 switch (uMsg) 377 { 378 case WM_INITDIALOG: 379 pContext = (LANSTATUSUI_CONTEXT*)lParam; 380 381 hDlgCtrl = GetDlgItem(hwndDlg, IDC_DETAILS); 382 383 /* get client rect */ 384 GetClientRect(hDlgCtrl, &rect); 385 386 /* calculate column width */ 387 dwSize = rect.right / 2; 388 389 InsertColumnToListView(hDlgCtrl, IDS_PROPERTY, 0, dwSize); 390 InsertColumnToListView(hDlgCtrl, IDS_VALUE, 1, dwSize); 391 392 dwSize = 0; 393 pCurAdapter = NULL; 394 pAdapterInfo = NULL; 395 if (GetAdaptersInfo(NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) 396 { 397 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize)); 398 if (pAdapterInfo) 399 { 400 if (GetAdaptersInfo(pAdapterInfo, &dwSize) == NO_ERROR) 401 { 402 pCurAdapter = pAdapterInfo; 403 while (pCurAdapter && pCurAdapter->Index != pContext->dwAdapterIndex) 404 pCurAdapter = pCurAdapter->Next; 405 406 if (pCurAdapter->Index != pContext->dwAdapterIndex) 407 pCurAdapter = NULL; 408 } 409 } 410 } 411 412 ZeroMemory(&li, sizeof(LVITEMW)); 413 li.mask = LVIF_TEXT; 414 li.iSubItem = 1; 415 li.pszText = szBuffer; 416 417 if (pCurAdapter) 418 { 419 li.iItem = InsertItemToListView(hDlgCtrl, IDS_PHYSICAL_ADDRESS); 420 if (li.iItem >= 0) 421 { 422 swprintf(szBuffer, L"%02x-%02x-%02x-%02x-%02x-%02x",pCurAdapter->Address[0], pCurAdapter->Address[1], 423 pCurAdapter->Address[2], pCurAdapter->Address[3], pCurAdapter->Address[4], pCurAdapter->Address[5]); 424 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 425 } 426 li.iItem = InsertItemToListView(hDlgCtrl, IDS_IP_ADDRESS); 427 if (li.iItem >= 0) 428 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) 429 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 430 431 li.iItem = InsertItemToListView(hDlgCtrl, IDS_SUBNET_MASK); 432 if (li.iItem >= 0) 433 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpMask.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) 434 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 435 436 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DEF_GATEWAY); 437 if (li.iItem >= 0 && pCurAdapter->GatewayList.IpAddress.String[0] != '0') 438 { 439 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->GatewayList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) 440 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 441 } 442 443 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DHCP_SERVER); 444 if (li.iItem >= 0 && pCurAdapter->DhcpServer.IpAddress.String[0] != '0') 445 { 446 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->DhcpServer.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) 447 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 448 } 449 450 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_OBTAINED); 451 if (li.iItem >= 0 && pCurAdapter->LeaseObtained != NULL) 452 { 453 struct tm *leaseOptained; 454 455 leaseOptained = localtime(&pCurAdapter->LeaseObtained); 456 457 if (wcsftime(szBuffer, 100, L"%m/%d/%Y %H:%M:%S %p", leaseOptained) != 0) 458 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 459 } 460 461 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_EXPIRES); 462 if (li.iItem >= 0 && pCurAdapter->LeaseExpires != NULL) 463 { 464 struct tm *leaseExpire; 465 466 leaseExpire = localtime(&pCurAdapter->LeaseExpires); 467 468 if (wcsftime(szBuffer, 100, L"%m/%d/%Y %H:%M:%S %p", leaseExpire) != 0) 469 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 470 } 471 } 472 473 dwSize = 0; 474 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DNS_SERVERS); 475 if (GetPerAdapterInfo(pContext->dwAdapterIndex, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) 476 { 477 pPerAdapter = static_cast<PIP_PER_ADAPTER_INFO>(CoTaskMemAlloc(dwSize)); 478 if (pPerAdapter) 479 { 480 if (GetPerAdapterInfo(pContext->dwAdapterIndex, pPerAdapter, &dwSize) == ERROR_SUCCESS) 481 { 482 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DNS_SERVERS); 483 if (li.iItem >= 0) 484 AddIPAddressToListView(hDlgCtrl, &pPerAdapter->DnsServerList, li.iItem); 485 } 486 CoTaskMemFree(pPerAdapter); 487 } 488 } 489 490 if (pCurAdapter) 491 { 492 li.iItem = InsertItemToListView(hDlgCtrl, IDS_WINS_SERVERS); 493 if (pCurAdapter->HaveWins) 494 { 495 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->PrimaryWinsServer, li.iItem); 496 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->SecondaryWinsServer, li.iItem+1); 497 } 498 } 499 500 CoTaskMemFree(pAdapterInfo); 501 break; 502 503 case WM_COMMAND: 504 if (LOWORD(wParam) == IDC_CLOSE) 505 { 506 EndDialog(hwndDlg, FALSE); 507 break; 508 } 509 } 510 511 return FALSE; 512 } 513 514 INT_PTR 515 CALLBACK 516 LANStatusUiAdvancedDlg( 517 HWND hwndDlg, 518 UINT uMsg, 519 WPARAM wParam, 520 LPARAM lParam) 521 { 522 WCHAR szBuffer[100] = {0}; 523 PROPSHEETPAGE *page; 524 LANSTATUSUI_CONTEXT * pContext; 525 DWORD dwIpAddr; 526 527 528 switch (uMsg) 529 { 530 case WM_INITDIALOG: 531 page = (PROPSHEETPAGE*)lParam; 532 pContext = (LANSTATUSUI_CONTEXT*)page->lParam; 533 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext); 534 if (pContext->DHCPEnabled) 535 LoadStringW(netshell_hInstance, IDS_ASSIGNED_DHCP, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)); 536 else 537 LoadStringW(netshell_hInstance, IDS_ASSIGNED_MANUAL, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)); 538 539 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; 540 SendDlgItemMessageW(hwndDlg, IDC_DETAILSTYPE, WM_SETTEXT, 0, (LPARAM)szBuffer); 541 542 543 dwIpAddr = ntohl(pContext->IpAddress); 544 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr), 545 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr)); 546 SendDlgItemMessageW(hwndDlg, IDC_DETAILSIP, WM_SETTEXT, 0, (LPARAM)szBuffer); 547 548 dwIpAddr = ntohl(pContext->SubnetMask); 549 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr), 550 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr)); 551 SendDlgItemMessageW(hwndDlg, IDC_DETAILSSUBNET, WM_SETTEXT, 0, (LPARAM)szBuffer); 552 553 dwIpAddr = ntohl(pContext->Gateway); 554 if (dwIpAddr) 555 { 556 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr), 557 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr)); 558 SendDlgItemMessageW(hwndDlg, IDC_DETAILSGATEWAY, WM_SETTEXT, 0, (LPARAM)szBuffer); 559 } 560 return TRUE; 561 case WM_COMMAND: 562 if (LOWORD(wParam) == IDC_DETAILS) 563 { 564 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER); 565 if (pContext) 566 { 567 DialogBoxParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_LAN_NETSTATUSDETAILS), GetParent(hwndDlg), 568 LANStatusUiDetailsDlg, (LPARAM)pContext); 569 } 570 } 571 break; 572 default: 573 break; 574 } 575 return FALSE; 576 } 577 578 VOID 579 DisableNetworkAdapter(INetConnection * pNet, LANSTATUSUI_CONTEXT * pContext, HWND hwndDlg) 580 { 581 HRESULT hr = pNet->Disconnect(); 582 if (FAILED_UNEXPECTEDLY(hr)) 583 return; 584 585 NOTIFYICONDATAW nid; 586 587 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_CANCEL); 588 ZeroMemory(&nid, sizeof(nid)); 589 nid.cbSize = sizeof(nid); 590 nid.uID = pContext->uID; 591 nid.hWnd = pContext->hwndDlg; 592 nid.uFlags = NIF_STATE; 593 nid.dwState = NIS_HIDDEN; 594 nid.dwStateMask = NIS_HIDDEN; 595 596 Shell_NotifyIconW(NIM_MODIFY, &nid); 597 } 598 599 600 INT_PTR 601 CALLBACK 602 LANStatusUiDlg( 603 HWND hwndDlg, 604 UINT uMsg, 605 WPARAM wParam, 606 LPARAM lParam) 607 { 608 PROPSHEETPAGE *page; 609 LANSTATUSUI_CONTEXT * pContext; 610 LPPSHNOTIFY lppsn; 611 612 switch (uMsg) 613 { 614 case WM_INITDIALOG: 615 page = (PROPSHEETPAGE*)lParam; 616 pContext = (LANSTATUSUI_CONTEXT*)page->lParam; 617 pContext->hwndDlg = hwndDlg; 618 InitializeLANStatusUiDlg(hwndDlg, pContext); 619 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext); 620 return TRUE; 621 case WM_COMMAND: 622 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER); 623 if (LOWORD(wParam) == IDC_STATUS_PROPERTIES) 624 { 625 if (pContext) 626 { 627 ShowNetConnectionProperties(pContext->pNet, GetParent(pContext->hwndDlg)); 628 BringWindowToTop(GetParent(pContext->hwndDlg)); 629 } 630 break; 631 } 632 else if (LOWORD(wParam) == IDC_ENDISABLE) 633 { 634 DisableNetworkAdapter(pContext->pNet, pContext, hwndDlg); 635 break; 636 } 637 case WM_NOTIFY: 638 lppsn = (LPPSHNOTIFY) lParam; 639 if (lppsn->hdr.code == PSN_APPLY || lppsn->hdr.code == PSN_RESET) 640 { 641 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER); 642 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); 643 pContext->hwndDlg = NULL; 644 return TRUE; 645 } 646 break; 647 } 648 return FALSE; 649 } 650 651 VOID 652 InitializePropertyDialog( 653 LANSTATUSUI_CONTEXT * pContext, 654 NETCON_PROPERTIES * pProperties) 655 { 656 DWORD dwSize, dwAdapterIndex, dwResult; 657 LPOLESTR pStr; 658 IP_ADAPTER_INFO *pAdapterInfo, *pCurAdapter; 659 660 if (FAILED(StringFromCLSID((CLSID)pProperties->guidId, &pStr))) 661 { 662 return; 663 } 664 665 /* get the IfTable */ 666 dwSize = 0; 667 dwResult = GetAdaptersInfo(NULL, &dwSize); 668 if (dwResult!= ERROR_BUFFER_OVERFLOW) 669 { 670 CoTaskMemFree(pStr); 671 return; 672 } 673 674 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize)); 675 if (!pAdapterInfo) 676 { 677 CoTaskMemFree(pAdapterInfo); 678 CoTaskMemFree(pStr); 679 return; 680 } 681 682 if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR) 683 { 684 CoTaskMemFree(pAdapterInfo); 685 CoTaskMemFree(pStr); 686 return; 687 } 688 689 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, pStr, &dwAdapterIndex)) 690 { 691 CoTaskMemFree(pAdapterInfo); 692 CoTaskMemFree(pStr); 693 return; 694 } 695 696 pCurAdapter = pAdapterInfo; 697 while (pCurAdapter->Index != dwAdapterIndex) 698 pCurAdapter = pCurAdapter->Next; 699 700 701 pContext->IpAddress = inet_addr(pCurAdapter->IpAddressList.IpAddress.String); 702 pContext->SubnetMask = inet_addr(pCurAdapter->IpAddressList.IpMask.String); 703 pContext->Gateway = inet_addr(pCurAdapter->GatewayList.IpAddress.String); 704 pContext->DHCPEnabled = pCurAdapter->DhcpEnabled; 705 CoTaskMemFree(pStr); 706 CoTaskMemFree(pAdapterInfo); 707 pContext->dwAdapterIndex = dwAdapterIndex; 708 } 709 710 static int CALLBACK 711 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) 712 { 713 // NOTE: This callback is needed to set large icon correctly. 714 HICON hIcon; 715 switch (uMsg) 716 { 717 case PSCB_INITIALIZED: 718 { 719 hIcon = LoadIconW(netshell_hInstance, MAKEINTRESOURCEW(IDI_NET_IDLE)); 720 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 721 break; 722 } 723 } 724 return 0; 725 } 726 727 VOID 728 ShowStatusPropertyDialog( 729 LANSTATUSUI_CONTEXT *pContext, 730 HWND hwndDlg) 731 { 732 HPROPSHEETPAGE hppages[2]; 733 PROPSHEETHEADERW pinfo; 734 NETCON_PROPERTIES * pProperties = NULL; 735 736 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW)); 737 ZeroMemory(hppages, sizeof(hppages)); 738 pinfo.dwSize = sizeof(PROPSHEETHEADERW); 739 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW | 740 PSH_USEICONID | PSH_USECALLBACK; 741 pinfo.phpage = hppages; 742 pinfo.hwndParent = hwndDlg; 743 pinfo.hInstance = netshell_hInstance; 744 pinfo.pszIcon = MAKEINTRESOURCEW(IDI_NET_IDLE); 745 pinfo.pfnCallback = PropSheetProc; 746 747 if (pContext->pNet->GetProperties(&pProperties) == S_OK) 748 { 749 if (pProperties->pszwName) 750 { 751 pinfo.pszCaption = pProperties->pszwName; 752 pinfo.dwFlags |= PSH_PROPTITLE; 753 } 754 InitializePropertyDialog(pContext, pProperties); 755 if (pProperties->MediaType == NCM_LAN && pProperties->Status == NCS_CONNECTED) 756 { 757 hppages[0] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUS), LANStatusUiDlg, (LPARAM)pContext, NULL); 758 if (hppages[0]) 759 pinfo.nPages++; 760 761 hppages[pinfo.nPages] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUSADVANCED), LANStatusUiAdvancedDlg, (LPARAM)pContext, NULL); 762 if (hppages[pinfo.nPages]) 763 pinfo.nPages++; 764 765 if (pinfo.nPages) 766 { 767 PropertySheetW(&pinfo); 768 } 769 } 770 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED || 771 pProperties->Status == NCS_HARDWARE_DISABLED) 772 { 773 ShowNetConnectionProperties(pContext->pNet, pContext->hwndDlg); 774 } 775 776 NcFreeNetconProperties(pProperties); 777 } 778 } 779 780 INT_PTR 781 CALLBACK 782 LANStatusDlg( 783 HWND hwndDlg, 784 UINT uMsg, 785 WPARAM wParam, 786 LPARAM lParam) 787 { 788 LANSTATUSUI_CONTEXT * pContext; 789 790 switch (uMsg) 791 { 792 case WM_INITDIALOG: 793 pContext = (LANSTATUSUI_CONTEXT *)lParam; 794 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam); 795 pContext->nIDEvent = SetTimer(hwndDlg, 0xFABC, 1000, NULL); 796 return TRUE; 797 case WM_TIMER: 798 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER); 799 if (wParam == (WPARAM)pContext->nIDEvent) 800 { 801 UpdateLanStatus(pContext->hwndDlg, pContext); 802 } 803 break; 804 case WM_SHOWSTATUSDLG: 805 if (LOWORD(lParam) == WM_LBUTTONDOWN) 806 { 807 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER); 808 if (!pContext) 809 break; 810 811 if (pContext->hwndDlg) 812 { 813 ShowWindow(GetParent(pContext->hwndDlg), SW_SHOW); 814 BringWindowToTop(GetParent(pContext->hwndDlg)); 815 } 816 else 817 { 818 ShowStatusPropertyDialog(pContext, hwndDlg); 819 } 820 break; 821 } 822 break; 823 } 824 return FALSE; 825 } 826 827 HRESULT 828 CLanStatus::InitializeNetTaskbarNotifications() 829 { 830 NOTIFYICONDATAW nid; 831 HWND hwndDlg; 832 CComPtr<INetConnectionManager> pNetConMan; 833 CComPtr<IEnumNetConnection> pEnumCon; 834 CComPtr<INetConnection> pNetCon; 835 NETCON_PROPERTIES* pProps; 836 HRESULT hr; 837 ULONG Count; 838 ULONG Index; 839 NOTIFICATION_ITEM * pItem, *pLast = NULL; 840 LANSTATUSUI_CONTEXT * pContext; 841 842 TRACE("InitializeNetTaskbarNotifications\n"); 843 844 if (m_pHead) 845 { 846 pItem = m_pHead; 847 while (pItem) 848 { 849 hr = pItem->pNet->GetProperties(&pProps); 850 if (SUCCEEDED(hr)) 851 { 852 ZeroMemory(&nid, sizeof(nid)); 853 nid.cbSize = sizeof(nid); 854 nid.uID = pItem->uID; 855 nid.hWnd = pItem->hwndDlg; 856 nid.uFlags = NIF_STATE; 857 if (pProps->dwCharacter & NCCF_SHOW_ICON) 858 nid.dwState = 0; 859 else 860 nid.dwState = NIS_HIDDEN; 861 862 nid.dwStateMask = NIS_HIDDEN; 863 Shell_NotifyIconW(NIM_MODIFY, &nid); 864 NcFreeNetconProperties(pProps); 865 } 866 pItem = pItem->pNext; 867 } 868 return S_OK; 869 } 870 /* get an instance to of IConnectionManager */ 871 hr = CNetConnectionManager_CreateInstance(IID_PPV_ARG(INetConnectionManager, &pNetConMan)); 872 if (FAILED_UNEXPECTEDLY(hr)) 873 return hr; 874 875 hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon); 876 if (FAILED_UNEXPECTEDLY(hr)) 877 return hr; 878 879 Index = 1; 880 while (TRUE) 881 { 882 hr = pEnumCon->Next(1, &pNetCon, &Count); 883 if (hr != S_OK) 884 break; 885 886 TRACE("new connection\n"); 887 pItem = static_cast<NOTIFICATION_ITEM*>(CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM))); 888 if (!pItem) 889 break; 890 891 pContext = static_cast<LANSTATUSUI_CONTEXT*>(CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT))); 892 if (!pContext) 893 { 894 CoTaskMemFree(pItem); 895 break; 896 } 897 898 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT)); 899 pContext->uID = Index; 900 pContext->pNet = pNetCon; 901 pItem->uID = Index; 902 pItem->pNext = NULL; 903 pItem->pNet = pNetCon; 904 pNetCon->AddRef(); 905 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext); 906 if (!hwndDlg) 907 { 908 ERR("CreateDialogParamW failed\n"); 909 continue; 910 } 911 912 ZeroMemory(&nid, sizeof(nid)); 913 nid.cbSize = sizeof(nid); 914 nid.uID = Index++; 915 nid.uFlags = NIF_MESSAGE; 916 nid.uVersion = NOTIFYICON_VERSION; 917 nid.uCallbackMessage = WM_SHOWSTATUSDLG; 918 nid.hWnd = hwndDlg; 919 920 hr = pNetCon->GetProperties(&pProps); 921 if (SUCCEEDED(hr)) 922 { 923 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID)); 924 if (!(pProps->dwCharacter & NCCF_SHOW_ICON)) 925 { 926 nid.dwState = NIS_HIDDEN; 927 nid.dwStateMask = NIS_HIDDEN; 928 nid.uFlags |= NIF_STATE; 929 } 930 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED) 931 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF)); 932 else if (pProps->Status == NCS_CONNECTED) 933 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE)); 934 935 if (nid.hIcon) 936 nid.uFlags |= NIF_ICON; 937 938 wcscpy(nid.szTip, pProps->pszwName); 939 nid.uFlags |= NIF_TIP; 940 } 941 pContext->hwndStatusDlg = hwndDlg; 942 pItem->hwndDlg = hwndDlg; 943 944 if (Shell_NotifyIconW(NIM_ADD, &nid)) 945 { 946 if (pLast) 947 pLast->pNext = pItem; 948 else 949 m_pHead = pItem; 950 951 pLast = pItem; 952 Index++; 953 } 954 else 955 { 956 ERR("Shell_NotifyIconW failed\n"); 957 CoTaskMemFree(pItem); 958 } 959 960 if (nid.uFlags & NIF_ICON) 961 DestroyIcon(nid.hIcon); 962 } 963 964 m_lpNetMan = pNetConMan; 965 return S_OK; 966 } 967 968 HRESULT 969 CLanStatus::ShowStatusDialogByCLSID(const GUID *pguidCmdGroup) 970 { 971 NOTIFICATION_ITEM *pItem; 972 973 pItem = m_pHead; 974 while (pItem) 975 { 976 if (IsEqualGUID(pItem->guidItem, *pguidCmdGroup)) 977 { 978 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONDOWN); 979 return S_OK; 980 } 981 pItem = pItem->pNext; 982 } 983 984 ERR("not found\n"); 985 return E_FAIL; 986 } 987 988 HRESULT 989 WINAPI 990 CLanStatus::QueryStatus( 991 const GUID *pguidCmdGroup, 992 ULONG cCmds, 993 OLECMD *prgCmds, 994 OLECMDTEXT *pCmdText) 995 { 996 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK); 997 return E_NOTIMPL; 998 } 999 1000 HRESULT 1001 WINAPI 1002 CLanStatus::Exec( 1003 const GUID *pguidCmdGroup, 1004 DWORD nCmdID, 1005 DWORD nCmdexecopt, 1006 VARIANT *pvaIn, 1007 VARIANT *pvaOut) 1008 { 1009 if (pguidCmdGroup) 1010 { 1011 if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject)) 1012 { 1013 return InitializeNetTaskbarNotifications(); 1014 } 1015 else 1016 { 1017 /* invoke status dialog */ 1018 return ShowStatusDialogByCLSID(pguidCmdGroup); 1019 } 1020 } 1021 return S_OK; 1022 } 1023