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 14 CLanStatus::CLanStatus() : 15 m_lpNetMan(NULL), 16 m_pHead(NULL) 17 { 18 } 19 20 VOID 21 UpdateLanStatusUiDlg( 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 120 VOID 121 UpdateLanStatus(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 254 VOID 255 InitializeLANStatusUiDlg(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 283 static 284 VOID 285 InsertColumnToListView( 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 308 static 309 VOID 310 AddIPAddressToListView( 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 350 static 351 INT 352 InsertItemToListView( 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 370 static 371 BOOL 372 tmToStr( 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 408 INT_PTR 409 CALLBACK 410 LANStatusUiDetailsDlg( 411 HWND hwndDlg, 412 UINT uMsg, 413 WPARAM wParam, 414 LPARAM lParam 415 ) 416 { 417 LANSTATUSUI_CONTEXT * pContext; 418 LVITEMW li; 419 WCHAR szBuffer[100]; 420 PIP_ADAPTER_INFO pAdapterInfo, pCurAdapter; 421 PIP_PER_ADAPTER_INFO pPerAdapter; 422 DWORD dwSize; 423 HWND hDlgCtrl; 424 RECT rect; 425 426 switch (uMsg) 427 { 428 case WM_INITDIALOG: 429 pContext = (LANSTATUSUI_CONTEXT*)lParam; 430 431 hDlgCtrl = GetDlgItem(hwndDlg, IDC_DETAILS); 432 433 /* get client rect */ 434 GetClientRect(hDlgCtrl, &rect); 435 436 /* calculate column width */ 437 dwSize = rect.right / 2; 438 439 InsertColumnToListView(hDlgCtrl, IDS_PROPERTY, 0, dwSize); 440 InsertColumnToListView(hDlgCtrl, IDS_VALUE, 1, dwSize); 441 442 dwSize = 0; 443 pCurAdapter = NULL; 444 pAdapterInfo = NULL; 445 if (GetAdaptersInfo(NULL, &dwSize) == ERROR_BUFFER_OVERFLOW) 446 { 447 pAdapterInfo = static_cast<PIP_ADAPTER_INFO>(CoTaskMemAlloc(dwSize)); 448 if (pAdapterInfo) 449 { 450 if (GetAdaptersInfo(pAdapterInfo, &dwSize) == NO_ERROR) 451 { 452 pCurAdapter = pAdapterInfo; 453 while (pCurAdapter && pCurAdapter->Index != pContext->dwAdapterIndex) 454 pCurAdapter = pCurAdapter->Next; 455 456 if (pCurAdapter->Index != pContext->dwAdapterIndex) 457 pCurAdapter = NULL; 458 } 459 } 460 } 461 462 ZeroMemory(&li, sizeof(LVITEMW)); 463 li.mask = LVIF_TEXT; 464 li.iSubItem = 1; 465 li.pszText = szBuffer; 466 467 if (pCurAdapter) 468 { 469 li.iItem = InsertItemToListView(hDlgCtrl, IDS_PHYSICAL_ADDRESS); 470 if (li.iItem >= 0) 471 { 472 swprintf(szBuffer, L"%02x-%02x-%02x-%02x-%02x-%02x",pCurAdapter->Address[0], pCurAdapter->Address[1], 473 pCurAdapter->Address[2], pCurAdapter->Address[3], pCurAdapter->Address[4], pCurAdapter->Address[5]); 474 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 475 } 476 li.iItem = InsertItemToListView(hDlgCtrl, IDS_IP_ADDRESS); 477 if (li.iItem >= 0) 478 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) 479 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 480 481 li.iItem = InsertItemToListView(hDlgCtrl, IDS_SUBNET_MASK); 482 if (li.iItem >= 0) 483 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpMask.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) 484 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 485 486 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DEF_GATEWAY); 487 if (li.iItem >= 0 && pCurAdapter->GatewayList.IpAddress.String[0] != '0') 488 { 489 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->GatewayList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) 490 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li); 491 } 492 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 563 INT_PTR 564 CALLBACK 565 LANStatusUiAdvancedDlg( 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 627 VOID 628 DisableNetworkAdapter(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 649 INT_PTR 650 CALLBACK 651 LANStatusUiDlg( 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 700 VOID 701 InitializePropertyDialog( 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 759 static int CALLBACK 760 PropSheetProc(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 776 VOID 777 ShowStatusPropertyDialog( 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 829 INT_PTR 830 CALLBACK 831 LANStatusDlg( 832 HWND hwndDlg, 833 UINT uMsg, 834 WPARAM wParam, 835 LPARAM lParam) 836 { 837 LANSTATUSUI_CONTEXT * pContext; 838 839 switch (uMsg) 840 { 841 case WM_INITDIALOG: 842 pContext = (LANSTATUSUI_CONTEXT *)lParam; 843 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam); 844 pContext->nIDEvent = SetTimer(hwndDlg, NETTIMERID, 1000, NULL); 845 return TRUE; 846 case WM_TIMER: 847 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER); 848 if (wParam == (WPARAM)pContext->nIDEvent) 849 { 850 UpdateLanStatus(pContext->hwndDlg, pContext); 851 } 852 break; 853 case WM_SHOWSTATUSDLG: 854 if (LOWORD(lParam) == WM_LBUTTONUP) 855 { 856 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER); 857 if (!pContext) 858 break; 859 860 if (pContext->hwndDlg) 861 { 862 ShowWindow(GetParent(pContext->hwndDlg), SW_SHOW); 863 BringWindowToTop(GetParent(pContext->hwndDlg)); 864 } 865 else 866 { 867 ShowStatusPropertyDialog(pContext, hwndDlg); 868 } 869 break; 870 } 871 break; 872 } 873 return FALSE; 874 } 875 876 HRESULT 877 CLanStatus::InitializeNetTaskbarNotifications() 878 { 879 NOTIFYICONDATAW nid; 880 HWND hwndDlg; 881 CComPtr<INetConnectionManager> pNetConMan; 882 CComPtr<IEnumNetConnection> pEnumCon; 883 CComPtr<INetConnection> pNetCon; 884 NETCON_PROPERTIES* pProps; 885 HRESULT hr; 886 ULONG Count; 887 ULONG Index; 888 NOTIFICATION_ITEM * pItem, *pLast = NULL; 889 LANSTATUSUI_CONTEXT * pContext; 890 891 TRACE("InitializeNetTaskbarNotifications\n"); 892 893 if (m_pHead) 894 { 895 pItem = m_pHead; 896 while (pItem) 897 { 898 hr = pItem->pNet->GetProperties(&pProps); 899 if (SUCCEEDED(hr)) 900 { 901 ZeroMemory(&nid, sizeof(nid)); 902 nid.cbSize = sizeof(nid); 903 nid.uID = pItem->uID; 904 nid.hWnd = pItem->hwndDlg; 905 nid.uFlags = NIF_STATE; 906 if (pProps->dwCharacter & NCCF_SHOW_ICON) 907 nid.dwState = 0; 908 else 909 nid.dwState = NIS_HIDDEN; 910 911 nid.dwStateMask = NIS_HIDDEN; 912 Shell_NotifyIconW(NIM_MODIFY, &nid); 913 NcFreeNetconProperties(pProps); 914 } 915 pItem = pItem->pNext; 916 } 917 return S_OK; 918 } 919 /* get an instance to of IConnectionManager */ 920 hr = CNetConnectionManager_CreateInstance(IID_PPV_ARG(INetConnectionManager, &pNetConMan)); 921 if (FAILED_UNEXPECTEDLY(hr)) 922 return hr; 923 924 hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon); 925 if (FAILED_UNEXPECTEDLY(hr)) 926 return hr; 927 928 Index = 1; 929 while (TRUE) 930 { 931 pNetCon.Release(); 932 hr = pEnumCon->Next(1, &pNetCon, &Count); 933 if (hr != S_OK) 934 break; 935 936 TRACE("new connection\n"); 937 pItem = static_cast<NOTIFICATION_ITEM*>(CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM))); 938 if (!pItem) 939 break; 940 941 pContext = static_cast<LANSTATUSUI_CONTEXT*>(CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT))); 942 if (!pContext) 943 { 944 CoTaskMemFree(pItem); 945 break; 946 } 947 948 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT)); 949 pContext->uID = Index; 950 pContext->pNet = pNetCon; 951 pContext->Status = -1; 952 pContext->dwAdapterIndex = Index; 953 pItem->uID = Index; 954 pItem->pNext = NULL; 955 pItem->pNet = pNetCon; 956 pItem->pNet->AddRef(); 957 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext); 958 if (!hwndDlg) 959 { 960 ERR("CreateDialogParamW failed\n"); 961 continue; 962 } 963 964 ZeroMemory(&nid, sizeof(nid)); 965 nid.cbSize = sizeof(nid); 966 nid.uID = Index++; 967 nid.uFlags = NIF_MESSAGE; 968 nid.uVersion = NOTIFYICON_VERSION; 969 nid.uCallbackMessage = WM_SHOWSTATUSDLG; 970 nid.hWnd = hwndDlg; 971 972 hr = pNetCon->GetProperties(&pProps); 973 if (SUCCEEDED(hr)) 974 { 975 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID)); 976 if (!(pProps->dwCharacter & NCCF_SHOW_ICON)) 977 { 978 nid.dwState = NIS_HIDDEN; 979 nid.dwStateMask = NIS_HIDDEN; 980 nid.uFlags |= NIF_STATE; 981 } 982 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED) 983 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF)); 984 else if (pProps->Status == NCS_CONNECTED) 985 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE)); 986 987 if (nid.hIcon) 988 nid.uFlags |= NIF_ICON; 989 990 wcscpy(nid.szTip, pProps->pszwName); 991 nid.uFlags |= NIF_TIP; 992 } 993 pContext->hwndStatusDlg = hwndDlg; 994 pItem->hwndDlg = hwndDlg; 995 996 if (Shell_NotifyIconW(NIM_ADD, &nid)) 997 { 998 if (pLast) 999 pLast->pNext = pItem; 1000 else 1001 m_pHead = pItem; 1002 1003 pLast = pItem; 1004 Index++; 1005 } 1006 else 1007 { 1008 ERR("Shell_NotifyIconW failed\n"); 1009 CoTaskMemFree(pItem); 1010 } 1011 1012 if (nid.uFlags & NIF_ICON) 1013 DestroyIcon(nid.hIcon); 1014 } 1015 1016 m_lpNetMan = pNetConMan; 1017 return S_OK; 1018 } 1019 1020 HRESULT 1021 CLanStatus::ShowStatusDialogByCLSID(const GUID *pguidCmdGroup) 1022 { 1023 NOTIFICATION_ITEM *pItem; 1024 1025 pItem = m_pHead; 1026 while (pItem) 1027 { 1028 if (IsEqualGUID(pItem->guidItem, *pguidCmdGroup)) 1029 { 1030 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONUP); 1031 return S_OK; 1032 } 1033 pItem = pItem->pNext; 1034 } 1035 1036 ERR("not found\n"); 1037 return E_FAIL; 1038 } 1039 1040 HRESULT 1041 WINAPI 1042 CLanStatus::QueryStatus( 1043 const GUID *pguidCmdGroup, 1044 ULONG cCmds, 1045 OLECMD *prgCmds, 1046 OLECMDTEXT *pCmdText) 1047 { 1048 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK); 1049 return E_NOTIMPL; 1050 } 1051 1052 HRESULT 1053 WINAPI 1054 CLanStatus::Exec( 1055 const GUID *pguidCmdGroup, 1056 DWORD nCmdID, 1057 DWORD nCmdexecopt, 1058 VARIANT *pvaIn, 1059 VARIANT *pvaOut) 1060 { 1061 if (pguidCmdGroup) 1062 { 1063 if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject)) 1064 { 1065 return InitializeNetTaskbarNotifications(); 1066 } 1067 else 1068 { 1069 /* invoke status dialog */ 1070 return ShowStatusDialogByCLSID(pguidCmdGroup); 1071 } 1072 } 1073 return S_OK; 1074 } 1075