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)
26 BOOL bConnect
= FALSE
;
28 WCHAR
*sWepKey
= NULL
;
31 BOOL bDisconnect
= FALSE
;
33 VOID
DoFormatMessage(DWORD ErrorCode
)
35 if (ErrorCode
== ERROR_SUCCESS
)
38 ConMsgPuts(StdErr
, FORMAT_MESSAGE_FROM_SYSTEM
,
39 NULL
, ErrorCode
, LANG_USER_DEFAULT
);
43 OpenDriverHandle(VOID
)
46 DWORD dwBytesReturned
;
49 /* Open a handle to the NDISUIO driver */
50 hDriver
= CreateFileW(NDISUIO_DEVICE_NAME
,
51 GENERIC_READ
| GENERIC_WRITE
,
55 FILE_ATTRIBUTE_NORMAL
,
57 if (hDriver
== INVALID_HANDLE_VALUE
)
58 return INVALID_HANDLE_VALUE
;
61 bSuccess
= DeviceIoControl(hDriver
,
62 IOCTL_NDISUIO_BIND_WAIT
,
72 return INVALID_HANDLE_VALUE
;
79 IsWlanAdapter(HANDLE hAdapter
)
82 DWORD dwBytesReturned
;
83 NDISUIO_QUERY_OID QueryOid
;
85 /* WLAN drivers must support this OID */
86 QueryOid
.Oid
= OID_GEN_PHYSICAL_MEDIUM
;
88 bSuccess
= DeviceIoControl(hAdapter
,
89 IOCTL_NDISUIO_QUERY_OID_VALUE
,
96 if (!bSuccess
|| *(PULONG
)QueryOid
.Data
!= NdisPhysicalMediumWirelessLan
)
103 OpenAdapterHandle(DWORD Index
, HANDLE
*hAdapter
, IP_ADAPTER_INDEX_MAP
*IpInfo
)
107 DWORD dwBytesReturned
;
108 DWORD QueryBindingSize
= sizeof(NDISUIO_QUERY_BINDING
) + (1024 * sizeof(WCHAR
));
109 PNDISUIO_QUERY_BINDING QueryBinding
;
110 DWORD dwStatus
, dwSize
;
112 PIP_INTERFACE_INFO InterfaceInfo
= NULL
;
114 /* Open the driver handle */
115 hDriver
= OpenDriverHandle();
116 if (hDriver
== INVALID_HANDLE_VALUE
)
119 /* Allocate the binding struct */
120 QueryBinding
= HeapAlloc(GetProcessHeap(), 0, QueryBindingSize
);
123 CloseHandle(hDriver
);
127 /* Query the adapter binding information */
128 QueryBinding
->BindingIndex
= Index
;
129 bSuccess
= DeviceIoControl(hDriver
,
130 IOCTL_NDISUIO_QUERY_BINDING
,
140 HeapFree(GetProcessHeap(), 0, QueryBinding
);
141 CloseHandle(hDriver
);
145 /* Bind to the adapter */
146 bSuccess
= DeviceIoControl(hDriver
,
147 IOCTL_NDISUIO_OPEN_DEVICE
,
148 (PUCHAR
)QueryBinding
+ QueryBinding
->DeviceNameOffset
,
149 QueryBinding
->DeviceNameLength
,
157 HeapFree(GetProcessHeap(), 0, QueryBinding
);
158 CloseHandle(hDriver
);
162 /* Get interface info from the IP helper */
163 dwSize
= sizeof(IP_INTERFACE_INFO
);
165 if (InterfaceInfo
) HeapFree(GetProcessHeap(), 0, InterfaceInfo
);
166 InterfaceInfo
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
169 HeapFree(GetProcessHeap(), 0, QueryBinding
);
170 CloseHandle(hDriver
);
173 dwStatus
= GetInterfaceInfo(InterfaceInfo
, &dwSize
);
174 } while (dwStatus
== ERROR_INSUFFICIENT_BUFFER
);
176 if (dwStatus
!= NO_ERROR
)
178 HeapFree(GetProcessHeap(), 0, QueryBinding
);
179 HeapFree(GetProcessHeap(), 0, InterfaceInfo
);
180 CloseHandle(hDriver
);
184 for (i
= 0; i
< InterfaceInfo
->NumAdapters
; i
++)
186 if (wcsstr((PWCHAR
)((PUCHAR
)QueryBinding
+ QueryBinding
->DeviceNameOffset
),
187 InterfaceInfo
->Adapter
[i
].Name
))
189 *IpInfo
= InterfaceInfo
->Adapter
[i
];
192 HeapFree(GetProcessHeap(), 0, QueryBinding
);
193 HeapFree(GetProcessHeap(), 0, InterfaceInfo
);
199 HeapFree(GetProcessHeap(), 0, QueryBinding
);
200 HeapFree(GetProcessHeap(), 0, InterfaceInfo
);
201 CloseHandle(hDriver
);
206 /* Only works with the first adapter for now */
208 OpenWlanAdapter(HANDLE
*hAdapter
, IP_ADAPTER_INDEX_MAP
*IpInfo
)
210 DWORD dwCurrentIndex
;
212 for (dwCurrentIndex
= 0; ; dwCurrentIndex
++)
214 if (!OpenAdapterHandle(dwCurrentIndex
, hAdapter
, IpInfo
))
217 if (IsWlanAdapter(*hAdapter
))
220 CloseHandle(*hAdapter
);
227 WlanDisconnect(HANDLE hAdapter
, PIP_ADAPTER_INDEX_MAP IpInfo
)
230 DWORD dwBytesReturned
;
231 NDISUIO_SET_OID SetOid
;
233 /* Release this IP address */
234 IpReleaseAddress(IpInfo
);
236 /* Disassociate from the AP */
237 SetOid
.Oid
= OID_802_11_DISASSOCIATE
;
238 bSuccess
= DeviceIoControl(hAdapter
,
239 IOCTL_NDISUIO_SET_OID_VALUE
,
241 FIELD_OFFSET(NDISUIO_SET_OID
, Data
),
249 ConResPuts(StdOut
, IDS_SUCCESS
);
255 CharToHex(WCHAR Char
)
257 if ((Char
>= L
'0') && (Char
<= L
'9'))
260 if ((Char
>= L
'a') && (Char
<= L
'f'))
261 return Char
- L
'a' + 10;
263 if ((Char
>= L
'A') && (Char
<= L
'F'))
264 return Char
- L
'A' + 10;
270 WlanPrintCurrentStatus(HANDLE hAdapter
)
272 PNDISUIO_QUERY_OID QueryOid
;
275 DWORD dwBytesReturned
;
276 PNDIS_802_11_SSID SsidInfo
;
277 CHAR SsidBuffer
[NDIS_802_11_LENGTH_SSID
+ 1];
281 QueryOidSize
= FIELD_OFFSET(NDISUIO_QUERY_OID
, Data
) + sizeof(NDIS_802_11_SSID
);
282 QueryOid
= HeapAlloc(GetProcessHeap(), 0, QueryOidSize
);
286 QueryOid
->Oid
= OID_802_11_SSID
;
287 SsidInfo
= (PNDIS_802_11_SSID
)QueryOid
->Data
;
289 bSuccess
= DeviceIoControl(hAdapter
,
290 IOCTL_NDISUIO_QUERY_OID_VALUE
,
299 HeapFree(GetProcessHeap(), 0, QueryOid
);
303 /* Copy the SSID to our internal buffer and terminate it */
304 RtlCopyMemory(SsidBuffer
, SsidInfo
->Ssid
, SsidInfo
->SsidLength
);
305 SsidBuffer
[SsidInfo
->SsidLength
] = 0;
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
);
313 QueryOid
->Oid
= OID_802_11_BSSID
;
315 bSuccess
= DeviceIoControl(hAdapter
,
316 IOCTL_NDISUIO_QUERY_OID_VALUE
,
323 if (SsidInfo
->SsidLength
== 0 || !bSuccess
)
325 ConResPuts(StdOut
, IDS_WLAN_DISCONNECT
);
326 HeapFree(GetProcessHeap(), 0, QueryOid
);
331 ConResPuts(StdOut
, IDS_MSG_CURRENT_WIRELESS
);
334 printf("SSID: %s\n", SsidBuffer
);
337 for (i
= 0; i
< sizeof(NDIS_802_11_MAC_ADDRESS
); i
++)
339 UINT BssidData
= QueryOid
->Data
[i
];
341 printf("%.2x", BssidData
);
343 if (i
!= sizeof(NDIS_802_11_MAC_ADDRESS
) - 1)
348 HeapFree(GetProcessHeap(), 0, QueryOid
);
349 QueryOidSize
= sizeof(NDISUIO_QUERY_OID
);
350 QueryOid
= HeapAlloc(GetProcessHeap(), 0, QueryOidSize
);
354 QueryOid
->Oid
= OID_802_11_INFRASTRUCTURE_MODE
;
356 bSuccess
= DeviceIoControl(hAdapter
,
357 IOCTL_NDISUIO_QUERY_OID_VALUE
,
366 HeapFree(GetProcessHeap(), 0, QueryOid
);
370 K32LoadStringW(GetModuleHandle(NULL
),
371 *(PUINT
)QueryOid
->Data
== Ndis802_11IBSS
? IDS_ADHOC
: IDS_INFRASTRUCTURE
,
373 ARRAYSIZE(szMsgBuf
));
374 ConResPrintf(StdOut
, IDS_MSG_NETWORK_MODE
, szMsgBuf
);
376 QueryOid
->Oid
= OID_802_11_WEP_STATUS
;
378 bSuccess
= DeviceIoControl(hAdapter
,
379 IOCTL_NDISUIO_QUERY_OID_VALUE
,
388 HeapFree(GetProcessHeap(), 0, QueryOid
);
392 K32LoadStringW(GetModuleHandle(NULL
),
393 *(PUINT
)QueryOid
->Data
== Ndis802_11WEPEnabled
? IDS_YES
: IDS_NO
,
395 ARRAYSIZE(szMsgBuf
));
396 ConResPrintf(StdOut
, IDS_MSG_WEP_ENABLED
, szMsgBuf
);
399 QueryOid
->Oid
= OID_802_11_RSSI
;
401 bSuccess
= DeviceIoControl(hAdapter
,
402 IOCTL_NDISUIO_QUERY_OID_VALUE
,
411 /* This OID is optional */
412 printf("RSSI: %i dBm\n", *(PINT
)QueryOid
->Data
);
415 QueryOid
->Oid
= OID_802_11_TX_POWER_LEVEL
;
417 bSuccess
= DeviceIoControl(hAdapter
,
418 IOCTL_NDISUIO_QUERY_OID_VALUE
,
427 /* This OID is optional */
428 ConResPrintf(StdOut
, IDS_MSG_TRANSMISSION_POWER
, *(PUINT
)QueryOid
->Data
);
433 QueryOid
->Oid
= OID_802_11_NUMBER_OF_ANTENNAS
;
435 bSuccess
= DeviceIoControl(hAdapter
,
436 IOCTL_NDISUIO_QUERY_OID_VALUE
,
445 /* This OID is optional */
446 ConResPrintf(StdOut
, IDS_MSG_ANTENNA_COUNT
, *(PUINT
)QueryOid
->Data
);
449 QueryOid
->Oid
= OID_802_11_TX_ANTENNA_SELECTED
;
451 bSuccess
= DeviceIoControl(hAdapter
,
452 IOCTL_NDISUIO_QUERY_OID_VALUE
,
461 UINT TransmitAntenna
= *(PUINT
)QueryOid
->Data
;
463 if (TransmitAntenna
!= 0xFFFFFFFF)
464 ConResPrintf(StdOut
, IDS_MSG_TRANSMIT_ANTENNA
, TransmitAntenna
);
466 ConResPuts(StdOut
, IDS_MSG_TRANSMIT_ANTENNA_ANY
);
469 QueryOid
->Oid
= OID_802_11_RX_ANTENNA_SELECTED
;
471 bSuccess
= DeviceIoControl(hAdapter
,
472 IOCTL_NDISUIO_QUERY_OID_VALUE
,
481 UINT ReceiveAntenna
= *(PUINT
)QueryOid
->Data
;
483 if (ReceiveAntenna
!= 0xFFFFFFFF)
484 ConResPrintf(StdOut
, IDS_MSG_RECEIVE_ANTENNA
, ReceiveAntenna
);
486 ConResPuts(StdOut
, IDS_MSG_RECEIVE_ANTENNA_ANY
);
491 QueryOid
->Oid
= OID_802_11_FRAGMENTATION_THRESHOLD
;
493 bSuccess
= DeviceIoControl(hAdapter
,
494 IOCTL_NDISUIO_QUERY_OID_VALUE
,
503 /* This OID is optional */
504 ConResPrintf(StdOut
, IDS_MSG_FRAGMENT_THRESHOLD
, *(PUINT
)QueryOid
->Data
);
507 QueryOid
->Oid
= OID_802_11_RTS_THRESHOLD
;
509 bSuccess
= DeviceIoControl(hAdapter
,
510 IOCTL_NDISUIO_QUERY_OID_VALUE
,
519 /* This OID is optional */
520 ConResPrintf(StdOut
, IDS_MSG_RTS_THRESHOLD
, *(PUINT
)QueryOid
->Data
);
523 HeapFree(GetProcessHeap(), 0, QueryOid
);
530 WlanConnect(HANDLE hAdapter
)
532 CHAR SsidBuffer
[NDIS_802_11_LENGTH_SSID
+ 1];
534 DWORD dwBytesReturned
, SetOidSize
;
535 PNDISUIO_SET_OID SetOid
;
536 PNDIS_802_11_SSID Ssid
;
539 SetOidSize
= sizeof(NDISUIO_SET_OID
);
540 SetOid
= HeapAlloc(GetProcessHeap(), 0, SetOidSize
);
544 /* Set the network mode */
545 SetOid
->Oid
= OID_802_11_INFRASTRUCTURE_MODE
;
546 *(PULONG
)SetOid
->Data
= bAdhoc
? Ndis802_11IBSS
: Ndis802_11Infrastructure
;
548 bSuccess
= DeviceIoControl(hAdapter
,
549 IOCTL_NDISUIO_SET_OID_VALUE
,
558 HeapFree(GetProcessHeap(), 0, SetOid
);
562 /* Set the authentication mode */
563 SetOid
->Oid
= OID_802_11_AUTHENTICATION_MODE
;
564 *(PULONG
)SetOid
->Data
= sWepKey
? Ndis802_11AuthModeShared
: Ndis802_11AuthModeOpen
;
566 bSuccess
= DeviceIoControl(hAdapter
,
567 IOCTL_NDISUIO_SET_OID_VALUE
,
576 HeapFree(GetProcessHeap(), 0, SetOid
);
582 PNDIS_802_11_WEP WepData
;
584 HeapFree(GetProcessHeap(), 0, SetOid
);
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
);
593 /* Add the WEP key */
594 SetOid
->Oid
= OID_802_11_ADD_WEP
;
595 WepData
= (PNDIS_802_11_WEP
)SetOid
->Data
;
597 WepData
->KeyIndex
= 0x80000000;
598 WepData
->KeyLength
= wcslen(sWepKey
) >> 1;
599 WepData
->Length
= FIELD_OFFSET(NDIS_802_11_WEP
, KeyMaterial
) + WepData
->KeyLength
;
601 /* Assemble the hex key */
603 while (sWepKey
[i
<< 1] != '\0')
605 WepData
->KeyMaterial
[i
] = CharToHex(sWepKey
[i
<< 1]) << 4;
606 WepData
->KeyMaterial
[i
] |= CharToHex(sWepKey
[(i
<< 1) + 1]);
610 bSuccess
= DeviceIoControl(hAdapter
,
611 IOCTL_NDISUIO_SET_OID_VALUE
,
620 HeapFree(GetProcessHeap(), 0, SetOid
);
625 /* Set the encryption status */
626 SetOid
->Oid
= OID_802_11_WEP_STATUS
;
627 *(PULONG
)SetOid
->Data
= sWepKey
? Ndis802_11WEPEnabled
: Ndis802_11WEPDisabled
;
629 bSuccess
= DeviceIoControl(hAdapter
,
630 IOCTL_NDISUIO_SET_OID_VALUE
,
639 HeapFree(GetProcessHeap(), 0, SetOid
);
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
);
650 SetOid
->Oid
= OID_802_11_BSSID
;
651 RtlFillMemory(SetOid
->Data
, sizeof(NDIS_802_11_MAC_ADDRESS
), 0xFF);
653 bSuccess
= DeviceIoControl(hAdapter
,
654 IOCTL_NDISUIO_SET_OID_VALUE
,
663 HeapFree(GetProcessHeap(), 0, SetOid
);
667 HeapFree(GetProcessHeap(), 0, SetOid
);
668 SetOidSize
= FIELD_OFFSET(NDISUIO_SET_OID
, Data
) + sizeof(NDIS_802_11_SSID
);
669 SetOid
= HeapAlloc(GetProcessHeap(), 0, SetOidSize
);
673 /* Finally, set the SSID */
674 SetOid
->Oid
= OID_802_11_SSID
;
675 Ssid
= (PNDIS_802_11_SSID
)SetOid
->Data
;
677 snprintf(SsidBuffer
, sizeof(SsidBuffer
), "%S", sSsid
);
678 RtlCopyMemory(Ssid
->Ssid
, SsidBuffer
, strlen(SsidBuffer
));
679 Ssid
->SsidLength
= strlen(SsidBuffer
);
681 bSuccess
= DeviceIoControl(hAdapter
,
682 IOCTL_NDISUIO_SET_OID_VALUE
,
690 HeapFree(GetProcessHeap(), 0, SetOid
);
695 ConResPuts(StdOut
, IDS_SUCCESS
);
700 WlanScan(HANDLE hAdapter
)
703 DWORD dwBytesReturned
;
704 NDISUIO_SET_OID SetOid
;
705 PNDISUIO_QUERY_OID QueryOid
;
707 PNDIS_802_11_BSSID_LIST BssidList
;
709 DWORD dwNetworkCount
;
712 SetOid
.Oid
= OID_802_11_BSSID_LIST_SCAN
;
714 /* Send the scan OID */
715 bSuccess
= DeviceIoControl(hAdapter
,
716 IOCTL_NDISUIO_SET_OID_VALUE
,
718 FIELD_OFFSET(NDISUIO_SET_OID
, Data
),
726 /* Wait 2 seconds for the scan to return some results */
729 /* Allocate space for 10 networks to be returned initially */
735 HeapFree(GetProcessHeap(), 0, QueryOid
);
737 QueryOidSize
= sizeof(NDISUIO_QUERY_OID
) + (sizeof(NDIS_WLAN_BSSID
) * dwNetworkCount
);
738 QueryOid
= HeapAlloc(GetProcessHeap(), 0, QueryOidSize
);
742 QueryOid
->Oid
= OID_802_11_BSSID_LIST
;
743 BssidList
= (PNDIS_802_11_BSSID_LIST
)QueryOid
->Data
;
745 bSuccess
= DeviceIoControl(hAdapter
,
746 IOCTL_NDISUIO_QUERY_OID_VALUE
,
753 if (!bSuccess
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
755 /* Try allocating space for 10 more networks */
756 dwNetworkCount
+= 10;
766 HeapFree(GetProcessHeap(), 0, QueryOid
);
770 if (BssidList
->NumberOfItems
== 0)
772 ConResPuts(StdOut
, IDS_NO_NETWORK
);
776 PNDIS_WLAN_BSSID BssidInfo
= BssidList
->Bssid
;
777 for (i
= 0; i
< BssidList
->NumberOfItems
; i
++)
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];
785 /* SSID member is a non-null terminated ASCII string */
786 RtlCopyMemory(SsidBuffer
, Ssid
->Ssid
, Ssid
->SsidLength
);
787 SsidBuffer
[Ssid
->SsidLength
] = 0;
789 printf("\nSSID: %s\n", SsidBuffer
);
792 for (j
= 0; j
< sizeof(NDIS_802_11_MAC_ADDRESS
); j
++)
794 UINT BssidData
= BssidInfo
->MacAddress
[j
];
796 printf("%.2x", BssidData
);
798 if (j
!= sizeof(NDIS_802_11_MAC_ADDRESS
) - 1)
803 K32LoadStringW(GetModuleHandle(NULL
),
804 BssidInfo
->Privacy
== 0 ? IDS_NO
: IDS_YES
,
806 ARRAYSIZE(szMsgBuf
));
807 ConResPrintf(StdOut
, IDS_MSG_ENCRYPTED
, szMsgBuf
);
808 K32LoadStringW(GetModuleHandle(NULL
),
809 NetworkType
== Ndis802_11IBSS
? IDS_ADHOC
: IDS_INFRASTRUCTURE
,
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
);
816 for (j
= 0; j
< NDIS_802_11_LENGTH_RATES
; j
++)
818 Rate
= BssidInfo
->SupportedRates
[j
];
821 /* Bit 7 is the basic rates bit */
824 /* SupportedRates are in units of .5 */
827 /* Bit 0 is set so we need to add 0.5 */
828 printf("%u.5 ", (Rate
>> 1));
832 /* Bit 0 is clear so just print the conversion */
833 printf("%u ", (Rate
>> 1));
839 /* Move to the next entry */
840 BssidInfo
= (PNDIS_WLAN_BSSID
)((PUCHAR
)BssidInfo
+ BssidInfo
->Length
);
844 HeapFree(GetProcessHeap(), 0, QueryOid
);
849 BOOL
ParseCmdline(int argc
, WCHAR
*argv
[])
853 for (i
= 1; i
< argc
; i
++)
855 if (argv
[i
][0] == L
'-')
868 ConResPuts(StdOut
, IDS_USAGE
);
877 ConResPuts(StdOut
, IDS_USAGE
);
886 ConResPuts(StdOut
, IDS_USAGE
);
893 ConResPuts(StdOut
, IDS_USAGE
);
901 int wmain(int argc
, WCHAR
*argv
[])
904 IP_ADAPTER_INDEX_MAP IpInfo
;
906 /* Initialize the Console Standard Streams */
909 if (!ParseCmdline(argc
, argv
))
912 if (!OpenWlanAdapter(&hAdapter
, &IpInfo
))
914 ConResPuts(StdOut
, IDS_NO_WLAN_ADAPTER
);
920 if (!WlanScan(hAdapter
))
922 DoFormatMessage(GetLastError());
923 CloseHandle(hAdapter
);
927 else if (bDisconnect
)
929 if (!WlanDisconnect(hAdapter
, &IpInfo
))
931 DoFormatMessage(GetLastError());
932 CloseHandle(hAdapter
);
938 if (!WlanConnect(hAdapter
))
940 DoFormatMessage(GetLastError());
941 CloseHandle(hAdapter
);
947 if (!WlanPrintCurrentStatus(hAdapter
))
949 DoFormatMessage(GetLastError());
950 CloseHandle(hAdapter
);
955 CloseHandle(hAdapter
);