[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 = 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_EX 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_EX) * 15);
268 QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize);
269 if (!QueryOid)
270 return FALSE;
271
272 QueryOid->Oid = OID_802_11_BSSID_LIST;
273 BssidList = 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_EX BssidInfo = BssidList->Bssid[i];
298 PNDIS_802_11_SSID Ssid = &BssidInfo->Ssid;
299 UCHAR SupportedRates[16] = &BssidInfo->SupportedRates;
300 NDIS_802_11_RSSI Rssi = BssidInfo->Rssi;
301 NDIS_802_11_NETWORK_INFRASTRUCTURE NetworkType = BssidInfo->InfrastructureMode;
302 CHAR SsidBuffer[33];
303
304 /* SSID member is a non-null terminated ASCII string */
305 RtlCopyMemory(SsidBuffer, Ssid->Ssid, Ssid->SsidLength);
306 SsidBuffer[Ssid->SsidLength] = 0;
307
308 _tprintf(_T("\nSSID: %s\n"
309 "Encrypted: %s"
310 "Network Type: %s\n"
311 "RSSI: %i\n"
312 "Supported Rates: "),
313 SsidBuffer,
314 BssidInfo->Privacy == 0 ? "No" : "Yes",
315 NetworkType == Ndis802_11IBSS ? "Adhoc" : "Infrastructure",
316 (int)Rssi);
317
318 for (j = 0; j < 16; j++)
319 {
320 if (SupportedRates[j] != 0)
321 {
322 /* SupportedRates are in units of .5 */
323 _tprintf(_T("%d "), (SupportedRates[j] << 2));
324 }
325 }
326 _tprintf(_T("\n"));
327 }
328 }
329
330 HeapFree(GetProcessHeap(), 0, QueryOid);
331
332 return bSuccess;
333 }
334
335 VOID Usage()
336 {
337 _tprintf(_T("\nConfigures a WLAN adapter.\n\n"
338 "WLANCONF [-c SSID] [-d] [-s]\n\n"
339 " -c SSID Connects to a supplied SSID.\n"
340 " -d Disconnects from the current AP.\n"
341 " -s Scans and displays a list of access points in range.\n"));
342 }
343
344
345 BOOL ParseCmdline(int argc, char* argv[])
346 {
347 INT i;
348
349 for (i = 1; i < argc; i++)
350 {
351 if ((argc > 1) && (argv[i][0] == '-'))
352 {
353 TCHAR c;
354
355 while ((c = *++argv[i]) != '\0')
356 {
357 switch (c)
358 {
359 case 's' :
360 bScan = TRUE;
361 break;
362 case 'd' :
363 bDisconnect = TRUE;
364 break;
365 case 'c' :
366 bConnect = TRUE;
367 sSsid = argv[++i];
368 break;
369 default :
370 Usage();
371 return FALSE;
372 }
373 }
374 }
375 }
376
377 if (!bScan && !bDisconnect && !bConnect)
378 {
379 Usage();
380 return FALSE;
381 }
382
383 return TRUE;
384 }
385
386 int main(int argc, char* argv[])
387 {
388 HANDLE hAdapter;
389
390 if (!ParseCmdline(argc, argv))
391 return -1;
392
393 hAdapter = OpenWlanAdapter();
394 if (hAdapter == INVALID_HANDLE_VALUE)
395 {
396 DoFormatMessage(GetLastError());
397 return -1;
398 }
399
400 if (bScan)
401 {
402 if (!WlanScan(hAdapter))
403 {
404 DoFormatMessage(GetLastError());
405 CloseHandle(hAdapter);
406 return -1;
407 }
408 }
409 else if (bDisconnect)
410 {
411 if (!WlanDisconnect(hAdapter))
412 {
413 DoFormatMessage(GetLastError());
414 CloseHandle(hAdapter);
415 return -1;
416 }
417 }
418 else
419 {
420 if (!WlanConnect(hAdapter))
421 {
422 DoFormatMessage(GetLastError());
423 CloseHandle(hAdapter);
424 return -1;
425 }
426 }
427
428 CloseHandle(hAdapter);
429 return 0;
430 }