2025-11-28 00:35:46 +09:00

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;
}