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

659 lines
18 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 "EapHostCommon.h"
#include "memory.h"
#include "strsafe.h"
namespace SDK_METHOD_SAMPLE_COMMON
{
/**
* Allocate space for the EAPAttributes structure that will contain specified number of EAP attributes.
*
* @param attribCount The # of Eap attributes to create.
*
* @param ppEapAttributes (input/output) A pointer to the real data buffer pointer.
* The real pointer will be set to point to the allocated memory.
*
* @return A Win32 error code, indicating success or failure.
*/
DWORD
AllocateAttributes(
IN DWORD attribCount,
IN OUT EapAttributes **ppEapAttributes
)
{
DWORD retCode = NO_ERROR;
DWORD bufLen = 0;
// Sanity Check
if (! ppEapAttributes)
{
retCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if(attribCount > MAX_ATTR_IN_EAP_ATTRIBUTES)
{
retCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// Allocate Memory for the EapAttributes structure.
//
retCode = AllocateMemory(sizeof(EapAttributes), (PVOID*)ppEapAttributes);
if (retCode != NO_ERROR)
{
goto Cleanup;
}
//
// Assign the number of EAP attributes that the EapAttributes structure will contain.
//
(*ppEapAttributes)->dwNumberOfAttributes = attribCount;
//
// Allocate Memory for the EapAttribute pointer in the EapAttributes structure.
//
bufLen = sizeof(EapAttribute) * attribCount;
retCode = AllocateMemory(bufLen, (PVOID*)&((*ppEapAttributes)->pAttribs));
if (retCode != NO_ERROR)
{
goto Cleanup;
}
// AllocateMemory() initializes the buffer to NULL values.
Cleanup:
if(retCode != NO_ERROR)
FreeMemory((PVOID*)ppEapAttributes);
return retCode;
}
/**
* Free a EapAttributes structure.
*
* This function will walk the chain of attributes, freeing each attribute's
* Value data pointer, it will free the list's data buffer, and set the former
* data buffer pointer to point to NULL.
*
* @param ppEapAttributes (input/output) A pointer to the real data buffer
* pointer.
*
* @return A Win32 error code, indicating success or failure.
*
*/
DWORD
FreeAttributes(
IN OUT EapAttributes **ppEapAttributes
)
{
DWORD retCode = NO_ERROR;
DWORD attribCount = 0;
EapAttribute *pEapAttrib = NULL;
DWORD i = 0;
//Sanity Check
if (! ppEapAttributes)
{
retCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if (! *ppEapAttributes)
{
// Return silently. No attribute. Nothing to free.
goto Cleanup;
}
attribCount = (*ppEapAttributes)->dwNumberOfAttributes;
//
// Free all the Value pointers in each EAP attribute.
//
for(i = 0; i < attribCount; i++)
{
pEapAttrib = &(((*ppEapAttributes)->pAttribs)[i]);
retCode = FreeMemory((PVOID*)&(pEapAttrib->pValue));
if (retCode != NO_ERROR)
goto Cleanup;
}
//
// Free the (EapAttribute *) in the EapAttributes structure.
//
retCode = FreeMemory((PVOID *)&((*ppEapAttributes)->pAttribs));
if (retCode != NO_ERROR)
goto Cleanup;
//
// Free the EapAttributes structure.
//
retCode = FreeMemory((PVOID*)ppEapAttributes);
if (retCode != NO_ERROR)
goto Cleanup;
// FreeMemory sets the buffer pointer to NULL after freeing the data.
Cleanup:
return retCode;
}
/**
* Set an attribute in a pre-allocated list.
*
* This function takes the attribute list buffer from AllocateAttributes(),
* finds the first unset attribute, and sets it to contain the specified data.
* It allocates memory for the attribute's value member.
*
* @param pEapAttributes (input/output) A pointer to the real data buffer pointer.
* @param eaType New attribute's type (from eaptypes.h).
* @param dwLength New attribute's length.
* @param pValue New attribute's value.
*
* @return A Win32 error code, indicating success or failure.
*/
DWORD
AddAttribute(
IN OUT EapAttributes *pEapAttributes,
IN EapAttributeType eaType,
IN DWORD dwLength,
IN PVOID pValue
)
{
DWORD retCode = NO_ERROR;
DWORD i = 0;
EapAttribute *pEapAttrib = NULL;
//Sanity Check
if (! pEapAttributes)
{
retCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// Find the next available (empty) attribute.
//
for (i = 0; i < pEapAttributes->dwNumberOfAttributes; i++)
{
pEapAttrib = &((pEapAttributes->pAttribs)[i]);
if (pEapAttrib->eaType == eatMinimum)
break;
}
//
// Array bounds check -- make sure we have room for this element.
//
if (i == pEapAttributes->dwNumberOfAttributes)
{
retCode = ERROR_OUT_OF_STRUCTURES;
goto Cleanup;
}
//
// Fill up the attribute structure.
//
pEapAttrib->eaType = eaType;
pEapAttrib->dwLength = dwLength;
retCode = AllocateMemory(dwLength, (PVOID*)&(pEapAttrib->pValue));
if (retCode != NO_ERROR)
{
goto Cleanup;
}
//
// Copy the actual data length into the buffer.
//
CopyMemory(pEapAttrib->pValue, pValue, dwLength);
Cleanup:
return retCode;
}
/**
* Append a new attribute onto the end of an existing list (extending list).
*
* This function creates a new, larger attribute list, copies attributes
* from the original list into the new list, and adds the new attribute
* onto the end of the list.
*
*
* @param ppAttributesList (input/output) A pointer to the real attribute
* list data buffer pointer. The data will be
* copied out of this buffer, the buffer freed, and
* the pointer set to the new attribute list.
* @param eaType New attribute's type (from EapTypes.h).
* @param dwLength New attribute's length
* @param value New attribute's value.
*
* @return A Win32 error code, indicating success or failure.
*/
DWORD
AppendAttributeToList(
IN OUT EapAttributes **ppAttributesList,
IN EapAttributeType eaType,
IN DWORD dwLength,
IN PVOID value
)
{
DWORD retCode = NO_ERROR;
DWORD dwCount = 0;
DWORD attribCountOld = 0;
EapAttribute *pEapAttrib = NULL;
DWORD dwIndex = 0;
EapAttributes *pNewAttributesList = NULL;
// Sanity check.
if (! ppAttributesList)
{
retCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// Determine how many attributes we'll need in the new list.
//
if (! *ppAttributesList)
{
attribCountOld = 0;
}
else
attribCountOld = (*ppAttributesList)->dwNumberOfAttributes;
dwCount = 1 + attribCountOld;
//
// Allocate a new attributes list, with the specified length.
//
retCode = AllocateAttributes(dwCount, &pNewAttributesList);
if (retCode != NO_ERROR)
goto Cleanup;
//
// Copy the old attributes list into the new list.
//
if (*ppAttributesList != NULL)
{
for( dwIndex = 0; dwIndex < attribCountOld; dwIndex++ )
{
pEapAttrib = &((*ppAttributesList)->pAttribs)[dwIndex];
retCode = AddAttribute(pNewAttributesList,
pEapAttrib->eaType,
pEapAttrib->dwLength,
pEapAttrib->pValue);
if (retCode != NO_ERROR)
goto Cleanup;
}
}
//
// Add the new attribute into the new list.
//
retCode = AddAttribute(pNewAttributesList, eaType, dwLength, value);
if (retCode != NO_ERROR)
goto Cleanup;
//
// Free the old list, and pass back the new list.
//
retCode = FreeAttributes(ppAttributesList);
if (retCode != NO_ERROR)
goto Cleanup;
*ppAttributesList = pNewAttributesList;
Cleanup:
if (retCode != NO_ERROR)
FreeAttributes(&pNewAttributesList);
return retCode;
}
/**
* Allocates EAP_ERROR structure and fills it using the input parameters.
*
* The memory will be freed by EapPeerFreeErrorMemory() or EapMethodAuthenticatorFreeErrorMemory()
* depending on who the caller of this API is.
*
* @param pEapError EAP_ERROR will be allocated at this pointer and
* populated with above input parameters.
* @param errCode Win32 error code
* @param dwReasonCode Reason Code
* @param pRootCauseGuid Root Cause GUID
* @param pRepairGuid Repair GUID
* @param pHelpLinkGuid Help Link GUID
* @param pRootCauseString String describing the root cause
* @param pRepairString String describing the repair mechanism
*
* @return A Win32 error code, indicating success or failure.
*/
DWORD AllocateandFillEapError(
IN OUT EAP_ERROR** pEapError,
IN DWORD errCode,
IN DWORD dwReasonCode,
IN LPCGUID pRootCauseGuid,
IN LPCGUID pRepairGuid,
IN LPCGUID pHelpLinkGuid,
IN _In_opt_ LPWSTR pRootCauseString,
IN _In_opt_ LPWSTR pRepairString
)
{
DWORD retCode = NO_ERROR;
//Sanity Check
if(!pEapError)
{
retCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// Allocate memory for EAP_ERROR.
//
retCode = AllocateMemory(sizeof(EAP_ERROR), (PVOID *)pEapError);
if(retCode != NO_ERROR)
goto Cleanup;
ZeroMemory(*pEapError, sizeof(EAP_ERROR));
//
// Assign the Win32 Error Code
//
(*pEapError)->dwWinError = errCode;
//
// Assign the EAP_METHOD_TYPE to indicate which EAP Method send the error.
//
(*pEapError)->type.eapType.type = EAPTYPE;
(*pEapError)->type.eapType.dwVendorId = VENODR_ID;
(*pEapError)->type.eapType.dwVendorType = VENDOR_TYPE;
(*pEapError)->type.dwAuthorId = AUTHOR_ID;
//
// Assign the reason code
//
(*pEapError)->dwReasonCode = dwReasonCode;
//
// Assign the RootCause GUID
//
if(pRootCauseGuid != NULL)
memcpy(&((*pEapError)->rootCauseGuid), pRootCauseGuid, sizeof(GUID));
//
// Assign the Repair GUID
//
if(pRepairGuid != NULL)
memcpy(&((*pEapError)->repairGuid), pRepairGuid, sizeof(GUID));
//
// Assign the HelpLink GUID
//
if(pHelpLinkGuid!= NULL)
memcpy(&((*pEapError)->helpLinkGuid), pHelpLinkGuid, sizeof(GUID));
//
// Assign the Root Cause String
//
retCode = CopyWideString(pRootCauseString, &((*pEapError)->pRootCauseString));
if(retCode != NO_ERROR)
goto Cleanup;
//
// Assign the Repair String
//
retCode = CopyWideString(pRepairString, &((*pEapError)->pRepairString));
if(retCode != NO_ERROR)
goto Cleanup;
Cleanup:
if(retCode != NO_ERROR)
FreeMemory((PVOID*)pEapError);
return retCode;
}
DWORD CopyWideString(
IN _In_opt_ LPWSTR pSrcWString,
OUT _Out_ LPWSTR *pDestWString)
{
DWORD retCode = NO_ERROR;
HRESULT hr = S_OK;
size_t dwStringLength = 0;
LPWSTR pTempString = NULL;
*pDestWString = NULL;
// Nothing to copy
if(!pSrcWString)
goto Cleanup;
hr = StringCbLengthW(pSrcWString, (size_t)(STRSAFE_MAX_CCH * sizeof(wchar_t)), &dwStringLength);
if (FAILED(hr))
{
retCode = HRESULT_CODE(hr);
goto Cleanup;
}
// StringCbLengthW - returns the length of string in bytes (excluding the null character).
// StringCbCopyW expects the length of string in bytes (including the null character).
dwStringLength += sizeof(wchar_t);
retCode = AllocateMemory((DWORD)dwStringLength, (PVOID *)&pTempString);
if(retCode != NO_ERROR)
{
goto Cleanup;
}
hr = StringCbCopyW((LPTSTR)pTempString, dwStringLength, pSrcWString);
if (FAILED(hr))
{
retCode = HRESULT_CODE(hr);
goto Cleanup;
}
//
// Set the OUT parameter
//
*pDestWString = pTempString;
Cleanup:
if((retCode != NO_ERROR) && (pTempString != NULL))
FreeMemory((PVOID *)&pTempString);
pTempString = NULL;
return retCode;
}
/**
* Convert a 32-bit integer from host format to wire format.
*
* This function reorders the bytes in a given 32-bit value, into
* from host-byte order into network-byte order.
*
* The calling function is responsible for allocating memory for the output
* value. This can come from an explicit allocation, or from an implicit
* allocation such as a reference to a local variable.
*
*
* @param dwHostFormat [in] The input value, in host-byte order.
* @param pWireFormat [out] The output value, in network-byte order.
*/
VOID
HostToWireFormat32(
IN DWORD dwHostFormat,
IN OUT PBYTE pWireFormat
)
{
*((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(dwHostFormat) >> 24);
*((PBYTE)(pWireFormat)+1) = (BYTE) ((DWORD)(dwHostFormat) >> 16);
*((PBYTE)(pWireFormat)+2) = (BYTE) ((DWORD)(dwHostFormat) >> 8);
*((PBYTE)(pWireFormat)+3) = (BYTE) (dwHostFormat);
}
/**
* Convert a 16-bit integer from host format to wire format.
*
* This function reorders the bytes in a given 16-bit value, into
* from host-byte order into network-byte order.
*
* The calling function is responsible for allocating memory for the output
* value. This can come from an explicit allocation, or from an implicit
* allocation such as a reference to a local variable.
*
*
* @param wHostFormat [in] The input value, in host-byte order.
* @param pWireFormat [out] The output value, in network-byte order.
*/
VOID
HostToWireFormat16(
IN WORD wHostFormat,
IN OUT PBYTE pWireFormat
)
{
*((PBYTE)(pWireFormat)+0) = (BYTE) ((DWORD)(wHostFormat) >> 8);
*((PBYTE)(pWireFormat)+1) = (BYTE) (wHostFormat);
}
/**
* Convert a 16-bit integer from wire format to host format.
*
* This function reorders the bytes in a given 16-bit value, into
* from network-byte order into host-byte order.
*
* The calling function is responsible for allocating memory for the output
* value. This can come from an explicit allocation, or from an implicit
* allocation such as a reference to a local variable.
*
*
* @param wWireFormat [in] The input value, in network-byte order.
* @param pHostFormat [out] The output value, in host-byte order.
*/
VOID
WireToHostFormat16(
IN WORD wWireFormat,
IN OUT PBYTE pHostFormat
)
{
*pHostFormat = ((*((PBYTE)(&wWireFormat)+0) << 8) +
(*((PBYTE)(&wWireFormat)+1)));
}
/// Get the current working directory and appends dllName (input param) to it.
DWORD GetFullPath(
OUT _Out_ LPWSTR &pathName,
IN OUT DWORD &pathNameLength,
IN _In_ LPWSTR dllName,
IN DWORD sizeofDllNameInBytes
)
{
DWORD retCode = ERROR_SUCCESS;
DWORD bufferLength = 0;
pathName = NULL;
// Get the length that needs to be allocated for getting the current directory.
bufferLength = GetCurrentDirectory(0, NULL);
if(!bufferLength)
{
retCode = GetLastError();
goto Cleanup;
}
// Buffer Length is the number of Wide Characters including the NULL character.
// We need to calculate the total number of bytes to be allocated.
bufferLength = (bufferLength - 1) * sizeof(WCHAR);
bufferLength += sizeof(WCHAR); // For the intermediate '\'
bufferLength += sizeofDllNameInBytes;
pathNameLength = bufferLength;
retCode = AllocateMemory(bufferLength, (PVOID *)&pathName);
if(retCode != ERROR_SUCCESS)
goto Cleanup;
// Actually get the directory path.
bufferLength = GetCurrentDirectory(pathNameLength, pathName);
if(bufferLength == 0)
goto Cleanup;
// Append "\"
CopyMemory(pathName + bufferLength, L"\\", sizeof(WCHAR));
// Append DllName.
CopyMemory(pathName + bufferLength + 1, dllName, sizeofDllNameInBytes);
Cleanup:
if((pathName != NULL) &&
((retCode != ERROR_SUCCESS) || (bufferLength == 0)))
FreeMemory((PVOID *)&pathName);
return retCode;
}
/**
* Report a message to the trace log.
*
* This function reports the specified message to a file in
* \c %SystemRoot%\Tracing\[TraceFileName.log], where \c TraceFileName is the
* string used in the TraceRegister() call. This tracing
* log can help when trying to debug issues on Eap Methods on clients & servers where
* physical access is not possible, or where debuggers can't be run easily
*
* @param Format [in] An output string format specification, which can
* include printf-style format values (ie, "%d").
*
* @param ... [in] A number of optional arguments, corresponding to
* the number of format specifiers in the Format
* parameter.
*/
VOID
EapTrace(
IN _In_ CHAR* Format,
...
)
{
va_list arglist;
va_start(arglist, Format);
/// The default level assigned to each trace message.
DWORD g_DefaultTraceLevel = 0x00010000;
TraceVprintfExA(g_dwEapTraceId,
g_DefaultTraceLevel | TRACE_USE_MASK | TRACE_USE_MSEC,
Format,
arglist);
va_end(arglist);
}
} // End "namespace SDK_METHOD_SAMPLE_COMMON