1 /* 2 * PROJECT: ReactOS WLAN command-line configuration utility 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Allows WLAN configuration via the command prompt 5 * COPYRIGHT: Copyright 2012 Cameron Gutman <cameron.gutman@reactos.org> 6 */ 7 8 #include <stdio.h> 9 #include <stdarg.h> 10 #include <tchar.h> 11 12 #include <windef.h> 13 #include <winbase.h> 14 #include <devioctl.h> 15 #include <ntddndis.h> 16 #include <nuiouser.h> 17 #include <iphlpapi.h> 18 19 #include <conutils.h> 20 21 #include "resource.h" 22 23 BOOL bScan = FALSE; 24 25 BOOL bConnect = FALSE; 26 WCHAR *sSsid = NULL; 27 WCHAR *sWepKey = NULL; 28 BOOL bAdhoc = FALSE; 29 30 BOOL bDisconnect = FALSE; 31 32 VOID DoFormatMessage(DWORD ErrorCode) 33 { 34 if (ErrorCode == ERROR_SUCCESS) 35 return; 36 37 ConMsgPuts(StdErr, FORMAT_MESSAGE_FROM_SYSTEM, 38 NULL, ErrorCode, LANG_USER_DEFAULT); 39 } 40 41 HANDLE 42 OpenDriverHandle(VOID) 43 { 44 HANDLE hDriver; 45 DWORD dwBytesReturned; 46 BOOL bSuccess; 47 48 /* Open a handle to the NDISUIO driver */ 49 hDriver = CreateFileW(NDISUIO_DEVICE_NAME, 50 GENERIC_READ | GENERIC_WRITE, 51 0, 52 NULL, 53 OPEN_EXISTING, 54 FILE_ATTRIBUTE_NORMAL, 55 NULL); 56 if (hDriver == INVALID_HANDLE_VALUE) 57 return INVALID_HANDLE_VALUE; 58 59 /* Wait for binds */ 60 bSuccess = DeviceIoControl(hDriver, 61 IOCTL_NDISUIO_BIND_WAIT, 62 NULL, 63 0, 64 NULL, 65 0, 66 &dwBytesReturned, 67 NULL); 68 if (!bSuccess) 69 { 70 CloseHandle(hDriver); 71 return INVALID_HANDLE_VALUE; 72 } 73 74 return hDriver; 75 } 76 77 BOOL 78 IsWlanAdapter(HANDLE hAdapter) 79 { 80 BOOL bSuccess; 81 DWORD dwBytesReturned; 82 NDISUIO_QUERY_OID QueryOid; 83 84 /* WLAN drivers must support this OID */ 85 QueryOid.Oid = OID_GEN_PHYSICAL_MEDIUM; 86 87 bSuccess = DeviceIoControl(hAdapter, 88 IOCTL_NDISUIO_QUERY_OID_VALUE, 89 &QueryOid, 90 sizeof(QueryOid), 91 &QueryOid, 92 sizeof(QueryOid), 93 &dwBytesReturned, 94 NULL); 95 if (!bSuccess || *(PULONG)QueryOid.Data != NdisPhysicalMediumWirelessLan) 96 return FALSE; 97 98 return TRUE; 99 } 100 101 BOOL 102 OpenAdapterHandle(DWORD Index, HANDLE *hAdapter, IP_ADAPTER_INDEX_MAP *IpInfo) 103 { 104 HANDLE hDriver; 105 BOOL bSuccess; 106 DWORD dwBytesReturned; 107 DWORD QueryBindingSize = sizeof(NDISUIO_QUERY_BINDING) + (1024 * sizeof(WCHAR)); 108 PNDISUIO_QUERY_BINDING QueryBinding; 109 DWORD dwStatus, dwSize; 110 LONG i; 111 PIP_INTERFACE_INFO InterfaceInfo = NULL; 112 113 /* Open the driver handle */ 114 hDriver = OpenDriverHandle(); 115 if (hDriver == INVALID_HANDLE_VALUE) 116 return FALSE; 117 118 /* Allocate the binding struct */ 119 QueryBinding = HeapAlloc(GetProcessHeap(), 0, QueryBindingSize); 120 if (!QueryBinding) 121 { 122 CloseHandle(hDriver); 123 return FALSE; 124 } 125 126 /* Query the adapter binding information */ 127 QueryBinding->BindingIndex = Index; 128 bSuccess = DeviceIoControl(hDriver, 129 IOCTL_NDISUIO_QUERY_BINDING, 130 QueryBinding, 131 QueryBindingSize, 132 QueryBinding, 133 QueryBindingSize, 134 &dwBytesReturned, 135 NULL); 136 137 if (!bSuccess) 138 { 139 HeapFree(GetProcessHeap(), 0, QueryBinding); 140 CloseHandle(hDriver); 141 return FALSE; 142 } 143 144 /* Bind to the adapter */ 145 bSuccess = DeviceIoControl(hDriver, 146 IOCTL_NDISUIO_OPEN_DEVICE, 147 (PUCHAR)QueryBinding + QueryBinding->DeviceNameOffset, 148 QueryBinding->DeviceNameLength, 149 NULL, 150 0, 151 &dwBytesReturned, 152 NULL); 153 154 if (!bSuccess) 155 { 156 HeapFree(GetProcessHeap(), 0, QueryBinding); 157 CloseHandle(hDriver); 158 return FALSE; 159 } 160 161 /* Get interface info from the IP helper */ 162 dwSize = sizeof(IP_INTERFACE_INFO); 163 do { 164 if (InterfaceInfo) HeapFree(GetProcessHeap(), 0, InterfaceInfo); 165 InterfaceInfo = HeapAlloc(GetProcessHeap(), 0, dwSize); 166 if (!InterfaceInfo) 167 { 168 HeapFree(GetProcessHeap(), 0, QueryBinding); 169 CloseHandle(hDriver); 170 return FALSE; 171 } 172 dwStatus = GetInterfaceInfo(InterfaceInfo, &dwSize); 173 } while (dwStatus == ERROR_INSUFFICIENT_BUFFER); 174 175 if (dwStatus != NO_ERROR) 176 { 177 HeapFree(GetProcessHeap(), 0, QueryBinding); 178 HeapFree(GetProcessHeap(), 0, InterfaceInfo); 179 CloseHandle(hDriver); 180 return FALSE; 181 } 182 183 for (i = 0; i < InterfaceInfo->NumAdapters; i++) 184 { 185 PWCHAR InterfaceGuid = wcschr(InterfaceInfo->Adapter[i].Name, L'{'); 186 187 if (InterfaceGuid == NULL) 188 continue; 189 190 if (wcsstr((PWCHAR)((PUCHAR)QueryBinding + QueryBinding->DeviceNameOffset), 191 InterfaceGuid)) 192 { 193 *IpInfo = InterfaceInfo->Adapter[i]; 194 *hAdapter = hDriver; 195 196 HeapFree(GetProcessHeap(), 0, QueryBinding); 197 HeapFree(GetProcessHeap(), 0, InterfaceInfo); 198 199 return TRUE; 200 } 201 } 202 203 HeapFree(GetProcessHeap(), 0, QueryBinding); 204 HeapFree(GetProcessHeap(), 0, InterfaceInfo); 205 CloseHandle(hDriver); 206 207 return FALSE; 208 } 209 210 /* Only works with the first adapter for now */ 211 BOOL 212 OpenWlanAdapter(HANDLE *hAdapter, IP_ADAPTER_INDEX_MAP *IpInfo) 213 { 214 DWORD dwCurrentIndex; 215 216 for (dwCurrentIndex = 0; ; dwCurrentIndex++) 217 { 218 if (!OpenAdapterHandle(dwCurrentIndex, hAdapter, IpInfo)) 219 break; 220 221 if (IsWlanAdapter(*hAdapter)) 222 return TRUE; 223 else 224 CloseHandle(*hAdapter); 225 } 226 227 return FALSE; 228 } 229 230 BOOL 231 WlanDisconnect(HANDLE hAdapter, PIP_ADAPTER_INDEX_MAP IpInfo) 232 { 233 BOOL bSuccess; 234 DWORD dwBytesReturned; 235 NDISUIO_SET_OID SetOid; 236 237 /* Release this IP address */ 238 IpReleaseAddress(IpInfo); 239 240 /* Disassociate from the AP */ 241 SetOid.Oid = OID_802_11_DISASSOCIATE; 242 bSuccess = DeviceIoControl(hAdapter, 243 IOCTL_NDISUIO_SET_OID_VALUE, 244 &SetOid, 245 FIELD_OFFSET(NDISUIO_SET_OID, Data), 246 NULL, 247 0, 248 &dwBytesReturned, 249 NULL); 250 if (!bSuccess) 251 return FALSE; 252 253 ConResPuts(StdOut, IDS_SUCCESS); 254 return TRUE; 255 } 256 257 static 258 UCHAR 259 CharToHex(WCHAR Char) 260 { 261 if ((Char >= L'0') && (Char <= L'9')) 262 return Char - L'0'; 263 264 if ((Char >= L'a') && (Char <= L'f')) 265 return Char - L'a' + 10; 266 267 if ((Char >= L'A') && (Char <= L'F')) 268 return Char - L'A' + 10; 269 270 return 0; 271 } 272 273 BOOL 274 WlanPrintCurrentStatus(HANDLE hAdapter) 275 { 276 PNDISUIO_QUERY_OID QueryOid; 277 DWORD QueryOidSize; 278 BOOL bSuccess; 279 DWORD dwBytesReturned; 280 PNDIS_802_11_SSID SsidInfo; 281 CHAR SsidBuffer[NDIS_802_11_LENGTH_SSID + 1]; 282 DWORD i; 283 WCHAR szMsgBuf[128]; 284 285 QueryOidSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + sizeof(NDIS_802_11_SSID); 286 QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize); 287 if (!QueryOid) 288 return FALSE; 289 290 QueryOid->Oid = OID_802_11_SSID; 291 SsidInfo = (PNDIS_802_11_SSID)QueryOid->Data; 292 293 bSuccess = DeviceIoControl(hAdapter, 294 IOCTL_NDISUIO_QUERY_OID_VALUE, 295 QueryOid, 296 QueryOidSize, 297 QueryOid, 298 QueryOidSize, 299 &dwBytesReturned, 300 NULL); 301 if (!bSuccess) 302 { 303 HeapFree(GetProcessHeap(), 0, QueryOid); 304 return FALSE; 305 } 306 307 /* Copy the SSID to our internal buffer and terminate it */ 308 RtlCopyMemory(SsidBuffer, SsidInfo->Ssid, SsidInfo->SsidLength); 309 SsidBuffer[SsidInfo->SsidLength] = 0; 310 311 HeapFree(GetProcessHeap(), 0, QueryOid); 312 QueryOidSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + sizeof(NDIS_802_11_MAC_ADDRESS); 313 QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize); 314 if (!QueryOid) 315 return FALSE; 316 317 QueryOid->Oid = OID_802_11_BSSID; 318 319 bSuccess = DeviceIoControl(hAdapter, 320 IOCTL_NDISUIO_QUERY_OID_VALUE, 321 QueryOid, 322 QueryOidSize, 323 QueryOid, 324 QueryOidSize, 325 &dwBytesReturned, 326 NULL); 327 if (SsidInfo->SsidLength == 0 || !bSuccess) 328 { 329 ConResPuts(StdOut, IDS_WLAN_DISCONNECT); 330 HeapFree(GetProcessHeap(), 0, QueryOid); 331 return TRUE; 332 } 333 else 334 { 335 ConResPuts(StdOut, IDS_MSG_CURRENT_WIRELESS); 336 } 337 338 printf("SSID: %s\n", SsidBuffer); 339 340 printf("BSSID: "); 341 for (i = 0; i < sizeof(NDIS_802_11_MAC_ADDRESS); i++) 342 { 343 UINT BssidData = QueryOid->Data[i]; 344 345 printf("%.2x", BssidData); 346 347 if (i != sizeof(NDIS_802_11_MAC_ADDRESS) - 1) 348 printf(":"); 349 } 350 printf("\n"); 351 352 HeapFree(GetProcessHeap(), 0, QueryOid); 353 QueryOidSize = sizeof(NDISUIO_QUERY_OID); 354 QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize); 355 if (!QueryOid) 356 return FALSE; 357 358 QueryOid->Oid = OID_802_11_INFRASTRUCTURE_MODE; 359 360 bSuccess = DeviceIoControl(hAdapter, 361 IOCTL_NDISUIO_QUERY_OID_VALUE, 362 QueryOid, 363 QueryOidSize, 364 QueryOid, 365 QueryOidSize, 366 &dwBytesReturned, 367 NULL); 368 if (!bSuccess) 369 { 370 HeapFree(GetProcessHeap(), 0, QueryOid); 371 return FALSE; 372 } 373 374 K32LoadStringW(GetModuleHandle(NULL), 375 *(PUINT)QueryOid->Data == Ndis802_11IBSS ? IDS_ADHOC : IDS_INFRASTRUCTURE, 376 szMsgBuf, 377 ARRAYSIZE(szMsgBuf)); 378 ConResPrintf(StdOut, IDS_MSG_NETWORK_MODE, szMsgBuf); 379 380 QueryOid->Oid = OID_802_11_WEP_STATUS; 381 382 bSuccess = DeviceIoControl(hAdapter, 383 IOCTL_NDISUIO_QUERY_OID_VALUE, 384 QueryOid, 385 QueryOidSize, 386 QueryOid, 387 QueryOidSize, 388 &dwBytesReturned, 389 NULL); 390 if (!bSuccess) 391 { 392 HeapFree(GetProcessHeap(), 0, QueryOid); 393 return FALSE; 394 } 395 396 K32LoadStringW(GetModuleHandle(NULL), 397 *(PUINT)QueryOid->Data == Ndis802_11WEPEnabled ? IDS_YES : IDS_NO, 398 szMsgBuf, 399 ARRAYSIZE(szMsgBuf)); 400 ConResPrintf(StdOut, IDS_MSG_WEP_ENABLED, szMsgBuf); 401 402 printf("\n"); 403 QueryOid->Oid = OID_802_11_RSSI; 404 405 bSuccess = DeviceIoControl(hAdapter, 406 IOCTL_NDISUIO_QUERY_OID_VALUE, 407 QueryOid, 408 QueryOidSize, 409 QueryOid, 410 QueryOidSize, 411 &dwBytesReturned, 412 NULL); 413 if (bSuccess) 414 { 415 /* This OID is optional */ 416 printf("RSSI: %i dBm\n", *(PINT)QueryOid->Data); 417 } 418 419 QueryOid->Oid = OID_802_11_TX_POWER_LEVEL; 420 421 bSuccess = DeviceIoControl(hAdapter, 422 IOCTL_NDISUIO_QUERY_OID_VALUE, 423 QueryOid, 424 QueryOidSize, 425 QueryOid, 426 QueryOidSize, 427 &dwBytesReturned, 428 NULL); 429 if (bSuccess) 430 { 431 /* This OID is optional */ 432 ConResPrintf(StdOut, IDS_MSG_TRANSMISSION_POWER, *(PUINT)QueryOid->Data); 433 } 434 435 printf("\n"); 436 437 QueryOid->Oid = OID_802_11_NUMBER_OF_ANTENNAS; 438 439 bSuccess = DeviceIoControl(hAdapter, 440 IOCTL_NDISUIO_QUERY_OID_VALUE, 441 QueryOid, 442 QueryOidSize, 443 QueryOid, 444 QueryOidSize, 445 &dwBytesReturned, 446 NULL); 447 if (bSuccess) 448 { 449 /* This OID is optional */ 450 ConResPrintf(StdOut, IDS_MSG_ANTENNA_COUNT, *(PUINT)QueryOid->Data); 451 } 452 453 QueryOid->Oid = OID_802_11_TX_ANTENNA_SELECTED; 454 455 bSuccess = DeviceIoControl(hAdapter, 456 IOCTL_NDISUIO_QUERY_OID_VALUE, 457 QueryOid, 458 QueryOidSize, 459 QueryOid, 460 QueryOidSize, 461 &dwBytesReturned, 462 NULL); 463 if (bSuccess) 464 { 465 UINT TransmitAntenna = *(PUINT)QueryOid->Data; 466 467 if (TransmitAntenna != 0xFFFFFFFF) 468 ConResPrintf(StdOut, IDS_MSG_TRANSMIT_ANTENNA, TransmitAntenna); 469 else 470 ConResPuts(StdOut, IDS_MSG_TRANSMIT_ANTENNA_ANY); 471 } 472 473 QueryOid->Oid = OID_802_11_RX_ANTENNA_SELECTED; 474 475 bSuccess = DeviceIoControl(hAdapter, 476 IOCTL_NDISUIO_QUERY_OID_VALUE, 477 QueryOid, 478 QueryOidSize, 479 QueryOid, 480 QueryOidSize, 481 &dwBytesReturned, 482 NULL); 483 if (bSuccess) 484 { 485 UINT ReceiveAntenna = *(PUINT)QueryOid->Data; 486 487 if (ReceiveAntenna != 0xFFFFFFFF) 488 ConResPrintf(StdOut, IDS_MSG_RECEIVE_ANTENNA, ReceiveAntenna); 489 else 490 ConResPuts(StdOut, IDS_MSG_RECEIVE_ANTENNA_ANY); 491 } 492 493 printf("\n"); 494 495 QueryOid->Oid = OID_802_11_FRAGMENTATION_THRESHOLD; 496 497 bSuccess = DeviceIoControl(hAdapter, 498 IOCTL_NDISUIO_QUERY_OID_VALUE, 499 QueryOid, 500 QueryOidSize, 501 QueryOid, 502 QueryOidSize, 503 &dwBytesReturned, 504 NULL); 505 if (bSuccess) 506 { 507 /* This OID is optional */ 508 ConResPrintf(StdOut, IDS_MSG_FRAGMENT_THRESHOLD, *(PUINT)QueryOid->Data); 509 } 510 511 QueryOid->Oid = OID_802_11_RTS_THRESHOLD; 512 513 bSuccess = DeviceIoControl(hAdapter, 514 IOCTL_NDISUIO_QUERY_OID_VALUE, 515 QueryOid, 516 QueryOidSize, 517 QueryOid, 518 QueryOidSize, 519 &dwBytesReturned, 520 NULL); 521 if (bSuccess) 522 { 523 /* This OID is optional */ 524 ConResPrintf(StdOut, IDS_MSG_RTS_THRESHOLD, *(PUINT)QueryOid->Data); 525 } 526 527 HeapFree(GetProcessHeap(), 0, QueryOid); 528 529 printf("\n"); 530 return TRUE; 531 } 532 533 BOOL 534 WlanConnect(HANDLE hAdapter) 535 { 536 CHAR SsidBuffer[NDIS_802_11_LENGTH_SSID + 1]; 537 BOOL bSuccess; 538 DWORD dwBytesReturned, SetOidSize; 539 PNDISUIO_SET_OID SetOid; 540 PNDIS_802_11_SSID Ssid; 541 DWORD i; 542 543 SetOidSize = sizeof(NDISUIO_SET_OID); 544 SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize); 545 if (!SetOid) 546 return FALSE; 547 548 /* Set the network mode */ 549 SetOid->Oid = OID_802_11_INFRASTRUCTURE_MODE; 550 *(PULONG)SetOid->Data = bAdhoc ? Ndis802_11IBSS : Ndis802_11Infrastructure; 551 552 bSuccess = DeviceIoControl(hAdapter, 553 IOCTL_NDISUIO_SET_OID_VALUE, 554 SetOid, 555 SetOidSize, 556 NULL, 557 0, 558 &dwBytesReturned, 559 NULL); 560 if (!bSuccess) 561 { 562 HeapFree(GetProcessHeap(), 0, SetOid); 563 return FALSE; 564 } 565 566 /* Set the authentication mode */ 567 SetOid->Oid = OID_802_11_AUTHENTICATION_MODE; 568 *(PULONG)SetOid->Data = sWepKey ? Ndis802_11AuthModeShared : Ndis802_11AuthModeOpen; 569 570 bSuccess = DeviceIoControl(hAdapter, 571 IOCTL_NDISUIO_SET_OID_VALUE, 572 SetOid, 573 SetOidSize, 574 NULL, 575 0, 576 &dwBytesReturned, 577 NULL); 578 if (!bSuccess) 579 { 580 HeapFree(GetProcessHeap(), 0, SetOid); 581 return FALSE; 582 } 583 584 if (sWepKey) 585 { 586 PNDIS_802_11_WEP WepData; 587 588 HeapFree(GetProcessHeap(), 0, SetOid); 589 590 SetOidSize = FIELD_OFFSET(NDISUIO_SET_OID, Data) + 591 FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial) + 592 (wcslen(sWepKey) >> 1); 593 SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize); 594 if (!SetOid) 595 return FALSE; 596 597 /* Add the WEP key */ 598 SetOid->Oid = OID_802_11_ADD_WEP; 599 WepData = (PNDIS_802_11_WEP)SetOid->Data; 600 601 WepData->KeyIndex = 0x80000000; 602 WepData->KeyLength = wcslen(sWepKey) >> 1; 603 WepData->Length = FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial) + WepData->KeyLength; 604 605 /* Assemble the hex key */ 606 i = 0; 607 while (sWepKey[i << 1] != '\0') 608 { 609 WepData->KeyMaterial[i] = CharToHex(sWepKey[i << 1]) << 4; 610 WepData->KeyMaterial[i] |= CharToHex(sWepKey[(i << 1) + 1]); 611 i++; 612 } 613 614 bSuccess = DeviceIoControl(hAdapter, 615 IOCTL_NDISUIO_SET_OID_VALUE, 616 SetOid, 617 SetOidSize, 618 NULL, 619 0, 620 &dwBytesReturned, 621 NULL); 622 if (!bSuccess) 623 { 624 HeapFree(GetProcessHeap(), 0, SetOid); 625 return FALSE; 626 } 627 } 628 629 /* Set the encryption status */ 630 SetOid->Oid = OID_802_11_WEP_STATUS; 631 *(PULONG)SetOid->Data = sWepKey ? Ndis802_11WEPEnabled : Ndis802_11WEPDisabled; 632 633 bSuccess = DeviceIoControl(hAdapter, 634 IOCTL_NDISUIO_SET_OID_VALUE, 635 SetOid, 636 SetOidSize, 637 NULL, 638 0, 639 &dwBytesReturned, 640 NULL); 641 if (!bSuccess) 642 { 643 HeapFree(GetProcessHeap(), 0, SetOid); 644 return FALSE; 645 } 646 647 HeapFree(GetProcessHeap(), 0, SetOid); 648 SetOidSize = FIELD_OFFSET(NDISUIO_SET_OID, Data) + sizeof(NDIS_802_11_MAC_ADDRESS); 649 SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize); 650 if (!SetOid) 651 return FALSE; 652 653 /* Set the BSSID */ 654 SetOid->Oid = OID_802_11_BSSID; 655 RtlFillMemory(SetOid->Data, sizeof(NDIS_802_11_MAC_ADDRESS), 0xFF); 656 657 bSuccess = DeviceIoControl(hAdapter, 658 IOCTL_NDISUIO_SET_OID_VALUE, 659 SetOid, 660 SetOidSize, 661 NULL, 662 0, 663 &dwBytesReturned, 664 NULL); 665 if (!bSuccess) 666 { 667 HeapFree(GetProcessHeap(), 0, SetOid); 668 return FALSE; 669 } 670 671 HeapFree(GetProcessHeap(), 0, SetOid); 672 SetOidSize = FIELD_OFFSET(NDISUIO_SET_OID, Data) + sizeof(NDIS_802_11_SSID); 673 SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize); 674 if (!SetOid) 675 return FALSE; 676 677 /* Finally, set the SSID */ 678 SetOid->Oid = OID_802_11_SSID; 679 Ssid = (PNDIS_802_11_SSID)SetOid->Data; 680 681 snprintf(SsidBuffer, sizeof(SsidBuffer), "%S", sSsid); 682 RtlCopyMemory(Ssid->Ssid, SsidBuffer, strlen(SsidBuffer)); 683 Ssid->SsidLength = strlen(SsidBuffer); 684 685 bSuccess = DeviceIoControl(hAdapter, 686 IOCTL_NDISUIO_SET_OID_VALUE, 687 SetOid, 688 SetOidSize, 689 NULL, 690 0, 691 &dwBytesReturned, 692 NULL); 693 694 HeapFree(GetProcessHeap(), 0, SetOid); 695 696 if (!bSuccess) 697 return FALSE; 698 699 ConResPuts(StdOut, IDS_SUCCESS); 700 return TRUE; 701 } 702 703 BOOL 704 WlanScan(HANDLE hAdapter) 705 { 706 BOOL bSuccess; 707 DWORD dwBytesReturned; 708 NDISUIO_SET_OID SetOid; 709 PNDISUIO_QUERY_OID QueryOid; 710 DWORD QueryOidSize; 711 PNDIS_802_11_BSSID_LIST BssidList; 712 DWORD i, j; 713 DWORD dwNetworkCount; 714 WCHAR szMsgBuf[128]; 715 716 SetOid.Oid = OID_802_11_BSSID_LIST_SCAN; 717 718 /* Send the scan OID */ 719 bSuccess = DeviceIoControl(hAdapter, 720 IOCTL_NDISUIO_SET_OID_VALUE, 721 &SetOid, 722 FIELD_OFFSET(NDISUIO_SET_OID, Data), 723 NULL, 724 0, 725 &dwBytesReturned, 726 NULL); 727 if (!bSuccess) 728 return FALSE; 729 730 /* Wait 2 seconds for the scan to return some results */ 731 Sleep(2000); 732 733 /* Allocate space for 10 networks to be returned initially */ 734 QueryOid = NULL; 735 dwNetworkCount = 10; 736 for (;;) 737 { 738 if (QueryOid) 739 HeapFree(GetProcessHeap(), 0, QueryOid); 740 741 QueryOidSize = sizeof(NDISUIO_QUERY_OID) + (sizeof(NDIS_WLAN_BSSID) * dwNetworkCount); 742 QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize); 743 if (!QueryOid) 744 return FALSE; 745 746 QueryOid->Oid = OID_802_11_BSSID_LIST; 747 BssidList = (PNDIS_802_11_BSSID_LIST)QueryOid->Data; 748 749 bSuccess = DeviceIoControl(hAdapter, 750 IOCTL_NDISUIO_QUERY_OID_VALUE, 751 QueryOid, 752 QueryOidSize, 753 QueryOid, 754 QueryOidSize, 755 &dwBytesReturned, 756 NULL); 757 if (!bSuccess && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 758 { 759 /* Try allocating space for 10 more networks */ 760 dwNetworkCount += 10; 761 } 762 else 763 { 764 break; 765 } 766 } 767 768 if (!bSuccess) 769 { 770 HeapFree(GetProcessHeap(), 0, QueryOid); 771 return FALSE; 772 } 773 774 if (BssidList->NumberOfItems == 0) 775 { 776 ConResPuts(StdOut, IDS_NO_NETWORK); 777 } 778 else 779 { 780 PNDIS_WLAN_BSSID BssidInfo = BssidList->Bssid; 781 for (i = 0; i < BssidList->NumberOfItems; i++) 782 { 783 PNDIS_802_11_SSID Ssid = &BssidInfo->Ssid; 784 NDIS_802_11_RSSI Rssi = BssidInfo->Rssi; 785 NDIS_802_11_NETWORK_INFRASTRUCTURE NetworkType = BssidInfo->InfrastructureMode; 786 CHAR SsidBuffer[NDIS_802_11_LENGTH_SSID + 1]; 787 UINT Rate; 788 789 /* SSID member is a non-null terminated ASCII string */ 790 RtlCopyMemory(SsidBuffer, Ssid->Ssid, Ssid->SsidLength); 791 SsidBuffer[Ssid->SsidLength] = 0; 792 793 printf("\nSSID: %s\n", SsidBuffer); 794 795 printf("BSSID: "); 796 for (j = 0; j < sizeof(NDIS_802_11_MAC_ADDRESS); j++) 797 { 798 UINT BssidData = BssidInfo->MacAddress[j]; 799 800 printf("%.2x", BssidData); 801 802 if (j != sizeof(NDIS_802_11_MAC_ADDRESS) - 1) 803 printf(":"); 804 } 805 printf("\n"); 806 807 K32LoadStringW(GetModuleHandle(NULL), 808 BssidInfo->Privacy == 0 ? IDS_NO : IDS_YES, 809 szMsgBuf, 810 ARRAYSIZE(szMsgBuf)); 811 ConResPrintf(StdOut, IDS_MSG_ENCRYPTED, szMsgBuf); 812 K32LoadStringW(GetModuleHandle(NULL), 813 NetworkType == Ndis802_11IBSS ? IDS_ADHOC : IDS_INFRASTRUCTURE, 814 szMsgBuf, 815 ARRAYSIZE(szMsgBuf)); 816 ConResPrintf(StdOut, IDS_MSG_NETWORK_TYPE, szMsgBuf); 817 ConResPrintf(StdOut, IDS_MSG_RSSI, (int)Rssi); 818 ConResPuts(StdOut, IDS_MSG_SUPPORT_RATE); 819 820 for (j = 0; j < NDIS_802_11_LENGTH_RATES; j++) 821 { 822 Rate = BssidInfo->SupportedRates[j]; 823 if (Rate != 0) 824 { 825 /* Bit 7 is the basic rates bit */ 826 Rate = Rate & 0x7F; 827 828 /* SupportedRates are in units of .5 */ 829 if (Rate & 0x01) 830 { 831 /* Bit 0 is set so we need to add 0.5 */ 832 printf("%u.5 ", (Rate >> 1)); 833 } 834 else 835 { 836 /* Bit 0 is clear so just print the conversion */ 837 printf("%u ", (Rate >> 1)); 838 } 839 } 840 } 841 printf("\n"); 842 843 /* Move to the next entry */ 844 BssidInfo = (PNDIS_WLAN_BSSID)((PUCHAR)BssidInfo + BssidInfo->Length); 845 } 846 } 847 848 HeapFree(GetProcessHeap(), 0, QueryOid); 849 850 return bSuccess; 851 } 852 853 BOOL ParseCmdline(int argc, WCHAR *argv[]) 854 { 855 INT i; 856 857 for (i = 1; i < argc; i++) 858 { 859 if (argv[i][0] == L'-') 860 { 861 switch (argv[i][1]) 862 { 863 case L's': 864 bScan = TRUE; 865 break; 866 case L'd': 867 bDisconnect = TRUE; 868 break; 869 case L'c': 870 if (i == argc - 1) 871 { 872 ConResPuts(StdOut, IDS_USAGE); 873 return FALSE; 874 } 875 bConnect = TRUE; 876 sSsid = argv[++i]; 877 break; 878 case L'w': 879 if (i == argc - 1) 880 { 881 ConResPuts(StdOut, IDS_USAGE); 882 return FALSE; 883 } 884 sWepKey = argv[++i]; 885 break; 886 case L'a': 887 bAdhoc = TRUE; 888 break; 889 default : 890 ConResPuts(StdOut, IDS_USAGE); 891 return FALSE; 892 } 893 894 } 895 else 896 { 897 ConResPuts(StdOut, IDS_USAGE); 898 return FALSE; 899 } 900 } 901 902 return TRUE; 903 } 904 905 int wmain(int argc, WCHAR *argv[]) 906 { 907 HANDLE hAdapter; 908 IP_ADAPTER_INDEX_MAP IpInfo; 909 910 /* Initialize the Console Standard Streams */ 911 ConInitStdStreams(); 912 913 if (!ParseCmdline(argc, argv)) 914 return -1; 915 916 if (!OpenWlanAdapter(&hAdapter, &IpInfo)) 917 { 918 ConResPuts(StdOut, IDS_NO_WLAN_ADAPTER); 919 return -1; 920 } 921 922 if (bScan) 923 { 924 if (!WlanScan(hAdapter)) 925 { 926 DoFormatMessage(GetLastError()); 927 CloseHandle(hAdapter); 928 return -1; 929 } 930 } 931 else if (bDisconnect) 932 { 933 if (!WlanDisconnect(hAdapter, &IpInfo)) 934 { 935 DoFormatMessage(GetLastError()); 936 CloseHandle(hAdapter); 937 return -1; 938 } 939 } 940 else if (bConnect) 941 { 942 if (!WlanConnect(hAdapter)) 943 { 944 DoFormatMessage(GetLastError()); 945 CloseHandle(hAdapter); 946 return -1; 947 } 948 } 949 else 950 { 951 if (!WlanPrintCurrentStatus(hAdapter)) 952 { 953 DoFormatMessage(GetLastError()); 954 CloseHandle(hAdapter); 955 return -1; 956 } 957 } 958 959 CloseHandle(hAdapter); 960 return 0; 961 } 962