[WLANCONF]
[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 <windows.h>
10 #include <tchar.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <ntddndis.h>
14 #include <nuiouser.h>
15
16 BOOL bScan = FALSE;
17
18 BOOL bConnect = FALSE;
19 char* sSsid = NULL;
20
21 BOOL bDisconnect = FALSE;
22
23 DWORD DoFormatMessage(DWORD ErrorCode)
24 {
25 LPVOID lpMsgBuf;
26 DWORD RetVal;
27
28 if ((RetVal = FormatMessage(
29 FORMAT_MESSAGE_ALLOCATE_BUFFER |
30 FORMAT_MESSAGE_FROM_SYSTEM |
31 FORMAT_MESSAGE_IGNORE_INSERTS,
32 NULL,
33 ErrorCode,
34 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
35 (LPTSTR) &lpMsgBuf,
36 0,
37 NULL )))
38 {
39 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
40
41 LocalFree(lpMsgBuf);
42
43 /* return number of TCHAR's stored in output buffer
44 * excluding '\0' - as FormatMessage does*/
45 return RetVal;
46 }
47 else
48 return 0;
49 }
50
51 HANDLE
52 OpenDriverHandle(VOID)
53 {
54 HANDLE hDriver;
55 DWORD dwBytesReturned;
56 BOOL bSuccess;
57
58 /* Open a handle to this NDISUIO driver */
59 hDriver = CreateFileW(NDISUIO_DEVICE_NAME,
60 GENERIC_READ | GENERIC_WRITE,
61 0,
62 NULL,
63 OPEN_EXISTING,
64 FILE_ATTRIBUTE_NORMAL,
65 NULL);
66 if (hDriver == INVALID_HANDLE_VALUE)
67 return INVALID_HANDLE_VALUE;
68
69 /* Wait for binds */
70 bSuccess = DeviceIoControl(hDriver,
71 IOCTL_NDISUIO_BIND_WAIT,
72 NULL,
73 0,
74 NULL,
75 0,
76 &dwBytesReturned,
77 NULL);
78 if (!bSuccess)
79 {
80 CloseHandle(hDriver);
81 return INVALID_HANDLE_VALUE;
82 }
83
84 return hDriver;
85 }
86
87 BOOL
88 IsWlanAdapter(HANDLE hAdapter)
89 {
90 BOOL bSuccess;
91 DWORD dwBytesReturned;
92 NDISUIO_QUERY_OID QueryOid;
93
94 /* NDIS 5.1 WLAN drivers must support this OID */
95 QueryOid.Oid = OID_GEN_PHYSICAL_MEDIUM;
96
97 bSuccess = DeviceIoControl(hAdapter,
98 IOCTL_NDISUIO_QUERY_OID_VALUE,
99 &QueryOid,
100 sizeof(QueryOid),
101 &QueryOid,
102 sizeof(QueryOid),
103 &dwBytesReturned,
104 NULL);
105 if (!bSuccess || *(PULONG)QueryOid.Data != NdisPhysicalMediumWirelessLan)
106 return FALSE;
107
108 return TRUE;
109 }
110
111 HANDLE
112 OpenAdapterHandle(DWORD Index)
113 {
114 HANDLE hDriver;
115 BOOL bSuccess;
116 DWORD dwBytesReturned;
117 char Buffer[1024];
118 PNDISUIO_QUERY_BINDING QueryBinding = (PNDISUIO_QUERY_BINDING)Buffer;
119
120 /* Open the driver handle */
121 hDriver = OpenDriverHandle();
122 if (hDriver == INVALID_HANDLE_VALUE)
123 return INVALID_HANDLE_VALUE;
124
125 /* Query for bindable adapters */
126 QueryBinding->BindingIndex = 0;
127 do {
128 bSuccess = DeviceIoControl(hDriver,
129 IOCTL_NDISUIO_QUERY_BINDING,
130 NULL,
131 0,
132 NULL,
133 0,
134 &dwBytesReturned,
135 NULL);
136 if (QueryBinding->BindingIndex == Index)
137 break;
138 QueryBinding->BindingIndex++;
139 } while (bSuccess);
140
141 if (!bSuccess)
142 {
143 CloseHandle(hDriver);
144 return INVALID_HANDLE_VALUE;
145 }
146
147 /* Bind to the adapter */
148 bSuccess = DeviceIoControl(hDriver,
149 IOCTL_NDISUIO_OPEN_DEVICE,
150 (PUCHAR)QueryBinding + QueryBinding->DeviceNameOffset,
151 QueryBinding->DeviceNameLength,
152 NULL,
153 0,
154 &dwBytesReturned,
155 NULL);
156 if (!bSuccess)
157 {
158 CloseHandle(hDriver);
159 return INVALID_HANDLE_VALUE;
160 }
161
162 return hDriver;
163 }
164
165 /* Only works with the first adapter for now */
166 HANDLE
167 OpenWlanAdapter(VOID)
168 {
169 DWORD dwCurrentIndex;
170 HANDLE hCurrentAdapter;
171
172 for (dwCurrentIndex = 0; ; dwCurrentIndex++)
173 {
174 hCurrentAdapter = OpenAdapterHandle(dwCurrentIndex);
175 if (hCurrentAdapter == INVALID_HANDLE_VALUE)
176 break;
177
178 if (IsWlanAdapter(hCurrentAdapter))
179 return hCurrentAdapter;
180 else
181 CloseHandle(hCurrentAdapter);
182 }
183
184 return INVALID_HANDLE_VALUE;
185 }
186
187 BOOL
188 WlanDisconnect(HANDLE hAdapter)
189 {
190 BOOL bSuccess;
191 DWORD dwBytesReturned;
192 NDISUIO_SET_OID SetOid;
193
194 SetOid.Oid = OID_802_11_DISASSOCIATE;
195
196 bSuccess = DeviceIoControl(hAdapter,
197 IOCTL_NDISUIO_SET_OID_VALUE,
198 &SetOid,
199 sizeof(SetOid),
200 NULL,
201 0,
202 &dwBytesReturned,
203 NULL);
204
205 return bSuccess;
206 }
207
208 BOOL
209 WlanConnect(HANDLE hAdapter)
210 {
211 BOOL bSuccess;
212 DWORD dwBytesReturned;
213 PNDISUIO_SET_OID SetOid;
214 PNDIS_802_11_SSID Ssid;
215
216 SetOid = HeapAlloc(GetProcessHeap(), 0, sizeof(NDISUIO_SET_OID) + sizeof(NDIS_802_11_SSID));
217 if (!SetOid)
218 return FALSE;
219
220 SetOid->Oid = OID_802_11_SSID;
221 Ssid = (PNDIS_802_11_SSID)SetOid->Data;
222
223 /* Fill the OID data buffer */
224 RtlCopyMemory(Ssid->Ssid, sSsid, strlen(sSsid));
225 Ssid->SsidLength = strlen(sSsid);
226
227 bSuccess = DeviceIoControl(hAdapter,
228 IOCTL_NDISUIO_SET_OID_VALUE,
229 &SetOid,
230 sizeof(SetOid),
231 NULL,
232 0,
233 &dwBytesReturned,
234 NULL);
235
236 HeapFree(GetProcessHeap(), 0, SetOid);
237
238 return bSuccess;
239 }
240
241 BOOL
242 WlanScan(HANDLE hAdapter)
243 {
244 BOOL bSuccess;
245 DWORD dwBytesReturned;
246 NDISUIO_SET_OID SetOid;
247 PNDISUIO_QUERY_OID QueryOid;
248 DWORD QueryOidSize;
249 PNDIS_802_11_BSSID_LIST BssidList;
250 DWORD i, j;
251
252 SetOid.Oid = OID_802_11_BSSID_LIST_SCAN;
253
254 /* Send the scan OID */
255 bSuccess = DeviceIoControl(hAdapter,
256 IOCTL_NDISUIO_SET_OID_VALUE,
257 &SetOid,
258 sizeof(SetOid),
259 NULL,
260 0,
261 &dwBytesReturned,
262 NULL);
263 if (!bSuccess)
264 return FALSE;
265
266 /* Allocate space for 15 networks to be returned */
267 QueryOidSize = sizeof(NDISUIO_QUERY_OID) + (sizeof(NDIS_WLAN_BSSID) * 15);
268 QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize);
269 if (!QueryOid)
270 return FALSE;
271
272 QueryOid->Oid = OID_802_11_BSSID_LIST;
273 BssidList = (PNDIS_802_11_BSSID_LIST)QueryOid->Data;
274
275 bSuccess = DeviceIoControl(hAdapter,
276 IOCTL_NDISUIO_QUERY_OID_VALUE,
277 QueryOid,
278 QueryOidSize,
279 QueryOid,
280 QueryOidSize,
281 &dwBytesReturned,
282 NULL);
283 if (!bSuccess)
284 {
285 HeapFree(GetProcessHeap(), 0, QueryOid);
286 return FALSE;
287 }
288
289 if (BssidList->NumberOfItems == 0)
290 {
291 _tprintf(_T("No networks found in range\n"));
292 }
293 else
294 {
295 for (i = 0; i < BssidList->NumberOfItems; i++)
296 {
297 PNDIS_WLAN_BSSID BssidInfo = &BssidList->Bssid[i];
298 PNDIS_802_11_SSID Ssid = &BssidInfo->Ssid;
299 NDIS_802_11_RSSI Rssi = BssidInfo->Rssi;
300 NDIS_802_11_NETWORK_INFRASTRUCTURE NetworkType = BssidInfo->InfrastructureMode;
301 CHAR SsidBuffer[NDIS_802_11_LENGTH_SSID + 1];
302
303 /* SSID member is a non-null terminated ASCII string */
304 RtlCopyMemory(SsidBuffer, Ssid->Ssid, Ssid->SsidLength);
305 SsidBuffer[Ssid->SsidLength] = 0;
306
307 _tprintf(_T("\nSSID: %s\n"
308 "Encrypted: %s"
309 "Network Type: %s\n"
310 "RSSI: %i\n"
311 "Supported Rates: "),
312 SsidBuffer,
313 BssidInfo->Privacy == 0 ? "No" : "Yes",
314 NetworkType == Ndis802_11IBSS ? "Adhoc" : "Infrastructure",
315 (int)Rssi);
316
317 for (j = 0; j < NDIS_802_11_LENGTH_RATES; j++)
318 {
319 if (BssidInfo->SupportedRates[j] != 0)
320 {
321 /* SupportedRates are in units of .5 */
322 _tprintf(_T("%d "), (BssidInfo->SupportedRates[j] << 2));
323 }
324 }
325 _tprintf(_T("\n"));
326 }
327 }
328
329 HeapFree(GetProcessHeap(), 0, QueryOid);
330
331 return bSuccess;
332 }
333
334 VOID Usage()
335 {
336 _tprintf(_T("\nConfigures a WLAN adapter.\n\n"
337 "WLANCONF [-c SSID] [-d] [-s]\n\n"
338 " -c SSID Connects to a supplied SSID.\n"
339 " -d Disconnects from the current AP.\n"
340 " -s Scans and displays a list of access points in range.\n"));
341 }
342
343
344 BOOL ParseCmdline(int argc, char* argv[])
345 {
346 INT i;
347
348 for (i = 1; i < argc; i++)
349 {
350 if ((argc > 1) && (argv[i][0] == '-'))
351 {
352 TCHAR c;
353
354 while ((c = *++argv[i]) != '\0')
355 {
356 switch (c)
357 {
358 case 's' :
359 bScan = TRUE;
360 break;
361 case 'd' :
362 bDisconnect = TRUE;
363 break;
364 case 'c' :
365 bConnect = TRUE;
366 sSsid = argv[++i];
367 break;
368 default :
369 Usage();
370 return FALSE;
371 }
372 }
373 }
374 }
375
376 if (!bScan && !bDisconnect && !bConnect)
377 {
378 Usage();
379 return FALSE;
380 }
381
382 return TRUE;
383 }
384
385 int main(int argc, char* argv[])
386 {
387 HANDLE hAdapter;
388
389 if (!ParseCmdline(argc, argv))
390 return -1;
391
392 hAdapter = OpenWlanAdapter();
393 if (hAdapter == INVALID_HANDLE_VALUE)
394 {
395 DoFormatMessage(GetLastError());
396 return -1;
397 }
398
399 if (bScan)
400 {
401 if (!WlanScan(hAdapter))
402 {
403 DoFormatMessage(GetLastError());
404 CloseHandle(hAdapter);
405 return -1;
406 }
407 }
408 else if (bDisconnect)
409 {
410 if (!WlanDisconnect(hAdapter))
411 {
412 DoFormatMessage(GetLastError());
413 CloseHandle(hAdapter);
414 return -1;
415 }
416 }
417 else
418 {
419 if (!WlanConnect(hAdapter))
420 {
421 DoFormatMessage(GetLastError());
422 CloseHandle(hAdapter);
423 return -1;
424 }
425 }
426
427 CloseHandle(hAdapter);
428 return 0;
429 }