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 hr = pEnumCon->Next(1, &pNetCon, &Count); 919 if (hr != S_OK) 920 break; 921 922 TRACE("new connection\n"); 923 pItem = static_cast<NOTIFICATION_ITEM*>(CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM))); 924 if (!pItem) 925 break; 926 927 pContext = static_cast<LANSTATUSUI_CONTEXT*>(CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT))); 928 if (!pContext) 929 { 930 CoTaskMemFree(pItem); 931 break; 932 } 933 934 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT)); 935 pContext->uID = Index; 936 pContext->pNet = pNetCon; 937 pItem->uID = Index; 938 pItem->pNext = NULL; 939 pItem->pNet = pNetCon; 940 pNetCon->AddRef(); 941 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext); 942 if (!hwndDlg) 943 { 944 ERR("CreateDialogParamW failed\n"); 945 continue; 946 } 947 948 ZeroMemory(&nid, sizeof(nid)); 949 nid.cbSize = sizeof(nid); 950 nid.uID = Index++; 951 nid.uFlags = NIF_MESSAGE; 952 nid.uVersion = NOTIFYICON_VERSION; 953 nid.uCallbackMessage = WM_SHOWSTATUSDLG; 954 nid.hWnd = hwndDlg; 955 956 hr = pNetCon->GetProperties(&pProps); 957 if (SUCCEEDED(hr)) 958 { 959 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID)); 960 if (!(pProps->dwCharacter & NCCF_SHOW_ICON)) 961 { 962 nid.dwState = NIS_HIDDEN; 963 nid.dwStateMask = NIS_HIDDEN; 964 nid.uFlags |= NIF_STATE; 965 } 966 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED) 967 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF)); 968 else if (pProps->Status == NCS_CONNECTED) 969 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE)); 970 971 if (nid.hIcon) 972 nid.uFlags |= NIF_ICON; 973 974 wcscpy(nid.szTip, pProps->pszwName); 975 nid.uFlags |= NIF_TIP; 976 } 977 pContext->hwndStatusDlg = hwndDlg; 978 pItem->hwndDlg = hwndDlg; 979 980 if (Shell_NotifyIconW(NIM_ADD, &nid)) 981 { 982 if (pLast) 983 pLast->pNext = pItem; 984 else 985 m_pHead = pItem; 986 987 pLast = pItem; 988 Index++; 989 } 990 else 991 { 992 ERR("Shell_NotifyIconW failed\n"); 993 CoTaskMemFree(pItem); 994 } 995 996 if (nid.uFlags & NIF_ICON) 997 DestroyIcon(nid.hIcon); 998 } 999 1000 m_lpNetMan = pNetConMan; 1001 return S_OK; 1002 } 1003 1004 HRESULT 1005 CLanStatus::ShowStatusDialogByCLSID(const GUID *pguidCmdGroup) 1006 { 1007 NOTIFICATION_ITEM *pItem; 1008 1009 pItem = m_pHead; 1010 while (pItem) 1011 { 1012 if (IsEqualGUID(pItem->guidItem, *pguidCmdGroup)) 1013 { 1014 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONDOWN); 1015 return S_OK; 1016 } 1017 pItem = pItem->pNext; 1018 } 1019 1020 ERR("not found\n"); 1021 return E_FAIL; 1022 } 1023 1024 HRESULT 1025 WINAPI 1026 CLanStatus::QueryStatus( 1027 const GUID *pguidCmdGroup, 1028 ULONG cCmds, 1029 OLECMD *prgCmds, 1030 OLECMDTEXT *pCmdText) 1031 { 1032 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK); 1033 return E_NOTIMPL; 1034 } 1035 1036 HRESULT 1037 WINAPI 1038 CLanStatus::Exec( 1039 const GUID *pguidCmdGroup, 1040 DWORD nCmdID, 1041 DWORD nCmdexecopt, 1042 VARIANT *pvaIn, 1043 VARIANT *pvaOut) 1044 { 1045 if (pguidCmdGroup) 1046 { 1047 if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject)) 1048 { 1049 return InitializeNetTaskbarNotifications(); 1050 } 1051 else 1052 { 1053 /* invoke status dialog */ 1054 return ShowStatusDialogByCLSID(pguidCmdGroup); 1055 } 1056 } 1057 return S_OK; 1058 } 1059