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