/*++
Copyright (c) 2005 Microsoft Corporation
Abstract:
Sample IHV Extensibility DLL to extend
802.11 LWF driver for third party protocols.
--*/
#include "precomp.h"
//
// Get Version info.
//
DWORD
WINAPI
Dot11ExtIhvGetVersionInfo
(
OUT PDOT11_IHV_VERSION_INFO pDot11IHVVersionInfo
)
{
if ( pDot11IHVVersionInfo )
{
pDot11IHVVersionInfo->dwVerMin = 0;
pDot11IHVVersionInfo->dwVerMax = 0;
}
return ERROR_SUCCESS;
}
//
// Initialize service.
//
DWORD
WINAPI
Dot11ExtIhvInitService
(
IN DWORD dwVerNumUsed,
IN PDOT11EXT_APIS pDot11ExtAPI,
IN LPVOID pvReserved,
OUT PDOT11EXT_IHV_HANDLERS pDot11IHVHandlers
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
UNREFERENCED_PARAMETER( pvReserved );
if
(
( 0 != dwVerNumUsed ) ||
( !pDot11ExtAPI ) ||
( !pDot11IHVHandlers )
)
{
dwResult = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR( dwResult );
}
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
InitAdapterDetailsList( );
g_pDot11ExtApi = (PDOT11EXT_APIS) PrivateMemoryAlloc( sizeof( DOT11EXT_APIS ) );
if ( !g_pDot11ExtApi )
{
dwResult = ERROR_OUTOFMEMORY;
BAIL_ON_WIN32_ERROR( dwResult );
}
(*g_pDot11ExtApi) = (*pDot11ExtAPI);
HandlerInit( pDot11IHVHandlers );
error:
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// Deinitialize service.
//
VOID
WINAPI
IhvDeinitService
(
VOID
)
{
EnterCriticalSection( &g_csSynch );
// disable starting new threads or adding new adapters.
StartShutdown( );
LeaveCriticalSection( &g_csSynch );
WaitOnZeroThreads( );
DeinitAdapterDetailsList( );
if ( g_pDot11ExtApi )
{
PrivateMemoryFree( g_pDot11ExtApi );
g_pDot11ExtApi = NULL;
}
return;
}
//
// Initialize adapter
//
DWORD
WINAPI
IhvInitAdapter
(
IN PDOT11_ADAPTER pDot11Adapter,
IN HANDLE hDot11SvcHandle,
OUT PHANDLE phIhvExtAdapter
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
HANDLE hIhvExtAdapter = NULL;
USHORT usEtherTypeReg[] = { 0x888e, 0x8333 };
if (( !pDot11Adapter ) || (!hDot11SvcHandle) || (!phIhvExtAdapter) )
{
dwResult = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR( dwResult );
}
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
InitAdapterDetails
(
hDot11SvcHandle,
&hIhvExtAdapter
);
BAIL_ON_WIN32_ERROR( dwResult );
dwResult =
(g_pDot11ExtApi->Dot11ExtSetEtherTypeHandling)
(
hDot11SvcHandle,
3,
0,
NULL,
2,
usEtherTypeReg
);
BAIL_ON_WIN32_ERROR( dwResult );
(*phIhvExtAdapter) = hIhvExtAdapter;
hIhvExtAdapter = NULL;
error:
if ( hIhvExtAdapter )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// Deinit adapter.
//
VOID
WINAPI
IhvDeinitAdapter
(
IN HANDLE hIhvExtAdapter
)
{
DerefenceAdapterDetails( hIhvExtAdapter );
return;
}
//
// Handle session change notification.
//
DWORD
WINAPI
IhvProcessSessionChange
(
IN ULONG uEventType,
IN PWTSSESSION_NOTIFICATION pSessionNotification
)
{
UNREFERENCED_PARAMETER( pSessionNotification );
if ( WTS_CONSOLE_CONNECT == uEventType )
{
// The sample does not use this session ID
// anywhere. In an actual application, IHV
// developers may want to use this session ID to
// get/set the user data.
g_dwSessionID = WTSGetActiveConsoleSessionId( );
}
return ERROR_SUCCESS;
}
//
// Checks if UI request is pending.
//
DWORD
WINAPI
IhvIsUIRequestPending
(
IN GUID guidUIRequest,
OUT PBOOL pbIsRequestPending
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
PADAPTER_DETAILS pAdapterDetails = NULL;
HANDLE hIhvExtAdapter = NULL;
ASSERT( pbIsRequestPending );
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
// obtain reference to the adapter using
// UI request GUID.
dwResult =
ReferenceAdapterDetailsByUIRequestGuid
(
&guidUIRequest,
&pAdapterDetails,
&hIhvExtAdapter
);
if ( ERROR_NOT_FOUND == dwResult )
{
dwResult = ERROR_SUCCESS;
(*pbIsRequestPending) = FALSE;
BAIL( );
}
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
(*pbIsRequestPending) = TRUE;
error:
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// Handle NIC specific notifications.
//
DWORD
WINAPI
IhvReceiveIndication
(
IN HANDLE hIhvExtAdapter,
IN DOT11EXT_IHV_INDICATION_TYPE indicationType,
IN ULONG uBufferLength,
IN LPVOID pvBuffer
)
{
DWORD dwResult = ERROR_SUCCESS;
PDOT11_PMKID_CANDIDATE_LIST_PARAMETERS pPMKCandidateListParams = NULL;
PDOT11_TKIPMIC_FAILURE_PARAMETERS pTkipMicFailureParams = NULL;
PDOT11_PHY_STATE_PARAMETERS pPHYStateChange = NULL;
PDOT11_LINK_QUALITY_PARAMETERS pDot11LinkQualityParams = NULL;
ASSERT( pvBuffer );
// Note that sample does not really use the buffer.
UNREFERENCED_PARAMETER( hIhvExtAdapter );
UNREFERENCED_PARAMETER( uBufferLength );
switch ( indicationType )
{
case IndicationTypeNicSpecificNotification:
// The pointer pvBuffer can be interpreted by IHV appropriately. Format
// is a contract between the miniport driver and the IHV extensibility module.
break;
case IndicationTypePmkidCandidateList:
pPMKCandidateListParams = (PDOT11_PMKID_CANDIDATE_LIST_PARAMETERS) pvBuffer;
// Ihv extensibility module may choose to use this data appropriately.
break;
case IndicationTypeTkipMicFailure:
pTkipMicFailureParams = (PDOT11_TKIPMIC_FAILURE_PARAMETERS) pvBuffer;
// Ihv extensibility module may choose to use this data appropriately.
break;
case IndicationTypePhyStateChange:
pPHYStateChange = (PDOT11_PHY_STATE_PARAMETERS) pvBuffer;
// Ihv extensibility module may choose to use this data appropriately.
break;
case IndicationTypeLinkQuality:
pDot11LinkQualityParams = (PDOT11_LINK_QUALITY_PARAMETERS) pvBuffer;
// Ihv extensibility module may choose to use this data appropriately.
break;
default:
ASSERTFAILURE();
dwResult = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR( dwResult );
break;
}
error:
return dwResult;
}
//
// Perform the capabiity match.
//
DWORD
WINAPI
IhvPerformCapabilityMatch
(
IN HANDLE hIhvExtAdapter,
IN PDOT11EXT_IHV_PROFILE_PARAMS pIhvProfileParams,
IN PDOT11EXT_IHV_CONNECTIVITY_PROFILE pIhvConnProfile,
IN PDOT11EXT_IHV_SECURITY_PROFILE pIhvSecProfile,
IN PDOT11_BSS_LIST pConnectableBssid,
OUT PDWORD pdwReasonCode
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
PBYTE pbCurrPos = NULL;
ULONG uRemainBytes = 0;
ULONG uBssEntryBytes = 0;
PULDOT11_BSS_ENTRY pBssEntry = NULL;
PADAPTER_DETAILS pAdapterDetails = NULL;
PIHV_CONNECTIVITY_PROFILE pConnectivityProfile = NULL;
PIHV_SECURITY_PROFILE pSecurityProfile = NULL;
ASSERT( hIhvExtAdapter );
ASSERT( pdwReasonCode );
(*pdwReasonCode) = L2_REASON_CODE_UNKNOWN;
if ( !pConnectableBssid )
{
dwResult =
IhvValidateProfile
(
hIhvExtAdapter,
pIhvProfileParams,
pIhvConnProfile,
pIhvSecProfile,
pdwReasonCode
);
BAIL_ON_WIN32_ERROR( dwResult );
// Only validate profile if
// pConnectableBssid is NULL.
BAIL( );
}
// Validating data in pConnectableBssid
if (( 0 == pConnectableBssid->uNumOfBytes ) || ( NULL == pConnectableBssid->pucBuffer ))
{
dwResult = ERROR_NO_MATCH;
BAIL_ON_WIN32_ERROR( dwResult );
}
(*pdwReasonCode) = L2_REASON_CODE_IHV_BAD_PROFILE;
// parse the connectivity profile.
dwResult =
GetIhvConnectivityProfile
(
pIhvConnProfile,
&pConnectivityProfile
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pConnectivityProfile );
// parse the security profile.
dwResult =
GetIhvSecurityProfile
(
pIhvSecProfile,
&pSecurityProfile
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pSecurityProfile );
(*pdwReasonCode) = L2_REASON_CODE_UNKNOWN;
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
// reference the adapter.
dwResult =
ReferenceAdapterDetails
(
hIhvExtAdapter,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
// try matching each BSS description field with the profile
// and see if there is a match.
uRemainBytes = pConnectableBssid->uNumOfBytes;
pbCurrPos = pConnectableBssid->pucBuffer;
// BSS Description might not contain any buffer!
while (uRemainBytes >= FIELD_OFFSET(DOT11_BSS_ENTRY, ucBuffer))
{
pBssEntry = (PULDOT11_BSS_ENTRY)pbCurrPos;
uBssEntryBytes = pBssEntry->uBufferLength + FIELD_OFFSET(DOT11_BSS_ENTRY, ucBuffer);
ASSERT (uRemainBytes >= uBssEntryBytes);
uRemainBytes -= uBssEntryBytes;
pbCurrPos += uBssEntryBytes;
if
(
MatchBssDescription
(
pIhvProfileParams,
pConnectivityProfile,
pSecurityProfile,
pBssEntry
)
)
{
(*pdwReasonCode) = L2_REASON_CODE_SUCCESS;
dwResult = ERROR_SUCCESS;
BAIL( );
}
}
// Since none of the BSS entries matched.
dwResult = ERROR_NO_MATCH;
error:
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
FreeIhvConnectivityProfile( &pConnectivityProfile );
FreeIhvSecurityProfile( &pSecurityProfile );
return dwResult;
}
//
// Function to validate profile.
//
DWORD
WINAPI
IhvValidateProfile
(
IN HANDLE hIhvExtAdapter,
IN PDOT11EXT_IHV_PROFILE_PARAMS pIhvProfileParams,
IN PDOT11EXT_IHV_CONNECTIVITY_PROFILE pIhvConnProfile,
IN PDOT11EXT_IHV_SECURITY_PROFILE pIhvSecProfile,
OUT PDWORD pdwReasonCode
)
{
DWORD dwResult = ERROR_SUCCESS;
PIHV_CONNECTIVITY_PROFILE pConnectivityProfile = NULL;
PIHV_SECURITY_PROFILE pSecurityProfile = NULL;
ASSERT( hIhvExtAdapter );
ASSERT( pdwReasonCode );
UNREFERENCED_PARAMETER( hIhvExtAdapter );
UNREFERENCED_PARAMETER( pIhvProfileParams );
(*pdwReasonCode) = L2_REASON_CODE_IHV_BAD_PROFILE;
// parse ihv connectivity profile.
dwResult =
GetIhvConnectivityProfile
(
pIhvConnProfile,
&pConnectivityProfile
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pConnectivityProfile );
// parse ihv security profile.
dwResult =
GetIhvSecurityProfile
(
pIhvSecProfile,
&pSecurityProfile
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pSecurityProfile );
(*pdwReasonCode) = L2_REASON_CODE_SUCCESS;
error:
FreeIhvConnectivityProfile( &pConnectivityProfile );
FreeIhvSecurityProfile( &pSecurityProfile );
return dwResult;
}
//
// This function does the actual preassociation work.
//
DWORD
WINAPI
DoPreAssociate
(
LPVOID pvPreAssociate
)
{
DWORD dwResult = ERROR_SUCCESS;
DWORD dwStatus = ERROR_SUCCESS;
PADAPTER_DETAILS pAdapterDetails = NULL;
PRE_ASSOCIATE_FUNCTION lpfnPreAssociate = NULL;
BOOL bLocked = FALSE;
DWORD dwReasonCode = L2_REASON_CODE_UNKNOWN;
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
ReferenceAdapterDetails
(
(HANDLE) pvPreAssociate,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
dwReasonCode = L2_REASON_CODE_IHV_BAD_PROFILE;
if ( !(pAdapterDetails->pConnectivityProfile && pAdapterDetails->pSecurityProfile) )
{
dwResult = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR( dwResult );
}
// choose pre-association function based on profile content.
if
(
( pAdapterDetails->pSecurityProfile->bUseFullSecurity ) ||
( pAdapterDetails->pSecurityProfile->bUseIhvConnectivityOnly )
)
{
if ( pAdapterDetails->pSecurityProfile->bUseIhvConnectivityOnly )
{
lpfnPreAssociate = DoIhvConnPreAssociate;
}
else if ( NULL == pAdapterDetails->pConnectivityProfile->pszParam2 )
{
lpfnPreAssociate = DoMissingKeyWepPreAssociate;
}
else if ( 0 == pAdapterDetails->pConnectivityProfile->pszParam2[0] )
{
lpfnPreAssociate = DoMissingKeyWepPreAssociate;
}
else
{
lpfnPreAssociate = DoWepPreAssociate;
}
}
else if
(
( !(pAdapterDetails->pSecurityProfile->bUseFullSecurity) ) &&
( IHVAuthV1 == pAdapterDetails->pSecurityProfile->AuthType )
)
{
lpfnPreAssociate = Do1xPreAssociate;
}
else
{
dwResult = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR( dwResult );
}
dwReasonCode = L2_REASON_CODE_UNKNOWN;
LeaveCriticalSection( &g_csSynch );
bLocked = FALSE;
ASSERT( lpfnPreAssociate );
ASSERT( !bLocked );
dwResult =
(lpfnPreAssociate)
(
pAdapterDetails,
&dwReasonCode
);
BAIL_ON_WIN32_ERROR( dwResult );
error:
if ( pAdapterDetails )
{
DerefenceAdapterDetails( (HANDLE) &(pAdapterDetails->Link) );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
if ( pAdapterDetails )
{
// call the completion function directly in this thread.
dwStatus =
(g_pDot11ExtApi->Dot11ExtPreAssociateCompletion)
(
pAdapterDetails->hDot11SvcHandle,
pAdapterDetails->hConnectSession,
dwReasonCode,
dwResult
);
}
if ( ERROR_SUCCESS != dwStatus )
{
// IHV specific logging can happen here.
}
return dwResult;
}
//
// Function to start the preassociation thread.
//
DWORD
WINAPI
IhvPerformPreAssociate
(
IN HANDLE hIhvExtAdapter,
IN HANDLE hConnectSession,
IN PDOT11EXT_IHV_PROFILE_PARAMS pIhvProfileParams,
IN PDOT11EXT_IHV_CONNECTIVITY_PROFILE pIhvConnProfile,
IN PDOT11EXT_IHV_SECURITY_PROFILE pIhvSecProfile,
IN PDOT11_BSS_LIST pConnectableBssid,
OUT PDWORD pdwReasonCode
)
{
DWORD dwResult = ERROR_SUCCESS;
DWORD dwStatus = ERROR_SUCCESS;
BOOL bLocked = FALSE;
PADAPTER_DETAILS pAdapterDetails = NULL;
ASSERT ( pIhvProfileParams );
ASSERT ( pdwReasonCode );
UNREFERENCED_PARAMETER( pIhvProfileParams );
UNREFERENCED_PARAMETER( pConnectableBssid );
(*pdwReasonCode) = L2_REASON_CODE_UNKNOWN;
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
ReferenceAdapterDetails
(
hIhvExtAdapter,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
if ( nic_state_initialized != pAdapterDetails->NicState )
{
dwResult = ERROR_INVALID_STATE;
BAIL_ON_WIN32_ERROR( dwResult );
}
// Connection specific parameters should be properly initialized.
if
(
( pAdapterDetails->pOnexData ) ||
( pAdapterDetails->hConnectSession ) ||
( pAdapterDetails->pPerformPostAssociateCompletionRoutine ) ||
( pAdapterDetails->pPerformPostAssociateRoutine ) ||
( pAdapterDetails->pStopPostAssociateRoutine )
)
{
dwResult = ERROR_INVALID_STATE;
BAIL_ON_WIN32_ERROR( dwResult );
}
(*pdwReasonCode) = L2_REASON_CODE_IHV_BAD_PROFILE;
// parse connectivity profile
dwResult =
GetIhvConnectivityProfile
(
pIhvConnProfile,
&(pAdapterDetails->pConnectivityProfile)
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails->pConnectivityProfile );
// parse security profile.
dwResult =
GetIhvSecurityProfile
(
pIhvSecProfile,
&(pAdapterDetails->pSecurityProfile)
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails->pSecurityProfile );
(*pdwReasonCode) = L2_REASON_CODE_UNKNOWN;
pAdapterDetails->NicState = nic_state_pre_assoc_started;
pAdapterDetails->hConnectSession = hConnectSession;
pAdapterDetails->bModifyCurrentProfile = FALSE;
// post a new thread to do the pre-association work.
dwResult =
StartNewProtectedThread
(
hIhvExtAdapter,
DoPreAssociate,
(LPVOID) hIhvExtAdapter
);
BAIL_ON_WIN32_ERROR( dwResult );
(*pdwReasonCode) = L2_REASON_CODE_SUCCESS;
error:
if ( ERROR_SUCCESS != dwResult )
{
dwStatus =
IhvAdapterReset
(
hIhvExtAdapter
);
ASSERT( ERROR_SUCCESS == dwStatus );
}
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// This function starts post associate routine
// in a separate thread and returns.
//
DWORD
WINAPI
IhvPerformPostAssociate
(
IN HANDLE hIhvExtAdapter,
IN HANDLE hSecuritySessionID,
IN PDOT11_PORT_STATE pPortState,
IN ULONG uDot11AssocParamsBytes,
IN PDOT11_ASSOCIATION_COMPLETION_PARAMETERS pDot11AssocParams
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
PPOST_ASSOC_DATA ppostAssocData = NULL;
PADAPTER_DETAILS pAdapterDetails = NULL;
ASSERT ( pDot11AssocParams );
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
ReferenceAdapterDetails
(
hIhvExtAdapter,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
if ( nic_state_pre_assoc_ended != pAdapterDetails->NicState )
{
dwResult = ERROR_INVALID_STATE;
BAIL_ON_WIN32_ERROR( dwResult );
}
pAdapterDetails->NicState = nic_state_post_assoc_started;
// is any post-association work required ??
if ( pAdapterDetails->pPerformPostAssociateRoutine )
{
dwResult =
( pAdapterDetails->pPerformPostAssociateRoutine )
(
pAdapterDetails,
hSecuritySessionID,
pPortState,
uDot11AssocParamsBytes,
pDot11AssocParams
);
BAIL_ON_WIN32_ERROR( dwResult );
}
// The post association completion thread may have been
// started by the perform post association routine for
// the current profile. Check if the completion thread
// needs to be started and start the routine.
if ( pAdapterDetails->pPerformPostAssociateCompletionRoutine )
{
ppostAssocData = (PPOST_ASSOC_DATA) PrivateMemoryAlloc( sizeof( POST_ASSOC_DATA ) );
if ( !ppostAssocData )
{
dwResult = ERROR_OUTOFMEMORY;
BAIL_ON_WIN32_ERROR( dwResult );
}
ppostAssocData->hIhvExtAdapter = hIhvExtAdapter;
ppostAssocData->hDot11SvcHandle = pAdapterDetails->hDot11SvcHandle;
ppostAssocData->hSecuritySessionId = hSecuritySessionID;
dwResult =
StartNewProtectedThread
(
hIhvExtAdapter,
pAdapterDetails->pPerformPostAssociateCompletionRoutine,
ppostAssocData
);
BAIL_ON_WIN32_ERROR( dwResult );
ppostAssocData = NULL;
}
error:
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
PrivateMemoryFree( ppostAssocData );
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// Reset the adapter to initialized state.
//
DWORD
WINAPI
IhvAdapterReset
(
IN HANDLE hIhvExtAdapter
)
{
DWORD dwResult = ERROR_SUCCESS;
PADAPTER_DETAILS pAdapterDetails = NULL;
DWORD dwRefCount = 0;
BOOL bOk = FALSE;
BOOL bLocked = FALSE;
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
ReferenceAdapterDetails
(
hIhvExtAdapter,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
for ( ;; )
{
ASSERT( bLocked );
dwRefCount = pAdapterDetails->dwRefCount;
if ( 2 == dwRefCount ) // For adapter init and self call.
{
break;
}
if ( nic_state_pre_assoc_started == pAdapterDetails->NicState )
{
pAdapterDetails->NicState = nic_state_pre_assoc_ended;
bOk = SetEvent( pAdapterDetails->hUIResponse );
ASSERT( bOk );
}
LeaveCriticalSection( &g_csSynch );
bLocked = FALSE;
Sleep( 100 );
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
}
ASSERT( bLocked );
// Resetting adapter.
pAdapterDetails->NicState = nic_state_initialized;
pAdapterDetails->hConnectSession = NULL;
pAdapterDetails->bModifyCurrentProfile = FALSE;
pAdapterDetails->pPerformPostAssociateCompletionRoutine = NULL;
pAdapterDetails->pPerformPostAssociateRoutine = NULL;
pAdapterDetails->pStopPostAssociateRoutine = NULL;
// freeing UI response data.
pAdapterDetails->dwResponseLen = 0;
PrivateMemoryFree( pAdapterDetails->pbResponse );
pAdapterDetails->pbResponse = NULL;
ZeroMemory( &(pAdapterDetails->currentGuidUIRequest), sizeof( GUID ) );
// freeing profile and onex data
FreeOnexData( &(pAdapterDetails->pOnexData) );
FreeIhvConnectivityProfile( &(pAdapterDetails->pConnectivityProfile) );
FreeIhvSecurityProfile( &(pAdapterDetails->pSecurityProfile) );
// unblocking UI thread.
bOk = ResetEvent( pAdapterDetails->hUIResponse );
if ( !bOk )
{
dwResult = GetLastError( );
BAIL_ON_WIN32_ERROR( dwResult );
}
error:
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
return dwResult;
}
//
// Stop post association. Get back
// to the state before post association started.
//
DWORD
WINAPI
IhvStopPostAssociate
(
IN HANDLE hIhvExtAdapter,
IN PDOT11_MAC_ADDRESS pPeer,
IN DOT11_ASSOC_STATUS dot11AssocStatus
)
{
DWORD dwResult = ERROR_SUCCESS;
PADAPTER_DETAILS pAdapterDetails = NULL;
DWORD dwRefCount = 0;
BOOL bLocked = FALSE;
// The dot11AssocStatus parameter can be compared with
// values DOT11_ASSOC_STATUS_* defined in the public
// headers.
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
ReferenceAdapterDetails
(
hIhvExtAdapter,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
for ( ;; )
{
ASSERT( bLocked );
dwRefCount = pAdapterDetails->dwRefCount;
if ( 2 == dwRefCount ) // For adapter init and self call.
{
break;
}
LeaveCriticalSection( &g_csSynch );
bLocked = FALSE;
Sleep( 100 );
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
}
ASSERT( bLocked );
if ( nic_state_initialized == pAdapterDetails->NicState )
{
// NO OP
// To handle the case when stop post associate
// call comes after adapter reset.
BAIL( );
}
// Call the post association routine - if there is any.
if ( pAdapterDetails->pStopPostAssociateRoutine )
{
dwResult =
(pAdapterDetails->pStopPostAssociateRoutine)
(
pAdapterDetails,
pPeer,
dot11AssocStatus
);
BAIL_ON_WIN32_ERROR( dwResult );
}
pAdapterDetails->NicState = nic_state_pre_assoc_ended;
error:
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
return dwResult;
}
//
// Process received packets.
//
DWORD
WINAPI
IhvReceivePacket
(
IN HANDLE hIhvExtAdapter,
IN DWORD dwInBufferSize,
IN LPVOID pvInBuffer
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
PADAPTER_DETAILS pAdapterDetails = NULL;
IHV_RECEIVE_PACKET_HANDLER lpfnReceivePacket = NULL;
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
ReferenceAdapterDetails
(
hIhvExtAdapter,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
if ( pAdapterDetails->pOnexData && pAdapterDetails->pOnexData->lpfnReceivePacket )
{
lpfnReceivePacket = pAdapterDetails->pOnexData->lpfnReceivePacket;
}
else
{
dwResult = ERROR_INVALID_STATE;
BAIL_ON_WIN32_ERROR( dwResult );
}
LeaveCriticalSection( &g_csSynch );
bLocked = FALSE;
ASSERT( lpfnReceivePacket );
// Call the receive packet routine.
dwResult =
(lpfnReceivePacket)
(
pAdapterDetails,
dwInBufferSize,
pvInBuffer
);
BAIL_ON_WIN32_ERROR( dwResult );
error:
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// Local copy of possible discovery profiles.
//
DOT11EXT_IHV_DISCOVERY_PROFILE
g_IhvDiscoveryProfiles[] =
{
// discovery profile 1.
{
{
L""
L"0"
L""
L""
},
// Use MS Onex.
{
L""
L"FALSE"
L"IHVAuthV1"
L"IHVCipher1"
L"0"
L""
L"",
TRUE
}
},
// discovery profile 2
{
// Open Wep
{
L""
L"0"
L""
L""
},
// Full IHV Security
{
L""
L"TRUE"
L"IHVAuthV1"
L"IHVCipher1"
L"0"
L""
L"",
FALSE
}
}
};
//
// Create discovery profiles.
//
DWORD
WINAPI
IhvCreateDiscoveryProfiles
(
IN HANDLE hIhvExtAdapter,
IN BOOL bInsecure,
IN PDOT11EXT_IHV_PROFILE_PARAMS pIhvProfileParams,
IN PDOT11_BSS_LIST pConnectableBssid,
OUT PDOT11EXT_IHV_DISCOVERY_PROFILE_LIST pIhvDiscoveryProfileList,
OUT PDWORD pdwReasonCode
)
{
DWORD dwResult = ERROR_SUCCESS;
DWORD dwIndex = 0;
DWORD dwIHVNumProfiles = ARRAY_LENGTH( g_IhvDiscoveryProfiles );
ASSERT( pIhvDiscoveryProfileList );
ASSERT( pdwReasonCode );
UNREFERENCED_PARAMETER( hIhvExtAdapter );
UNREFERENCED_PARAMETER( bInsecure );
UNREFERENCED_PARAMETER( pIhvProfileParams );
UNREFERENCED_PARAMETER( pConnectableBssid );
(*pdwReasonCode) = L2_REASON_CODE_IHV_OUTOFMEMORY;
// allocate buffer for the array.
dwResult =
(g_pDot11ExtApi->Dot11ExtAllocateBuffer)
(
dwIHVNumProfiles * sizeof( DOT11EXT_IHV_DISCOVERY_PROFILE ),
(LPVOID*) &(pIhvDiscoveryProfileList->pIhvDiscoveryProfiles)
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pIhvDiscoveryProfileList->pIhvDiscoveryProfiles );
ZeroMemory
(
pIhvDiscoveryProfileList->pIhvDiscoveryProfiles,
dwIHVNumProfiles * sizeof( DOT11EXT_IHV_DISCOVERY_PROFILE )
);
// prepare each discovery profile.
for ( dwIndex = 0; dwIndex < dwIHVNumProfiles; dwIndex++ )
{
dwResult =
CopyDiscoveryProfile
(
g_IhvDiscoveryProfiles + dwIndex,
pIhvDiscoveryProfileList->pIhvDiscoveryProfiles + dwIndex
);
BAIL_ON_WIN32_ERROR( dwResult );
}
pIhvDiscoveryProfileList->dwCount = dwIHVNumProfiles;
(*pdwReasonCode) = L2_REASON_CODE_SUCCESS;
error:
if ( ERROR_SUCCESS != dwResult )
{
if ( pIhvDiscoveryProfileList->pIhvDiscoveryProfiles )
{
for ( dwIndex = 0; dwIndex < dwIHVNumProfiles; dwIndex++ )
{
FreeDiscoveryProfile( pIhvDiscoveryProfileList->pIhvDiscoveryProfiles + dwIndex );
}
(g_pDot11ExtApi->Dot11ExtFreeBuffer)( pIhvDiscoveryProfileList->pIhvDiscoveryProfiles );
}
pIhvDiscoveryProfileList->dwCount = 0;
}
return dwResult;
}
//
// Process UI Response function.
//
DWORD
WINAPI
IhvProcessUIResponse
(
IN GUID guidUIRequest,
IN DWORD dwByteCount,
IN LPVOID pvResponseBuffer
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
PADAPTER_DETAILS pAdapterDetails = NULL;
HANDLE hIhvExtAdapter = NULL;
if ( !( dwByteCount && pvResponseBuffer ) )
{
dwResult = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR( dwResult );
}
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
// find the adapter from the UI response guid.
dwResult =
ReferenceAdapterDetailsByUIRequestGuid
(
&guidUIRequest,
&pAdapterDetails,
&hIhvExtAdapter
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
ZeroMemory( &(pAdapterDetails->currentGuidUIRequest), sizeof( GUID ) );
// Copy the UI response to the adapter data structure.
PrivateMemoryFree( pAdapterDetails->pbResponse );
pAdapterDetails->pbResponse = (BYTE*) PrivateMemoryAlloc( dwByteCount );
if ( !(pAdapterDetails->pbResponse) )
{
dwResult = ERROR_OUTOFMEMORY;
BAIL_ON_WIN32_ERROR(dwResult);
}
CopyMemory( pAdapterDetails->pbResponse, pvResponseBuffer, dwByteCount );
(pAdapterDetails->dwResponseLen) = dwByteCount;
// Waiting thread can pick up the response now.
SetEvent( pAdapterDetails->hUIResponse );
error:
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// Handler to clear memory after sending packet.
//
DWORD
WINAPI
IhvSendPacketCompletion
(
IN HANDLE hSendCompletion
)
{
// The sample is not sending any packets.
// So send packet completion should
// not be called.
ASSERTFAILURE();
// The freeing function used here
// should be the reverse of the function
// used to allocate memory before calling
// Send Packet.
PrivateMemoryFree( (LPVOID) hSendCompletion );
return ERROR_SUCCESS;
}
//
// Function to return UI Request on OS query.
//
DWORD
WINAPI
IhvQueryUIRequest
(
IN HANDLE hIhvExtAdapter,
IN DOT11EXT_IHV_CONNECTION_PHASE connectionPhase,
OUT PDOT11EXT_IHV_UI_REQUEST* ppIhvUIRequest
)
{
// This IHV handler is a post Vista extensibility point.
// It is currently unused.
ASSERTFAILURE();
UNREFERENCED_PARAMETER( hIhvExtAdapter );
UNREFERENCED_PARAMETER( connectionPhase );
UNREFERENCED_PARAMETER( ppIhvUIRequest );
return ERROR_CALL_NOT_IMPLEMENTED;
}
//
// Handler to receive the Onex Result.
//
DWORD
WINAPI
IhvOnexIndicateResult
(
IN HANDLE hIhvExtAdapter,
IN DOT11_MSONEX_RESULT msOneXResult,
IN PDOT11_MSONEX_RESULT_PARAMS pDot11MsOneXResultParams
)
{
DWORD dwResult = ERROR_SUCCESS;
BOOL bLocked = FALSE;
PADAPTER_DETAILS pAdapterDetails = NULL;
EnterCriticalSection( &g_csSynch );
bLocked = TRUE;
dwResult =
ReferenceAdapterDetails
(
hIhvExtAdapter,
&pAdapterDetails
);
BAIL_ON_WIN32_ERROR( dwResult );
ASSERT( pAdapterDetails );
// If indication of result is required.
if ( pAdapterDetails->pOnexData && pAdapterDetails->pOnexData->lpfnIndicateResult )
{
dwResult =
(pAdapterDetails->pOnexData->lpfnIndicateResult)
(
pAdapterDetails,
msOneXResult,
pDot11MsOneXResultParams
);
BAIL_ON_WIN32_ERROR( dwResult );
}
else
{
dwResult = ERROR_INVALID_STATE;
BAIL_ON_WIN32_ERROR( dwResult );
}
error:
if ( pAdapterDetails )
{
DerefenceAdapterDetails( hIhvExtAdapter );
}
if ( bLocked )
{
LeaveCriticalSection( &g_csSynch );
}
return dwResult;
}
//
// Handler to receive Control.
//
DWORD
WINAPI
IhvControl
(
IN HANDLE hIhvExtAdapter,
IN DWORD dwInBufferSize,
IN PBYTE pInBuffer,
IN DWORD dwOutBufferSize,
OUT PBYTE pOutBuffer,
OUT PDWORD pdwBytesReturned
)
{
// Sample does not demonstrate use of IHV control.
UNREFERENCED_PARAMETER( hIhvExtAdapter );
UNREFERENCED_PARAMETER( dwInBufferSize );
UNREFERENCED_PARAMETER( pInBuffer );
UNREFERENCED_PARAMETER( dwOutBufferSize );
UNREFERENCED_PARAMETER( pOutBuffer );
UNREFERENCED_PARAMETER( pdwBytesReturned );
return ERROR_SUCCESS;
}