windows-nt/Source/XPSP1/NT/net/layer2svc/zeroconf/client/util.c
2020-09-26 16:20:57 +08:00

1114 lines
26 KiB
C

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2001
//
// File: U T I L. C
//
// Contents: Utility functions
//
//
//----------------------------------------------------------------------------
#include "util.h"
//+---------------------------------------------------------------------------
//
// EAPOL related util functions
//
//+---------------------------------------------------------------------------
// EAP configuration registry definitions.
static WCHAR REGKEY_Eap[] = L"System\\CurrentControlSet\\Services\\Rasman\\PPP\\EAP";
static WCHAR REGVAL_szFriendlyName[] = L"FriendlyName";
static WCHAR REGVAL_szConfigDll[] = L"ConfigUIPath";
static WCHAR REGVAL_szIdentityDll[] = L"IdentityPath";
static WCHAR REGVAL_fRequirePwd[] = L"InvokePasswordDialog";
static WCHAR REGVAL_fRequireUser[] = L"InvokeUsernameDialog";
static WCHAR REGVAL_pData[] = L"ConfigData";
static WCHAR REGVAL_fForceConfig[] = L"RequireConfigUI";
static WCHAR REGVAL_fMppeSupported[] = L"MPPEEncryptionSupported";
// Location of User blob
#define cwszEapKeyEapolUser L"Software\\Microsoft\\EAPOL\\UserEapInfo"
#define cwszDefault L"Default"
BYTE g_bDefaultSSID[MAX_SSID_LEN]={0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22, 0x33, 0x11, 0x22};
//
// EAP configuration manipulation routines
//
//+---------------------------------------------------------------------------
//
// Returns a created, empty EAPCFG descriptor node, or NULL on error.
//
DTLNODE*
CreateEapcfgNode (
void
)
{
DTLNODE* pNode = NULL;
EAPCFG* pEapcfg = NULL;
pNode = DtlCreateSizedNode( sizeof(EAPCFG), 0L );
if (pNode)
{
pEapcfg = (EAPCFG* )DtlGetData( pNode );
if (pEapcfg)
{
pEapcfg->dwKey = (DWORD )-1;
pEapcfg->pszConfigDll = NULL;
pEapcfg->pszIdentityDll = NULL;
pEapcfg->dwStdCredentialFlags = 0;
pEapcfg->fProvidesMppeKeys = FALSE;
pEapcfg->fForceConfig = FALSE;
pEapcfg->pData = NULL;
pEapcfg->cbData = 0;
pEapcfg->fConfigDllCalled = FALSE;
}
}
return pNode;
}
//+---------------------------------------------------------------------------
//
// Release resources associated with EAPCFG node 'pNode'. See
// DtlDestroyList.
//
VOID
DestroyEapcfgNode (
IN OUT DTLNODE* pNode
)
{
EAPCFG* pEapcfg = NULL;
pEapcfg = (EAPCFG* )DtlGetData( pNode );
if (pEapcfg)
{
if (pEapcfg->pszConfigDll)
FREE ( pEapcfg->pszConfigDll );
if (pEapcfg->pszIdentityDll)
FREE ( pEapcfg->pszIdentityDll );
if (pEapcfg->pData)
FREE ( pEapcfg->pData );
if (pEapcfg->pszFriendlyName)
FREE ( pEapcfg->pszFriendlyName );
}
DtlDestroyNode( pNode );
}
//+---------------------------------------------------------------------------
//
// Returns the EAPCFG node in list 'pList' with EAP key value of 'dwKey'
// or NULL if not found.
//
DTLNODE*
EapcfgNodeFromKey(
IN DTLLIST* pList,
IN DWORD dwKey
)
{
DTLNODE* pNode = NULL;
for (pNode = DtlGetFirstNode( pList );
pNode;
pNode = DtlGetNextNode( pNode ))
{
EAPCFG* pEapcfg = (EAPCFG* )DtlGetData( pNode );
if (pEapcfg)
{
if (pEapcfg->dwKey == dwKey)
{
return pNode;
}
}
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// Returns the address of a created list of installed custom
// authentication packages or NULL if none could be read. On success, it
// is caller's responsibility to eventually call DtlDestroyList on the
// returned list.
//
DTLLIST*
ReadEapcfgList (
IN DWORD dwFlags
)
{
DWORD dwErr = 0;
BOOL fOk = FALSE;
DTLLIST* pList = NULL;
DTLNODE* pNode = NULL;
EAPCFG* pEapcfg = NULL;
HKEY hkeyLM = NULL;
HKEY hkeyEap = NULL;
HKEY hkeyPackage = NULL;
CHAR szEapType[ 11 + 1 ];
DWORD dwEapType = 0;
TCHAR* psz = NULL;
DWORD dw;
DWORD cb;
INT i;
TCHAR* szCLSID = NULL;
DWORD dwHidePEAPMSCHAPv2 = 0;
HRESULT hr = S_OK;
pList = DtlCreateList( 0L );
if (!pList)
{
return NULL;
}
// Open the EAP key which contains a sub-key for each installed package.
dwErr = RegOpenKeyEx(
HKEY_LOCAL_MACHINE, (LPCTSTR)REGKEY_Eap, 0, KEY_READ, &hkeyEap );
if (dwErr != NO_ERROR)
{
return pList;
}
// Display EAP-MSCHAPv2 as an EAP method?
GetRegDword( hkeyEap, RAS_EAP_VALUENAME_HIDEPEAPMSCHAPv2, &dwHidePEAPMSCHAPv2 );
// Open each sub-key and extract the package definition from it's values.
// Problems with opening individual sub-keys result in that node only
// being discarded.
for (i = 0; TRUE; ++i)
{
cb = sizeof(szEapType);
dwErr = RegEnumKeyExA(
hkeyEap, i, szEapType, &cb, NULL, NULL, NULL, NULL );
if (dwErr != 0)
{
// Includes "out of items", the normal loop termination.
break;
}
dwEapType = atol (szEapType);
if (dwHidePEAPMSCHAPv2 != 0)
{
if (dwEapType == EAP_TYPE_MSCHAPv2)
{
// ignore EAP-MSCHAPv2
continue;
}
}
// Ignored non-mutual-auth DLLs like EAP
if (dwFlags & EAPOL_MUTUAL_AUTH_EAP_ONLY)
{
if (dwEapType == EAP_TYPE_MD5)
{
continue;
}
}
dwErr = RegOpenKeyExA(
hkeyEap, szEapType, 0, KEY_READ, &hkeyPackage );
if (dwErr != 0)
{
continue;
}
do
{
// Roles Supported
dw = RAS_EAP_ROLE_AUTHENTICATEE;
GetRegDword( hkeyPackage, RAS_EAP_VALUENAME_ROLES_SUPPORTED, &dw );
if (dw & RAS_EAP_ROLE_EXCLUDE_IN_EAP)
{
break;
}
if (!(dw & RAS_EAP_ROLE_AUTHENTICATEE))
{
break;
}
pNode = CreateEapcfgNode();
if (!pNode)
{
break;
}
pEapcfg = (EAPCFG* )DtlGetData( pNode );
if (!pEapcfg)
{
break;
}
// EAP type ID.
pEapcfg->dwKey = (LONG )atol( szEapType );
// Friendly display name.
psz = NULL;
dwErr = GetRegSz( hkeyPackage, REGVAL_szFriendlyName, &psz );
if (dwErr != 0)
{
break;
}
pEapcfg->pszFriendlyName = psz;
// Configuration DLL path.
psz = NULL;
dwErr = GetRegExpandSz( hkeyPackage, REGVAL_szConfigDll, &psz );
if (dwErr != 0)
{
break;
}
if (*psz)
{
pEapcfg->pszConfigDll = psz;
}
else
{
FREE ( psz );
}
// Identity DLL path.
psz = NULL;
dwErr = GetRegExpandSz( hkeyPackage, REGVAL_szIdentityDll, &psz );
if (dwErr != 0)
{
break;
}
if (*psz)
{
pEapcfg->pszIdentityDll = psz;
}
else
{
FREE ( psz );
}
// Prompt user name
dw = 1;
GetRegDword( hkeyPackage, REGVAL_fRequireUser, &dw );
if (dw)
pEapcfg->dwStdCredentialFlags |= EAPCFG_FLAG_RequireUsername;
// Prompt password
dw = 0;
GetRegDword( hkeyPackage, REGVAL_fRequirePwd, &dw );
if (dw)
pEapcfg->dwStdCredentialFlags |= EAPCFG_FLAG_RequirePassword;
// MPPE encryption keys flag.
dw = 0;
GetRegDword( hkeyPackage, REGVAL_fMppeSupported, &dw );
pEapcfg->fProvidesMppeKeys = !!dw;
// Force configuration API to run at least once.
dw = FALSE;
GetRegDword( hkeyPackage, REGVAL_fForceConfig, &dw );
pEapcfg->fForceConfig = !!dw;
// Configuration blob.
GetRegBinary(
hkeyPackage, REGVAL_pData,
&pEapcfg->pData, &pEapcfg->cbData );
// ConfigCLSID
dwErr = GetRegSz( hkeyPackage, RAS_EAP_VALUENAME_CONFIG_CLSID,
&szCLSID );
if (dwErr != 0)
{
break;
}
// Ignore errors. Eg. EAP MD5-Challenge does not have a ConfigCLSID.
//
// hr = CLSIDFromString( szCLSID, &( pEapcfg->guidConfigCLSID ) );
FREE ( szCLSID );
// Add the completed node to the list.
DtlAddNodeLast( pList, pNode );
fOk = TRUE;
} while (FALSE);
if (!fOk && pNode)
{
DestroyEapcfgNode( pNode );
}
RegCloseKey( hkeyPackage );
}
RegCloseKey( hkeyEap );
return pList;
}
//+---------------------------------------------------------------------------
//
// Allocates a sized node with space for 'lDataBytes' bytes of user data
// built-in. The node is initialized to contain the address of the
// built-in user data block (or NULL if of zero length) and the
// user-defined node identification code 'lNodeId'. The user data block
// is zeroed.
//
// Returns the address of the new node or NULL if out of memory.
//
DTLNODE*
DtlCreateSizedNode (
IN LONG lDataBytes,
IN LONG_PTR lNodeId
)
{
DTLNODE* pdtlnode = (DTLNODE *) MALLOC ( sizeof(DTLNODE) + lDataBytes );
if (pdtlnode)
{
ZeroMemory( pdtlnode, sizeof(DTLNODE) + lDataBytes );
if (lDataBytes)
pdtlnode->pData = pdtlnode + 1;
pdtlnode->lNodeId = lNodeId;
}
return pdtlnode;
}
//+---------------------------------------------------------------------------
//
// Deallocates node 'pdtlnode'. It is the caller's responsibility to free
// the entry in an unsized node, if necessary.
//
VOID
DtlDestroyNode (
IN OUT DTLNODE* pdtlnode
)
{
if (pdtlnode != NULL)
{
FREE ( pdtlnode );
}
}
//+---------------------------------------------------------------------------
//
// Adds 'pdtlnode' at the end of list 'pdtllist'.
//
// Returns the address of the added node, i.e. 'pdtlnode'.
//
DTLNODE*
DtlAddNodeLast (
IN OUT DTLLIST* pdtllist,
IN OUT DTLNODE* pdtlnode
)
{
if (pdtllist->lNodes)
{
pdtlnode->pdtlnodePrev = pdtllist->pdtlnodeLast;
pdtllist->pdtlnodeLast->pdtlnodeNext = pdtlnode;
}
else
{
pdtlnode->pdtlnodePrev = NULL;
pdtllist->pdtlnodeFirst = pdtlnode;
}
pdtllist->pdtlnodeLast = pdtlnode;
pdtlnode->pdtlnodeNext = NULL;
++pdtllist->lNodes;
return pdtlnode;
}
//+---------------------------------------------------------------------------
//
// Removes node 'pdtlnodeInList' from list 'pdtllist'.
//
// Returns the address of the removed node, i.e. 'pdtlnodeInList'.
//
DTLNODE*
DtlRemoveNode (
IN OUT DTLLIST* pdtllist,
IN OUT DTLNODE* pdtlnodeInList
)
{
if (pdtlnodeInList->pdtlnodePrev)
pdtlnodeInList->pdtlnodePrev->pdtlnodeNext = pdtlnodeInList->pdtlnodeNext;
else
pdtllist->pdtlnodeFirst = pdtlnodeInList->pdtlnodeNext;
if (pdtlnodeInList->pdtlnodeNext)
pdtlnodeInList->pdtlnodeNext->pdtlnodePrev = pdtlnodeInList->pdtlnodePrev;
else
pdtllist->pdtlnodeLast = pdtlnodeInList->pdtlnodePrev;
--pdtllist->lNodes;
return pdtlnodeInList;
}
//+---------------------------------------------------------------------------
//
// Allocates a list and initializes it to empty. The list is marked with
// the user-defined list identification code 'lListId'.
//
// Returns the address of the list control block or NULL if out of memory.
//
DTLLIST*
DtlCreateList (
IN LONG lListId
)
{
DTLLIST* pdtllist = MALLOC (sizeof(DTLLIST));
if (pdtllist)
{
pdtllist->pdtlnodeFirst = NULL;
pdtllist->pdtlnodeLast = NULL;
pdtllist->lNodes = 0;
pdtllist->lListId = lListId;
}
return pdtllist;
}
//+---------------------------------------------------------------------------
//
// Deallocates all nodes in list 'pdtllist' using the node deallocation
// function 'pfuncDestroyNode' if non-NULL or DtlDestroyNode otherwise.
// Won't GP-fault if passed a NULL list, e.g. if 'pdtllist', was never
// allocated.
//
VOID
DtlDestroyList (
IN OUT DTLLIST* pdtllist,
IN PDESTROYNODE pfuncDestroyNode
)
{
if (pdtllist)
{
DTLNODE* pdtlnode;
while (pdtlnode = DtlGetFirstNode( pdtllist ))
{
DtlRemoveNode( pdtllist, pdtlnode );
if (pfuncDestroyNode)
pfuncDestroyNode( pdtlnode );
else
DtlDestroyNode( pdtlnode );
}
FREE ( pdtllist );
}
}
//+---------------------------------------------------------------------------
//
// Set '*ppbResult' to the BINARY registry value 'pszName' under key
// 'hkey'. If the value does not exist *ppbResult' is set to NULL.
// '*PcbResult' is the number of bytes in the returned '*ppbResult'. It
// is caller's responsibility to Free the returned block.
//
VOID
GetRegBinary (
IN HKEY hkey,
IN TCHAR* pszName,
OUT BYTE** ppbResult,
OUT DWORD* pcbResult
)
{
DWORD dwErr;
DWORD dwType;
BYTE* pb;
DWORD cb;
*ppbResult = NULL;
*pcbResult = 0;
// Get result buffer size required.
dwErr = RegQueryValueEx(
hkey, pszName, NULL, &dwType, NULL, &cb );
if (dwErr != NO_ERROR)
{
return;
}
// Allocate result buffer.
pb = MALLOC (cb);
if (!pb)
{
return;
}
// Get the result block.
dwErr = RegQueryValueEx(
hkey, pszName, NULL, &dwType, (LPBYTE )pb, &cb );
if (dwErr == NO_ERROR)
{
*ppbResult = pb;
*pcbResult = cb;
}
}
//+---------------------------------------------------------------------------
//
// Set '*pdwResult' to the DWORD registry value 'pszName' under key
// 'hkey'. If the value does not exist '*pdwResult' is unchanged.
//
VOID
GetRegDword (
IN HKEY hkey,
IN TCHAR* pszName,
OUT DWORD* pdwResult
)
{
DWORD dwErr;
DWORD dwType;
DWORD dwResult;
DWORD cb;
cb = sizeof(DWORD);
dwErr = RegQueryValueEx(
hkey, pszName, NULL, &dwType, (LPBYTE )&dwResult, &cb );
if ((dwErr == NO_ERROR) && dwType == REG_DWORD && cb == sizeof(DWORD))
{
*pdwResult = dwResult;
}
}
//+---------------------------------------------------------------------------
//
// Set '*ppszResult' to the fully expanded EXPAND_SZ registry value
// 'pszName' under key 'hkey'. If the value does not exist *ppszResult'
// is set to empty string.
//
// Returns 0 if successful or an error code. It is caller's
// responsibility to Free the returned string.
//
DWORD
GetRegExpandSz(
IN HKEY hkey,
IN TCHAR* pszName,
OUT TCHAR** ppszResult )
{
DWORD dwErr;
DWORD cb;
TCHAR* pszResult;
// Get the unexpanded result string.
//
dwErr = GetRegSz( hkey, pszName, ppszResult );
if (dwErr != 0)
{
return dwErr;
}
// Find out how big the expanded string will be.
//
cb = ExpandEnvironmentStrings( *ppszResult, NULL, 0 );
if (cb == 0)
{
dwErr = GetLastError();
FREE ( *ppszResult );
return dwErr;
}
// Allocate a buffer for the expanded string.
//
pszResult = MALLOC ((cb + 1) * sizeof(TCHAR));
if (!pszResult)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
// Expand the environmant variables in the string, storing the result in
// the allocated buffer.
//
cb = ExpandEnvironmentStrings( *ppszResult, pszResult, cb + 1 );
if (cb == 0)
{
dwErr = GetLastError();
if (*ppszResult != NULL)
{
FREE ( *ppszResult );
}
if (pszResult != NULL)
{
FREE ( pszResult );
}
return dwErr;
}
FREE ( *ppszResult );
*ppszResult = pszResult;
return 0;
}
//+---------------------------------------------------------------------------
//
// Set '*ppszResult' to the SZ registry value 'pszName' under key 'hkey'.
// If the value does not exist *ppszResult' is set to empty string.
//
// Returns 0 if successful or an error code. It is caller's
// responsibility to Free the returned string.
//
DWORD
GetRegSz(
IN HKEY hkey,
IN TCHAR* pszName,
OUT TCHAR** ppszResult )
{
DWORD dwErr = NO_ERROR;
DWORD dwType;
DWORD cb;
TCHAR* pszResult;
// Get result buffer size required.
dwErr = RegQueryValueEx(
hkey, pszName, NULL, &dwType, NULL, &cb );
if (dwErr != NO_ERROR)
{
cb = sizeof(TCHAR);
}
// Allocate result buffer.
pszResult = MALLOC (cb * sizeof(TCHAR));
if (!pszResult)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
*pszResult = TEXT('\0');
*ppszResult = pszResult;
// Get the result string. It's not an error if we can't get it.
dwErr = RegQueryValueEx(
hkey, pszName, NULL, &dwType, (LPBYTE )pszResult, &cb );
return NO_ERROR;
}
//
// WZCGetEapUserInfo
//
// Description:
//
// Function called to retrieve the user data for an interface for a
// specific EAP type and SSID (if any). Data is retrieved from the HKCU hive
//
// Arguments:
// pwszGUID - pointer to GUID string for the interface
// dwEapTypeId - EAP type for which user data is to be stored
// dwSizeOfSSID - Size of Special identifier if any for the EAP user blob
// pbSSID - Special identifier if any for the EAP user blob
// pbUserInfo - output: pointer to EAP user data blob
// dwInfoSize - output: pointer to size of EAP user blob
//
// Return values:
// NO_ERROR - success
// non-zero - error
//
DWORD
WZCGetEapUserInfo (
IN WCHAR *pwszGUID,
IN DWORD dwEapTypeId,
IN DWORD dwSizeOfSSID,
IN BYTE *pbSSID,
IN OUT PBYTE pbUserInfo,
IN OUT DWORD *pdwInfoSize
)
{
HKEY hkey = NULL;
HKEY hkey1 = NULL;
HKEY hkey2 = NULL;
DWORD dwNumValues = 0, dwMaxValueNameLen = 0, dwTempValueNameLen = 0, dwMaxValueLen = 0;
DWORD dwIndex = 0, dwMaxValueName = 0;
WCHAR *pwszValueName = NULL;
BYTE *pbValueBuf = NULL;
DWORD dwValueData = 0;
BYTE *pbDefaultValue = NULL;
DWORD dwDefaultValueLen = 0;
BYTE *pbEapBlob = NULL;
DWORD dwEapBlob = 0;
BYTE *pbAuthData = NULL;
DWORD dwAuthData = 0;
BOOLEAN fFoundValue = FALSE;
EAPOL_INTF_PARAMS *pRegParams = NULL;
LONG lError = ERROR_SUCCESS;
DWORD dwRetCode = ERROR_SUCCESS;
do
{
// Validate input params
if (pwszGUID == NULL)
{
dwRetCode = ERROR_CAN_NOT_COMPLETE;
break;
}
if (dwEapTypeId == 0)
{
dwRetCode = ERROR_CAN_NOT_COMPLETE;
break;
}
// Get handle to HKCU\Software\...\UserEapInfo
if ((lError = RegOpenKeyEx (
HKEY_CURRENT_USER,
cwszEapKeyEapolUser,
0,
KEY_READ,
&hkey1
)) != ERROR_SUCCESS)
{
dwRetCode = (DWORD)lError;
break;
}
// Get handle to HKCU\Software\...\UserEapInfo\<GUID>
if ((lError = RegOpenKeyEx (
hkey1,
pwszGUID,
0,
KEY_READ,
&hkey2
)) != ERROR_SUCCESS)
{
dwRetCode = (DWORD)lError;
break;
}
// Set correct SSID
if (dwSizeOfSSID == 0)
{
pbSSID = g_bDefaultSSID;
dwSizeOfSSID = MAX_SSID_LEN;
}
if ((lError = RegQueryInfoKey (
hkey2,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&dwNumValues,
&dwMaxValueNameLen,
&dwMaxValueLen,
NULL,
NULL
)) != NO_ERROR)
{
dwRetCode = (DWORD)lError;
break;
}
if ((pwszValueName = MALLOC ((dwMaxValueNameLen + 1) * sizeof (WCHAR))) == NULL)
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
dwMaxValueNameLen++;
if ((pbValueBuf = MALLOC (dwMaxValueLen)) == NULL)
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
{
dwValueData = dwMaxValueLen;
dwTempValueNameLen = dwMaxValueNameLen;
if ((lError = RegEnumValue (
hkey2,
dwIndex,
pwszValueName,
&dwTempValueNameLen,
NULL,
NULL,
pbValueBuf,
&dwValueData
)) != ERROR_SUCCESS)
{
if (lError != ERROR_MORE_DATA)
{
break;
}
lError = ERROR_SUCCESS;
}
if (dwValueData < sizeof (EAPOL_INTF_PARAMS))
{
lError = ERROR_INVALID_DATA;
break;
}
pRegParams = (EAPOL_INTF_PARAMS *)pbValueBuf;
if (((DWORD)_wtol(pwszValueName)) > dwMaxValueName)
{
dwMaxValueName = _wtol (pwszValueName);
}
if (!memcmp (pRegParams->bSSID, pbSSID, dwSizeOfSSID))
{
fFoundValue = TRUE;
break;
}
}
if ((lError != ERROR_SUCCESS) && (lError != ERROR_NO_MORE_ITEMS))
{
dwRetCode = (DWORD)lError;
break;
}
else
{
lError = ERROR_SUCCESS;
}
if (!fFoundValue)
{
pbEapBlob = NULL;
dwEapBlob = 0;
}
else
{
// Use pbValueBuf & dwValueData
pbEapBlob = pbValueBuf;
dwEapBlob = dwValueData;
}
// If default blob is not present, exit
if ((pbEapBlob == NULL) && (dwEapBlob == 0))
{
*pdwInfoSize = 0;
break;
}
if ((dwRetCode = WZCGetEapData (
dwEapTypeId,
dwEapBlob,
pbEapBlob,
sizeof (EAPOL_INTF_PARAMS),
&dwAuthData,
&pbAuthData
)) != NO_ERROR)
{
break;
}
// Return the data if sufficient space allocated
if ((pbUserInfo != NULL) && (*pdwInfoSize >= dwAuthData))
{
memcpy (pbUserInfo, pbAuthData, dwAuthData);
}
else
{
dwRetCode = ERROR_INSUFFICIENT_BUFFER;
}
*pdwInfoSize = dwAuthData;
} while (FALSE);
if (hkey != NULL)
{
RegCloseKey (hkey);
}
if (hkey1 != NULL)
{
RegCloseKey (hkey1);
}
if (hkey2 != NULL)
{
RegCloseKey (hkey2);
}
if (pbValueBuf != NULL)
{
FREE (pbValueBuf);
}
if (pbDefaultValue != NULL)
{
FREE (pbDefaultValue);
}
if (pwszValueName != NULL)
{
FREE (pwszValueName);
}
return dwRetCode;
}
//
// WZCGetEapData
//
// Description:
//
// Function to extract Eap Data out of a blob containing many EAP data
//
// Arguments:
// dwEapType -
// dwSizeOfIn -
// pbBufferIn -
// dwOffset -
// pdwSizeOfOut -
// ppbBufferOut -
//
// Return values:
//
//
DWORD
WZCGetEapData (
IN DWORD dwEapType,
IN DWORD dwSizeOfIn,
IN BYTE *pbBufferIn,
IN DWORD dwOffset,
IN DWORD *pdwSizeOfOut,
IN PBYTE *ppbBufferOut
)
{
DWORD dwRetCode = NO_ERROR;
DWORD cbOffset = 0;
EAPOL_AUTH_DATA *pCustomData = NULL;
do
{
*pdwSizeOfOut = 0;
*ppbBufferOut = NULL;
if (pbBufferIn == NULL)
{
break;
}
// Align to start of EAP blob
cbOffset = dwOffset;
while (cbOffset < dwSizeOfIn)
{
pCustomData = (EAPOL_AUTH_DATA *)
((PBYTE) pbBufferIn + cbOffset);
if (pCustomData->dwEapType == dwEapType)
{
break;
}
cbOffset += sizeof (EAPOL_AUTH_DATA) + pCustomData->dwSize;
}
if (cbOffset < dwSizeOfIn)
{
*pdwSizeOfOut = pCustomData->dwSize;
*ppbBufferOut = pCustomData->bData;
}
}
while (FALSE);
return dwRetCode;
}
//
// WZCEapolFreeState
//
// Description:
//
// Function to free EAPOL interface state information on the client side
// obtained via RPC query
//
// Arguments:
// pIntfState -
//
// Return values:
//
//
DWORD
WZCEapolFreeState (
IN EAPOL_INTF_STATE *pIntfState
)
{
DWORD dwRetCode = NO_ERROR;
do
{
RpcFree(pIntfState->pwszLocalMACAddr);
RpcFree(pIntfState->pwszRemoteMACAddr);
RpcFree(pIntfState->pszEapIdentity);
}
while (FALSE);
return dwRetCode;
}