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