342 lines
8.4 KiB
C++
342 lines
8.4 KiB
C++
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
|
|
#include "stdafx.h"
|
|
|
|
#define HALF_BYTE_TO_HEX_WCHAR(b) (((b) < 10) ? (L'0' + (b)) : (L'A' + (b) - 10))
|
|
|
|
DWORD
|
|
StringToSsid(
|
|
__in LPCWSTR strSsid,
|
|
__out PDOT11_SSID pDot11Ssid
|
|
)
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
BYTE pbSsid[DOT11_SSID_MAX_LENGTH + 1];
|
|
DWORD dwBytes;
|
|
|
|
if (strSsid == NULL || pDot11Ssid == NULL || wcslen(strSsid) == 0)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
dwBytes = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
|
|
strSsid, -1, (LPSTR)pbSsid, sizeof(pbSsid), NULL, NULL);
|
|
|
|
if (dwBytes == 0)
|
|
{
|
|
// Conversion failed.
|
|
dwError = GetLastError();
|
|
|
|
if (dwError == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
dwError = ERROR_BAD_LENGTH;
|
|
}
|
|
|
|
goto error;
|
|
}
|
|
else if (dwBytes == 1)
|
|
{
|
|
// Zero-length SSID.
|
|
dwError = ERROR_BAD_LENGTH;
|
|
goto error;
|
|
}
|
|
else
|
|
{
|
|
// Conversion succeeded and length valid.
|
|
pDot11Ssid->uSSIDLength = dwBytes - 1;
|
|
memcpy(pDot11Ssid->ucSSID, pbSsid, pDot11Ssid->uSSIDLength);
|
|
}
|
|
|
|
error:
|
|
|
|
return dwError;
|
|
}
|
|
|
|
__success(ERROR_SUCCESS)
|
|
DWORD
|
|
SsidToDisplayName(
|
|
__in PDOT11_SSID pDot11Ssid,
|
|
__in BOOL bHexFallback,
|
|
__out_ecount_opt(*pcchDisplayName) LPWSTR strDisplayName,
|
|
__inout DWORD *pcchDisplayName
|
|
)
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
DWORD cchDisplayName, i, j;
|
|
BYTE hb;
|
|
WCHAR strHexResource[256];
|
|
DWORD cchHexResource = sizeof(strHexResource);
|
|
WCHAR strSSID[WLAN_MAX_NAME_LENGTH];
|
|
LPWSTR pszArgs[1] = {NULL};
|
|
|
|
if (pDot11Ssid == NULL ||
|
|
pcchDisplayName == NULL ||
|
|
(strDisplayName == NULL && *pcchDisplayName != 0) ||
|
|
pDot11Ssid->uSSIDLength > DOT11_SSID_MAX_LENGTH)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
LoadString (
|
|
GetModuleHandle(NULL),
|
|
IDS_ERROR_CANNOT_DISPLAY_SSID,
|
|
strHexResource,
|
|
256
|
|
);
|
|
strDisplayName[0] = L'\0';
|
|
if (pDot11Ssid->uSSIDLength == 0)
|
|
{
|
|
cchDisplayName = 0;
|
|
}
|
|
else
|
|
{
|
|
// Convert to get length, not including null.
|
|
cchDisplayName = MultiByteToWideChar(CP_ACP, 0,
|
|
(LPCSTR)pDot11Ssid->ucSSID, pDot11Ssid->uSSIDLength,
|
|
NULL, 0);
|
|
}
|
|
|
|
if (pDot11Ssid->uSSIDLength ==0 || cchDisplayName > 0)
|
|
{
|
|
// Length including null.
|
|
cchDisplayName ++;
|
|
|
|
// Conversion succeeded.
|
|
if (*pcchDisplayName < cchDisplayName)
|
|
{
|
|
// Insufficient buffer.
|
|
*pcchDisplayName = cchDisplayName;
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
// Sufficient buffer.
|
|
if (pDot11Ssid->uSSIDLength > 0)
|
|
{
|
|
cchDisplayName = MultiByteToWideChar(CP_ACP, 0,
|
|
(LPCSTR)pDot11Ssid->ucSSID, pDot11Ssid->uSSIDLength,
|
|
strDisplayName, *pcchDisplayName);
|
|
|
|
if (cchDisplayName == 0)
|
|
{
|
|
dwError = GetLastError();
|
|
goto error;
|
|
}
|
|
|
|
cchDisplayName++;
|
|
}
|
|
|
|
// Succeeded.
|
|
if (cchDisplayName < *pcchDisplayName)
|
|
{
|
|
strDisplayName[cchDisplayName - 1] = L'\0';
|
|
*pcchDisplayName = cchDisplayName;
|
|
}
|
|
else
|
|
{
|
|
// This should not happen, added to avoid prefast warning
|
|
_ASSERT(FALSE);
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
else if (bHexFallback)
|
|
{
|
|
// ACP Conversion failed. Try Hex conversion.
|
|
|
|
// Display name length including null.
|
|
cchDisplayName = cchHexResource + 2 * pDot11Ssid->uSSIDLength + 1;
|
|
|
|
if (*pcchDisplayName < cchDisplayName)
|
|
{
|
|
// Insufficient buffer.
|
|
*pcchDisplayName = cchDisplayName;
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
// Sufficient buffer.
|
|
for (i = 0, j = 0; i < pDot11Ssid->uSSIDLength; i++)
|
|
{
|
|
hb = pDot11Ssid->ucSSID[i] >> 4;
|
|
strSSID[j++] = HALF_BYTE_TO_HEX_WCHAR(hb);
|
|
hb = pDot11Ssid->ucSSID[i] & 0x0F;
|
|
strSSID[j++] = HALF_BYTE_TO_HEX_WCHAR(hb);
|
|
}
|
|
strSSID[j] = L'\0';
|
|
|
|
pszArgs[0] = strSSID;
|
|
cchDisplayName = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_STRING
|
|
| FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
strHexResource,
|
|
0,
|
|
0,
|
|
strDisplayName,
|
|
*pcchDisplayName,
|
|
(va_list *)pszArgs
|
|
);
|
|
if (cchDisplayName == 0)
|
|
{
|
|
dwError = GetLastError();
|
|
goto error;
|
|
}
|
|
*pcchDisplayName = cchDisplayName;
|
|
}
|
|
}
|
|
|
|
error:
|
|
return dwError;
|
|
}
|
|
|
|
DWORD
|
|
ConvertPassPhraseKeyStringToBuffer(
|
|
__in_ecount(dwLength) LPCWSTR strPassKeyString, // Unicode string
|
|
__in DWORD dwLength,
|
|
__in DOT11_AUTH_ALGORITHM dot11Auth,
|
|
__out_ecount_opt(*pdwBufLen) UCHAR* strPassKeyBuf, // NULL to get length required
|
|
__inout DWORD *pdwBufLen // in: length of buffer; out: chars copied/required
|
|
)
|
|
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
DWORD dwActualLen = dwLength;
|
|
UCHAR *lpstrKeyMaterial = NULL;
|
|
DWORD dwAllocLen = 0;
|
|
DWORD dwKeyBytes = 0;
|
|
BOOL bUnmappableChar = FALSE;
|
|
DWORD dwReqdBytes = 0;
|
|
BOOL bPassPhrase = FALSE;
|
|
|
|
if (!strPassKeyString)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL();
|
|
}
|
|
|
|
while ((dwActualLen != 0) && !strPassKeyString[dwActualLen-1])
|
|
{
|
|
dwActualLen--;
|
|
}
|
|
|
|
if (dwActualLen == 0)
|
|
{
|
|
dwError = ERROR_BAD_FORMAT;
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
dwAllocLen = WideCharToMultiByte(
|
|
CP_ACP,
|
|
WC_NO_BEST_FIT_CHARS,
|
|
strPassKeyString,
|
|
dwLength,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (!dwAllocLen)
|
|
{
|
|
dwError = GetLastError();
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
lpstrKeyMaterial = (UCHAR *)WlanAllocateMemory(dwAllocLen);
|
|
if (NULL == lpstrKeyMaterial)
|
|
{
|
|
dwError = GetLastError();
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
ZeroMemory(
|
|
lpstrKeyMaterial,
|
|
dwAllocLen
|
|
);
|
|
|
|
dwKeyBytes = WideCharToMultiByte(
|
|
CP_ACP,
|
|
WC_NO_BEST_FIT_CHARS,
|
|
strPassKeyString,
|
|
dwLength,
|
|
(LPSTR)lpstrKeyMaterial,
|
|
dwAllocLen,
|
|
NULL,
|
|
&bUnmappableChar
|
|
);
|
|
|
|
if (!dwKeyBytes)
|
|
{
|
|
dwError = GetLastError();
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
if (dwKeyBytes != dwAllocLen)
|
|
{
|
|
dwError = ERROR_INTERNAL_ERROR;
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
if (bUnmappableChar)
|
|
{
|
|
dwError = ERROR_BAD_FORMAT;
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
_ASSERT(DOT11_AUTH_ALGO_RSNA_PSK == dot11Auth);
|
|
switch (dot11Auth)
|
|
{
|
|
case DOT11_AUTH_ALGO_RSNA_PSK:
|
|
if ((dwKeyBytes > 63) || // Max length
|
|
(dwKeyBytes < 8)) // Min length
|
|
{
|
|
dwError = ERROR_BAD_FORMAT;
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
// Include an extra byte for the NULL terminator in a passphrase
|
|
dwReqdBytes = dwKeyBytes + 1;
|
|
break;
|
|
|
|
default:
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
if (!strPassKeyBuf || (*pdwBufLen < dwReqdBytes))
|
|
{
|
|
dwError = ERROR_MORE_DATA;
|
|
BAIL_ON_ERROR(dwError);
|
|
}
|
|
|
|
ZeroMemory(
|
|
strPassKeyBuf,
|
|
dwReqdBytes
|
|
);
|
|
|
|
CopyMemory(
|
|
strPassKeyBuf,
|
|
lpstrKeyMaterial,
|
|
dwKeyBytes
|
|
);
|
|
error:
|
|
if (pdwBufLen)
|
|
{
|
|
*pdwBufLen = dwReqdBytes;
|
|
}
|
|
|
|
if (lpstrKeyMaterial)
|
|
{
|
|
WlanFreeMemory(lpstrKeyMaterial);
|
|
}
|
|
|
|
|
|
return dwError;
|
|
}
|