summaryrefslogtreecommitdiff
path: root/network/wlan/ihvsample/ihvwep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'network/wlan/ihvsample/ihvwep.cpp')
-rw-r--r--network/wlan/ihvsample/ihvwep.cpp837
1 files changed, 837 insertions, 0 deletions
diff --git a/network/wlan/ihvsample/ihvwep.cpp b/network/wlan/ihvsample/ihvwep.cpp
new file mode 100644
index 00000000..3f4b1c6d
--- /dev/null
+++ b/network/wlan/ihvsample/ihvwep.cpp
@@ -0,0 +1,837 @@
+/*++
+
+Copyright (c) 2005 Microsoft Corporation
+
+Abstract:
+
+ Sample IHV Extensibility DLL to extend
+ 802.11 LWF driver for third party protocols.
+
+
+--*/
+
+#include "precomp.h"
+
+
+
+//
+// UI Request structure to
+// be parsed by IHV UI DLL.
+//
+typedef struct _IHV_UI_REQUEST
+{
+ CHAR szTitle [80];
+ CHAR szHelp [80];
+}
+IHV_UI_REQUEST, *PIHV_UI_REQUEST;
+
+
+DWORD
+ConvertHexCharToNibble
+(
+ CHAR chData,
+ BOOL bUpper,
+ PBYTE pbtData
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ BYTE btNibble = 0xF0;
+
+ ASSERT( pbtData );
+
+ if ( (chData >= '0') && (chData <= '9') )
+ {
+ btNibble = (BYTE) (chData - '0');
+ }
+ else if ( (chData >= 'a') && (chData <= 'f') )
+ {
+ btNibble = (BYTE) (chData - 'a') + 0xA;
+ }
+ else if ( (chData >= 'A') && (chData <= 'F') )
+ {
+ btNibble = (BYTE) (chData - 'A') + 0xA;
+ }
+ else
+ {
+ // Wrong type input
+ dwResult = ERROR_BAD_FORMAT;
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+ ASSERT( btNibble < 0xF0 );
+
+ if ( bUpper )
+ {
+ (*pbtData) = (*pbtData) & 0x0F;
+ (*pbtData) = (*pbtData) | (btNibble << 4);
+ }
+ else
+ {
+ (*pbtData) = (*pbtData) & 0xF0;
+ (*pbtData) = (*pbtData) | btNibble;
+ }
+
+error:
+ return dwResult;
+}
+
+
+// For a 13 byte key, user can choose to input upto 26 hex digits
+
+#define MAX_KEY_STRING_LENGTH 26
+
+#define MAX_RESPONSE_SIZE (( MAX_KEY_STRING_LENGTH + 1 ) * sizeof( WCHAR ) )
+
+//
+// The UI Response is a UNICODE string since
+// the UI module has just passed a BSTR to this
+// module. This UNICODE string needs to converted
+// to a key. Any IHV specific algorithm can be
+// used here.
+//
+
+DWORD
+ConvertStringToKey
+(
+ BYTE* pbKeyData,
+ DWORD* pdwKeyLen
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ HRESULT hr = S_OK;
+ CHAR szKey[ MAX_KEY_STRING_LENGTH + 2 ] = {0};
+ DWORD dwKeyStringLen = 0;
+ DWORD dwIndex = 0;
+
+
+ if
+ (
+ (!pbKeyData) ||
+ (!pdwKeyLen) ||
+ ( 0 == (*pdwKeyLen) ) ||
+ ( (*pdwKeyLen) % sizeof( WCHAR ) )
+ )
+ {
+ dwResult = ERROR_INVALID_PARAMETER;
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+ dwKeyStringLen = (DWORD) wcslen( (LPWSTR) pbKeyData );
+ if ( MAX_KEY_STRING_LENGTH < dwKeyStringLen )
+ {
+ dwResult = ERROR_BAD_FORMAT;
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+ // Converting the UNICODE string to
+ // ANSI string in scratch pad.
+ hr =
+ StringCchPrintfA
+ (
+ szKey,
+ MAX_KEY_STRING_LENGTH + 1,
+ "%S",
+ (WCHAR*) pbKeyData
+ );
+ BAIL_ON_FAILURE( hr );
+
+ ASSERT( dwKeyStringLen == (DWORD) strlen( szKey ));
+
+
+ if ( ( 5 == dwKeyStringLen ) || ( 13 == dwKeyStringLen ) )
+ {
+ // Copying the ANSI string back to original buffer.
+ hr =
+ StringCchPrintfA
+ (
+ (CHAR*) pbKeyData,
+ (*pdwKeyLen),
+ "%s",
+ szKey
+ );
+ BAIL_ON_FAILURE( hr );
+
+ // The strings are direct representations
+ // of the Wep Key and can be directly returned.
+ (*pdwKeyLen) = dwKeyStringLen;
+
+ TRACE_MESSAGE_VAL( "Received WEP key of length = ", (*pdwKeyLen) );
+
+ BAIL( );
+ }
+
+ if (( 10 != dwKeyStringLen ) && ( 26 != dwKeyStringLen ))
+ {
+ // Wrong length input
+ dwResult = ERROR_BAD_FORMAT;
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+ for( dwIndex = 0; dwIndex < (dwKeyStringLen / 2); dwIndex++ )
+ {
+ dwResult =
+ ConvertHexCharToNibble
+ (
+ szKey[ 2 * dwIndex ],
+ TRUE,
+ &(pbKeyData[ dwIndex ])
+ );
+ BAIL_ON_WIN32_ERROR( dwResult );
+
+ dwResult =
+ ConvertHexCharToNibble
+ (
+ szKey[ 1 + (2 * dwIndex) ],
+ FALSE,
+ &(pbKeyData[ dwIndex ])
+ );
+ BAIL_ON_WIN32_ERROR( dwResult );
+
+ }
+
+ (*pdwKeyLen) = dwKeyStringLen / 2;
+
+ TRACE_MESSAGE_VAL( "Received WEP key of length = ", (*pdwKeyLen) );
+
+error:
+ return WIN32_COMBINED_ERROR( dwResult, hr );
+}
+
+
+
+
+
+//
+// Defining UI help strings. In a realistic
+// implementation these values would be numbers
+// to be interpreted the IHV UI DLL that could
+// be converted to strings using resource files.
+//
+#define UI_TITLE_STRING "Title"
+#define UI_HELP_STRING "Help"
+
+
+
+
+// Send the UI request and wait for the UI response.
+DWORD
+SendUIRequestToReceiveKey
+(
+ PADAPTER_DETAILS pAdapterDetails,
+ DWORD* pdwKeyLen,
+ BYTE** ppbKeyData
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ DOT11EXT_IHV_UI_REQUEST uiRequest = {0};
+ PIHV_UI_REQUEST pIHVRequest = NULL;
+ CHAR szTitle[] = UI_TITLE_STRING;
+ CHAR szHelp[] = UI_HELP_STRING;
+ BOOL bLocked = FALSE;
+ HANDLE hUIResponse = NULL;
+
+
+
+ // CLSID of COM class that implements the UI page. In a real
+ // implementation this GUID could be dynamically obtained.
+ CLSID uiPageClsid =
+ {
+ /* 4A01F9F9-6012-4343-A8C4-10B5DF32672A */
+ 0x4A01F9F9,
+ 0x6012,
+ 0x4343,
+ {0xA8, 0xC4, 0x10, 0xB5, 0xDF, 0x32, 0x67, 0x2A}
+ };
+
+ ASSERT( pAdapterDetails );
+
+ // prepare the IHV request.
+ uiRequest.dwByteCount = sizeof(IHV_UI_REQUEST);
+ uiRequest.pvUIRequest = (BYTE*) PrivateMemoryAlloc( sizeof(IHV_UI_REQUEST) );
+ if ( !(uiRequest.pvUIRequest) )
+ {
+ dwResult = ERROR_OUTOFMEMORY;
+ BAIL( );
+ }
+
+ pIHVRequest = (IHV_UI_REQUEST*)uiRequest.pvUIRequest;
+
+
+ memcpy( pIHVRequest->szTitle , szTitle , sizeof(szTitle) );
+ memcpy( pIHVRequest->szHelp , szHelp , sizeof(szHelp) );
+
+ uiRequest.dwSessionId = WTSGetActiveConsoleSessionId( );
+ uiRequest.UIPageClsid = uiPageClsid;
+
+ // acquire the lock to register the request.
+ EnterCriticalSection( &g_csSynch );
+ bLocked = TRUE;
+
+ // create new request guid.
+ dwResult = UuidCreate( &(uiRequest.guidUIRequest) );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ // free the existing response.
+ PrivateMemoryFree( pAdapterDetails->pbResponse );
+ pAdapterDetails->pbResponse = NULL;
+
+ // register the guid.
+ pAdapterDetails->currentGuidUIRequest = uiRequest.guidUIRequest;
+
+ // Initializing the event this thread
+ // would be waiting on later.
+ ResetEvent( pAdapterDetails->hUIResponse );
+
+ hUIResponse = pAdapterDetails->hUIResponse;
+
+ // leave the lock since this thread needs
+ // to wait for the response.
+ LeaveCriticalSection( &g_csSynch );
+ bLocked = FALSE;
+
+
+ // send the request.
+ dwResult =
+ (g_pDot11ExtApi->Dot11ExtSendUIRequest)
+ (
+ pAdapterDetails->hDot11SvcHandle,
+ &uiRequest
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ TRACE_MESSAGE( "Sent UI request to receive key." );
+
+ // Waiting for UI response.
+ // This would be triggered
+ // off if no UI response
+ // is received.
+ dwResult =
+ WaitForSingleObject
+ (
+ hUIResponse,
+ 1000 * 60 * 5 // 5 minutes
+ );
+
+ // acquire the lock - required for both success and failure.
+ EnterCriticalSection( &g_csSynch );
+ bLocked = TRUE;
+
+ ZeroMemory( &(pAdapterDetails->currentGuidUIRequest), sizeof( GUID ) );
+
+ if ( WAIT_OBJECT_0 == dwResult )
+ {
+ dwResult = ERROR_SUCCESS;
+ }
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ if ( NULL == pAdapterDetails->pbResponse )
+ {
+ dwResult = ERROR_INVALID_STATE;
+ BAIL_ON_WIN32_ERROR(dwResult);
+ }
+
+
+ // At this point in the code a response
+ // has been received, and the thread
+ // has not been aborted.
+
+ (*ppbKeyData) = pAdapterDetails->pbResponse;
+ pAdapterDetails->pbResponse = NULL;
+
+ (*pdwKeyLen) = pAdapterDetails->dwResponseLen;
+
+
+ // Convert the Unicode string to ASCII.
+ dwResult =
+ ConvertStringToKey
+ (
+ *ppbKeyData,
+ pdwKeyLen
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ pAdapterDetails->bModifyCurrentProfile = TRUE;
+
+error:
+ if ( bLocked )
+ {
+ LeaveCriticalSection( &g_csSynch );
+ }
+ PrivateMemoryFree( uiRequest.pvUIRequest );
+ return dwResult;
+}
+
+
+//
+// Key index limits.
+//
+#define MIN_KEY_INDEX 0
+#define MAX_KEY_INDEX 3
+
+
+//
+// Perform Wep based pre-association once the key is known.
+//
+DWORD
+WINAPI
+DoWepPreAssociateCommon
+(
+ PADAPTER_DETAILS pAdapterDetails,
+ DWORD dwKeyLen,
+ BYTE* pbKeyData,
+ DWORD* pdwReasonCode
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ BOOL bLocked = FALSE;
+ LONG lIndex = 0;
+ PDOT11_CIPHER_DEFAULT_KEY_VALUE pKey = 0;
+ ULONG uLen = 0;
+
+ ASSERT( pAdapterDetails );
+ ASSERT( dwKeyLen );
+ ASSERT( pbKeyData );
+ ASSERT( pdwReasonCode );
+
+ // Reason code is set before making calls that could fail.
+ (*pdwReasonCode) = L2_REASON_CODE_IHV_OUTOFMEMORY;
+
+ uLen = FIELD_OFFSET(DOT11_CIPHER_DEFAULT_KEY_VALUE, ucKey) + dwKeyLen * sizeof(UCHAR);
+ pKey = (PDOT11_CIPHER_DEFAULT_KEY_VALUE) PrivateMemoryAlloc(uLen);
+ if (!pKey)
+ {
+ dwResult = ERROR_OUTOFMEMORY;
+ BAIL_ON_WIN32_ERROR(dwResult);
+ }
+ CopyMemory( &(pKey->ucKey), pbKeyData, dwKeyLen );
+
+ // Prepare the key.
+ pKey->AlgorithmId = DOT11_CIPHER_ALGO_WEP;
+ pKey->usKeyLength = (USHORT) dwKeyLen;
+ pKey->bStatic = TRUE;
+ pKey->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ pKey->Header.Revision = DOT11_CIPHER_DEFAULT_KEY_VALUE_REVISION_1;
+ pKey->Header.Size = sizeof(DOT11_CIPHER_DEFAULT_KEY_VALUE);
+
+ EnterCriticalSection( &g_csSynch );
+ bLocked = TRUE;
+
+ // Reason code is set before making calls that could fail.
+ (*pdwReasonCode) = L2_REASON_CODE_IHV_INVALID_STATE;
+
+ if ( nic_state_pre_assoc_started != pAdapterDetails->NicState )
+ {
+ dwResult = ERROR_INVALID_STATE;
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+ // Reason code is set before making calls that could fail.
+ (*pdwReasonCode) = L2_REASON_CODE_IHV_HARDWARE_FAILURE;
+
+ // plumb the settings and keys down.
+
+ TRACE_MESSAGE( "Setting Auth Algorithm." );
+ dwResult =
+ (g_pDot11ExtApi->Dot11ExtSetAuthAlgorithm)
+ (
+ pAdapterDetails->hDot11SvcHandle,
+ DOT11_AUTH_ALGO_80211_OPEN
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ TRACE_MESSAGE( "Setting Unicast cipher algorithm." );
+ dwResult =
+ (g_pDot11ExtApi->Dot11ExtSetUnicastCipherAlgorithm)
+ (
+ pAdapterDetails->hDot11SvcHandle,
+ DOT11_CIPHER_ALGO_WEP
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ TRACE_MESSAGE( "Setting exclude unencrypted flag." );
+ dwResult =
+ (g_pDot11ExtApi->Dot11ExtSetExcludeUnencrypted)
+ (
+ pAdapterDetails->hDot11SvcHandle,
+ TRUE
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ for ( lIndex = MAX_KEY_INDEX; lIndex >= MIN_KEY_INDEX; lIndex-- )
+ {
+ pKey->uKeyIndex = lIndex;
+
+ TRACE_MESSAGE( "Setting default key." );
+
+ dwResult =
+ (g_pDot11ExtApi->Dot11ExtSetDefaultKey)
+ (
+ pAdapterDetails->hDot11SvcHandle,
+ pKey,
+ DOT11_DIR_BOTH
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+ }
+
+ TRACE_MESSAGE( "Setting default key ID." );
+ dwResult =
+ (g_pDot11ExtApi->Dot11ExtSetDefaultKeyId)
+ (
+ pAdapterDetails->hDot11SvcHandle,
+ 0
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+
+ // Verified before, just after acquiring lock.
+ ASSERT( nic_state_pre_assoc_started == pAdapterDetails->NicState );
+
+ pAdapterDetails->NicState = nic_state_pre_assoc_ended;
+
+ // Reason code is set to SUCCESS.
+ (*pdwReasonCode) = L2_REASON_CODE_SUCCESS;
+
+ // register the post-association handlers with the adapter.
+
+ pAdapterDetails->pPerformPostAssociateCompletionRoutine = DoWepPostAssociate;
+ pAdapterDetails->pPerformPostAssociateRoutine = NULL;
+ pAdapterDetails->pStopPostAssociateRoutine = NULL;
+
+error:
+ if ( bLocked )
+ {
+ LeaveCriticalSection( &g_csSynch );
+ }
+ PrivateMemoryFree( pKey );
+ return dwResult;
+}
+
+
+// Pre-association when the profile does not have the key.
+DWORD
+WINAPI
+DoMissingKeyWepPreAssociate
+(
+ PADAPTER_DETAILS pAdapterDetails,
+ DWORD* pdwReasonCode
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ DWORD dwKeyLen = ERROR_SUCCESS;
+ BYTE* pbKeyData = NULL;
+
+ ASSERT( pAdapterDetails );
+ ASSERT( pdwReasonCode );
+
+ // Reason code is set before making calls that could fail.
+ (*pdwReasonCode) = L2_REASON_CODE_IHV_BAD_USER_KEY;
+
+ // Possible enhancement - try to call Dot11ExtGetProfileCustomUserData
+ // function in IHV Framework to see if the key is
+ // available there. Else, send UI Request.
+
+
+ // try to obtain the key through an UI request.
+ dwResult =
+ SendUIRequestToReceiveKey
+ (
+ pAdapterDetails,
+ &dwKeyLen,
+ &pbKeyData
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+ ASSERT ( pbKeyData );
+ ASSERT ( dwKeyLen );
+
+ // use the key for connection.
+ dwResult =
+ DoWepPreAssociateCommon
+ (
+ pAdapterDetails,
+ dwKeyLen,
+ pbKeyData,
+ pdwReasonCode
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+
+ // Possible enhancement - try to call Dot11ExtSetProfileCustomUserData
+ // to store the key if the key was obtained by a UI request.
+
+error:
+ PrivateMemoryFree( pbKeyData );
+ return dwResult;
+}
+
+
+
+
+
+
+
+// Pre-association when the profile does have the key.
+DWORD
+WINAPI
+DoWepPreAssociate
+(
+ PADAPTER_DETAILS pAdapterDetails,
+ DWORD* pdwReasonCode
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ BOOL bLocked = FALSE;
+ DWORD dwKeyLen = ERROR_SUCCESS;
+ CHAR szKey[MAX_RESPONSE_SIZE+1] = {0};
+
+ ASSERT( pAdapterDetails );
+ ASSERT( pdwReasonCode );
+
+ EnterCriticalSection( &g_csSynch );
+ bLocked = TRUE;
+
+ // Reason code is set before making calls that could fail.
+ (*pdwReasonCode) = L2_REASON_CODE_IHV_BAD_USER_KEY;
+
+ if
+ (
+ (!( pAdapterDetails->pConnectivityProfile )) ||
+ (!( pAdapterDetails->pConnectivityProfile->pszParam2 )) ||
+ ( 0 == pAdapterDetails->pConnectivityProfile->pszParam2[0] )
+ )
+ {
+ dwResult = ERROR_INVALID_STATE;
+ BAIL_ON_WIN32_ERROR(dwResult);
+ }
+
+ // Convert the profile string to a usable key.
+ dwKeyLen = (DWORD)wcslen( pAdapterDetails->pConnectivityProfile->pszParam2 );
+ dwKeyLen = sizeof(WCHAR) * ( 1 + dwKeyLen );
+
+ if ( dwKeyLen > sizeof( szKey ) )
+ {
+ dwResult = ERROR_BAD_PROFILE;
+ BAIL_ON_WIN32_ERROR(dwResult);
+ }
+
+
+ // Copy string.
+ CopyMemory
+ (
+ (BYTE*) szKey,
+ pAdapterDetails->pConnectivityProfile->pszParam2,
+ dwKeyLen
+ );
+
+ // Convert UNICODE to ASCII.
+ dwResult =
+ ConvertStringToKey
+ (
+ (BYTE*) szKey,
+ &dwKeyLen
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+ ASSERT ( dwKeyLen );
+
+
+ // Do pre-association with the key in the profile.
+ dwResult =
+ DoWepPreAssociateCommon
+ (
+ pAdapterDetails,
+ dwKeyLen,
+ (BYTE*) szKey,
+ pdwReasonCode
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+
+error:
+ if ( bLocked )
+ {
+ LeaveCriticalSection( &g_csSynch );
+ }
+ return dwResult;
+}
+
+
+
+
+extern
+DOT11EXT_IHV_DISCOVERY_PROFILE
+g_IhvDiscoveryProfiles[];
+
+
+//
+// This function is responsible for the post association
+// operations and completing the post association call
+// for WEP scenario.
+//
+DWORD
+WINAPI
+DoWepPostAssociate
+(
+ LPVOID pvPostAssociate
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ DWORD dwStatus = ERROR_SUCCESS;
+ DWORD dwReasonCode = L2_REASON_CODE_IHV_INVALID_STATE;
+ BOOL bLocked = FALSE;
+ PPOST_ASSOC_DATA ppostAssocData = (PPOST_ASSOC_DATA) pvPostAssociate;
+ PADAPTER_DETAILS pAdapterDetails = NULL;
+
+
+ ASSERT( ppostAssocData );
+
+ EnterCriticalSection( &g_csSynch );
+ bLocked = TRUE;
+
+ dwResult =
+ ReferenceAdapterDetails
+ (
+ ppostAssocData->hIhvExtAdapter,
+ &pAdapterDetails
+ );
+ BAIL_ON_WIN32_ERROR( dwResult );
+ ASSERT( pAdapterDetails );
+
+
+ if ( nic_state_post_assoc_started != pAdapterDetails->NicState )
+ {
+ dwResult = ERROR_INVALID_STATE;
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+ // This could be an appropriate place to modify the current profile
+
+ if ( pAdapterDetails->bModifyCurrentProfile )
+ {
+ pAdapterDetails->bModifyCurrentProfile = FALSE;
+
+ dwResult =
+ (g_pDot11ExtApi->Dot11ExtSetCurrentProfile)
+ (
+ pAdapterDetails->hDot11SvcHandle,
+ pAdapterDetails->hConnectSession,
+ &(g_IhvDiscoveryProfiles[1].IhvConnectivityProfile),
+ &(g_IhvDiscoveryProfiles[1].IhvSecurityProfile)
+ );
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+
+ // In wep connection case, function only changes the adapter state.
+ pAdapterDetails->NicState = nic_state_post_assoc_ended;
+
+
+ // Reason Code is set to success.
+ dwReasonCode = L2_REASON_CODE_SUCCESS;
+
+error:
+ if ( pAdapterDetails )
+ {
+ DerefenceAdapterDetails( ppostAssocData->hIhvExtAdapter );
+ }
+ if ( bLocked )
+ {
+ LeaveCriticalSection( &g_csSynch );
+ }
+
+ // call completion function.
+ dwStatus =
+ (g_pDot11ExtApi->Dot11ExtPostAssociateCompletion)
+ (
+ ppostAssocData->hDot11SvcHandle,
+ ppostAssocData->hSecuritySessionId,
+ NULL,
+ dwReasonCode,
+ dwResult
+ );
+ if ( ERROR_SUCCESS != dwStatus )
+ {
+ // IHV specific logging can happen here.
+ }
+ PrivateMemoryFree( ppostAssocData );
+ return dwResult;
+}
+
+
+// no op function for preassociation when
+// ihv is used only for connectivity. in a
+// realistic implementation there would probably
+// be calls to Dot11ExtNicSpecificExtension
+// in this function to prepare the driver for
+// additional connectivity settings.
+DWORD
+WINAPI
+DoIhvConnPreAssociate
+(
+ PADAPTER_DETAILS pAdapterDetails,
+ DWORD* pdwReasonCode
+)
+{
+ DWORD dwResult = ERROR_SUCCESS;
+ DWORD dwKeyLen = 0;
+ PBYTE pbKeyData = NULL;
+ BOOL bLocked = FALSE;
+
+ ASSERT( pAdapterDetails );
+ ASSERT( pdwReasonCode );
+
+ // try to send UI request to obtain some data that could be useful here.
+ // the sample does not really use the data.
+ dwResult =
+ SendUIRequestToReceiveKey
+ (
+ pAdapterDetails,
+ &dwKeyLen,
+ &pbKeyData
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+ ASSERT ( pbKeyData );
+
+ PrivateMemoryFree( pbKeyData );
+ pbKeyData = NULL;
+
+ // try to send UI request to obtain some data that could be useful here.
+ // the sample does not really use the data.
+ dwResult =
+ SendUIRequestToReceiveKey
+ (
+ pAdapterDetails,
+ &dwKeyLen,
+ &pbKeyData
+ );
+ BAIL_ON_WIN32_ERROR(dwResult);
+ ASSERT ( pbKeyData );
+
+
+ EnterCriticalSection( &g_csSynch );
+ bLocked = TRUE;
+
+ // Reason code is set before making calls that could fail.
+ (*pdwReasonCode) = L2_REASON_CODE_IHV_INVALID_STATE;
+
+ if ( nic_state_pre_assoc_started != pAdapterDetails->NicState )
+ {
+ dwResult = ERROR_INVALID_STATE;
+ BAIL_ON_WIN32_ERROR( dwResult );
+ }
+
+ pAdapterDetails->NicState = nic_state_pre_assoc_ended;
+
+ // Reason code is set to SUCCESS.
+ (*pdwReasonCode) = L2_REASON_CODE_SUCCESS;
+
+ pAdapterDetails->pPerformPostAssociateCompletionRoutine = NULL;
+ pAdapterDetails->pPerformPostAssociateRoutine = NULL;
+ pAdapterDetails->pStopPostAssociateRoutine = NULL;
+
+error:
+ if ( bLocked )
+ {
+ LeaveCriticalSection( &g_csSynch );
+ }
+ PrivateMemoryFree( pbKeyData );
+ return dwResult;
+}