// free security profile. VOID FreeIhvSecurityProfile ( PIHV_SECURITY_PROFILE* ppSecurityProfile ) { if ( ppSecurityProfile && (*ppSecurityProfile) ) { PrivateMemoryFree( (*ppSecurityProfile)->pszParam2 ); PrivateMemoryFree( (*ppSecurityProfile) ); (*ppSecurityProfile) = NULL; } }
VOID FreeIhvConnectivityProfile ( PIHV_CONNECTIVITY_PROFILE* ppConnectivityProfile ) { if ( ppConnectivityProfile && (*ppConnectivityProfile) ) { PrivateMemoryFree( (*ppConnectivityProfile)->pszParam2 ); PrivateMemoryFree( (*ppConnectivityProfile) ); (*ppConnectivityProfile) = NULL; } }
// 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; }
// // Calls the accessors to build native data. // HRESULT CIhvSecurityProfile::GetNativeData ( LPVOID* ppvData ) { HRESULT hr = S_OK; PIHV_SECURITY_PROFILE pIhvProfile = NULL; BSTR bstrParam2 = NULL; if ( !ppvData ) { hr = E_INVALIDARG; BAIL_ON_FAILURE( hr ); } pIhvProfile = (PIHV_SECURITY_PROFILE) PrivateMemoryAlloc( sizeof( IHV_SECURITY_PROFILE ) ); if ( !pIhvProfile ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE( hr ); } pIhvProfile->bUseIhvConnectivityOnly = ( m_pRootNode == NULL ); // Ignoring errors since structure is already // populated with defaults. hr = GetFullSecurityFlag ( &(pIhvProfile->bUseFullSecurity) ); hr = GetAuthType ( &(pIhvProfile->AuthType) ); hr = GetCipherType ( &(pIhvProfile->CipherType) ); hr = GetParam1 ( &(pIhvProfile->dwParam1) ); hr = GetParam2 ( &bstrParam2 ); BAIL_ON_FAILURE( hr ); if ( NULL == bstrParam2 ) { hr = E_POINTER; BAIL_ON_FAILURE( hr ); } hr = Wstr2Wstr ( bstrParam2, &(pIhvProfile->pszParam2) ); // Consuming earlier failures. hr = S_OK; // Transfering local cache to OUT parameter. (*ppvData) = pIhvProfile; pIhvProfile = NULL; error: if ( pIhvProfile ) { PrivateMemoryFree( pIhvProfile->pszParam2 ); // NULL Safe. PrivateMemoryFree( pIhvProfile ); } SYS_FREE_STRING( bstrParam2 ); return hr; }
// 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; }
// // 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; }
// // 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; }
// 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; }
// // Calls the accessors to build native data. // HRESULT CIhvConnectivityProfile::GetNativeData ( LPVOID* ppvData ) { HRESULT hr = S_OK; PIHV_CONNECTIVITY_PROFILE pIhvProfile = NULL; BSTR bstrParam2 = NULL; if ( !ppvData ) { hr = E_INVALIDARG; BAIL_ON_FAILURE( hr ); } pIhvProfile = (PIHV_CONNECTIVITY_PROFILE) PrivateMemoryAlloc( sizeof( IHV_CONNECTIVITY_PROFILE ) ); if ( !pIhvProfile ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE( hr ); } // Ignoring errors since structure is already // populated with defaults. hr = GetParam2 ( &bstrParam2 ); hr = Wstr2Wstr ( bstrParam2, &(pIhvProfile->pszParam2) ); hr = GetParam1 ( &(pIhvProfile->dwParam1) ); // Consuming earlier failures. hr = S_OK; // Transfering local cache to OUT parameter. (*ppvData) = pIhvProfile; pIhvProfile = NULL; error: if ( pIhvProfile ) { PrivateMemoryFree( pIhvProfile->pszParam2 ); // NULL Safe. PrivateMemoryFree( pIhvProfile ); } SYS_FREE_STRING( bstrParam2 ); return hr; }