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
DoFormatMessage(DWORD ErrorCode)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
OpenDriverHandle(VOID)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
IsWlanAdapter(HANDLE hAdapter)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
OpenAdapterHandle(DWORD Index,HANDLE * hAdapter,IP_ADAPTER_INDEX_MAP * IpInfo)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
OpenWlanAdapter(HANDLE * hAdapter,IP_ADAPTER_INDEX_MAP * IpInfo)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
WlanDisconnect(HANDLE hAdapter,PIP_ADAPTER_INDEX_MAP IpInfo)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
CharToHex(WCHAR Char)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
WlanPrintCurrentStatus(HANDLE hAdapter)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
WlanConnect(HANDLE hAdapter)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
WlanScan(HANDLE hAdapter)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
ParseCmdline(int argc,WCHAR * argv[])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
wmain(int argc,WCHAR * argv[])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