static AJ_Status DoConnectWifi(AJOBS_Info* connectInfo)
{
    AJ_Status status = AJ_OK;
    AJ_WiFiSecurityType secType = AJ_WIFI_SECURITY_NONE;
    AJ_WiFiCipherType cipherType = AJ_WIFI_CIPHER_NONE;
    AJOBS_AuthType fallback = AJOBS_AUTH_TYPE_OPEN;
    AJOBS_AuthType fallbackUntil = AJOBS_AUTH_TYPE_OPEN;
    uint8_t retries = 0;
    AJ_WiFiConnectState wifiConnectState;

    AJ_InfoPrintf(("Attempting to connect to %s with passcode=%s and auth=%d\n", connectInfo->ssid, connectInfo->pc, connectInfo->authType));

    switch (connectInfo->authType) {
    case AJOBS_AUTH_TYPE_ANY:
        if (strlen(connectInfo->pc) == 0) {
            break;
        }
        fallback = AJOBS_AUTH_TYPE_WPA2_CCMP;
        fallbackUntil = AJOBS_AUTH_TYPE_OPEN;
        break;

    case AJOBS_AUTH_TYPE_WPA_AUTO:
        if (strlen(connectInfo->pc) == 0) {
            break;
        }
        fallback = AJOBS_AUTH_TYPE_WPA_CCMP;
        fallbackUntil = AJOBS_AUTH_TYPE_WPA_TKIP;
        break;

    case AJOBS_AUTH_TYPE_WPA2_AUTO:
        if (strlen(connectInfo->pc) == 0) {
            break;
        }
        fallback = AJOBS_AUTH_TYPE_WPA2_CCMP;
        fallbackUntil = AJOBS_AUTH_TYPE_WPA2_TKIP;
        break;

    default:
        fallback = connectInfo->authType;
    }

    secType = GetSecType(fallback);
    cipherType = GetCipherType(fallback);
    AJ_InfoPrintf(("Trying to connect with auth=%d (secType=%d, cipherType=%d)\n", fallback, secType, cipherType));

    while (1) {
        if (connectInfo->state == AJOBS_STATE_CONFIGURED_NOT_VALIDATED) {
            connectInfo->state = AJOBS_STATE_CONFIGURED_VALIDATING;
        }

        uint8_t raw[(AJOBS_PASSCODE_MAX_LENGTH / 2) + 1];
        char* password = connectInfo->pc;
        if (AJ_WIFI_CIPHER_WEP != cipherType) {
            size_t hexLen = strlen(connectInfo->pc);
            AJ_HexToRaw(connectInfo->pc, hexLen, raw, (AJOBS_PASSCODE_MAX_LENGTH / 2) + 1);
            password = (char*)raw;
            password[hexLen / 2] = '\0';
        }

        status = AJ_ConnectWiFi(connectInfo->ssid, secType, cipherType, password);
        AJ_InfoPrintf(("AJ_ConnectWifi returned %s\n", AJ_StatusText(status)));

        wifiConnectState = AJ_GetWifiConnectState();

        // Set last error and state
        if ((status == AJ_OK) /* (wifiConnectState == AJ_WIFI_CONNECT_OK)*/) {
            obLastError.code = AJOBS_STATE_LAST_ERROR_VALIDATED;
            obLastError.message[0] = '\0';
            obState = AJOBS_STATE_CONFIGURED_VALIDATED;
            connectInfo->authType = fallback;
        } else if ((status == AJ_ERR_CONNECT) /* (wifiConnectState == AJ_WIFI_CONNECT_FAILED)*/) {
            obLastError.code = AJOBS_STATE_LAST_ERROR_UNREACHABLE;
            strncpy(obLastError.message, "Network unreachable!", AJOBS_ERROR_MESSAGE_LEN);
            if (connectInfo->state == AJOBS_STATE_CONFIGURED_VALIDATED || connectInfo->state == AJOBS_STATE_CONFIGURED_RETRY) {
                obState = AJOBS_STATE_CONFIGURED_RETRY;
            } else {
                obState = AJOBS_STATE_CONFIGURED_ERROR;
            }
        } else if ((status == AJ_ERR_SECURITY) /* (wifiConnectState == AJ_WIFI_AUTH_FAILED)*/) {
            obLastError.code = AJOBS_STATE_LAST_ERROR_UNAUTHORIZED;
            strncpy(obLastError.message, "Authorization failed!", AJOBS_ERROR_MESSAGE_LEN);
            if (connectInfo->state == AJOBS_STATE_CONFIGURED_VALIDATED || connectInfo->state == AJOBS_STATE_CONFIGURED_RETRY) {
                obState = AJOBS_STATE_CONFIGURED_RETRY;
            } else {
                obState = AJOBS_STATE_CONFIGURED_ERROR;
            }
        } else if (status == AJ_ERR_DRIVER) {
            obLastError.code = AJOBS_STATE_LAST_ERROR_ERROR_MESSAGE;
            strncpy(obLastError.message, "Driver error", AJOBS_ERROR_MESSAGE_LEN);
            obState = AJOBS_STATE_CONFIGURED_ERROR;
        } else if (status == AJ_ERR_DHCP) {
            obLastError.code = AJOBS_STATE_LAST_ERROR_ERROR_MESSAGE;
            strncpy(obLastError.message, "Failed to establish IP!", AJOBS_ERROR_MESSAGE_LEN);
            if (connectInfo->state == AJOBS_STATE_CONFIGURED_VALIDATED || connectInfo->state == AJOBS_STATE_CONFIGURED_RETRY) {
                obState = AJOBS_STATE_CONFIGURED_RETRY;
            } else {
                obState = AJOBS_STATE_CONFIGURED_ERROR;
            }
        } else {
            obLastError.code = AJOBS_STATE_LAST_ERROR_ERROR_MESSAGE;
            strncpy(obLastError.message, "Failed to connect! Unexpected error", AJOBS_ERROR_MESSAGE_LEN);
            obState = AJOBS_STATE_CONFIGURED_ERROR;
        }

        if (obState == AJOBS_STATE_CONFIGURED_VALIDATED) {
            break;
        }
        AJ_WarnPrintf(("Warning - DoConnectWifi wifiConnectState = %s\n", AJ_WiFiConnectStateText(wifiConnectState)));
        AJ_WarnPrintf(("Last error set to \"%s\" (code=%d)\n", obLastError.message, obLastError.code));

        if (obState == AJOBS_STATE_CONFIGURED_ERROR || obState == AJOBS_STATE_CONFIGURED_RETRY) {
            if (retries++ >= obSettings->AJOBS_MAX_RETRIES) {
                if (obState == AJOBS_STATE_CONFIGURED_ERROR && connectInfo->state == AJOBS_STATE_CONFIGURED_VALIDATING) {
                    if (connectInfo->authType < 0 && fallback > fallbackUntil) {
                        obLastError.code = AJOBS_STATE_LAST_ERROR_UNSUPPORTED_PROTOCOL;
                        strncpy(obLastError.message, "Unsupported protocol", AJOBS_ERROR_MESSAGE_LEN);
                        fallback--; // Try next authentication protocol
                        secType = GetSecType(fallback);
                        cipherType = GetCipherType(fallback);
                        retries = 0;
                        AJ_InfoPrintf(("Trying to connect with fallback auth=%d (secType=%d, cipherType=%d)\n", fallback, secType, cipherType));
                        continue;
                    }
                }
                break;
            }
            AJ_InfoPrintf(("Retry number %d out of %d\n", retries, obSettings->AJOBS_MAX_RETRIES));
        }
    }

    connectInfo->state = obState;
    status = (*obWriteInfo)(connectInfo);
    return status;
}
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) malloc( sizeof( IHV_SECURITY_PROFILE ) );
    if ( !pIhvProfile )
    {
        hr = E_OUTOFMEMORY;
        BAIL_ON_FAILURE( hr );
    }
    ZeroMemory( pIhvProfile, sizeof( IHV_SECURITY_PROFILE ) );

    hr =
    GetFullSecurityFlag
    (
        &(pIhvProfile->bUseFullSecurity)
    );
    BAIL_ON_FAILURE( hr );

    hr =
    GetAuthType
    (
        &(pIhvProfile->AuthType)
    );
    BAIL_ON_FAILURE( hr );

    hr =
    GetCipherType
    (
        &(pIhvProfile->CipherType)
    );
    BAIL_ON_FAILURE( hr );

    hr =
    GetParamDWORD
    (
        &(pIhvProfile->dwParam1)
    );
    BAIL_ON_FAILURE( hr );

    hr =
    GetParamBSTR
    (
        &bstrParam2
    );
    BAIL_ON_FAILURE( hr );

    if ( NULL == bstrParam2 ) {
        hr = E_POINTER;
        BAIL_ON_FAILURE( hr );
    }

    hr =
    Wstr2Wstr
    (
        bstrParam2,
        &(pIhvProfile->pszParam2)
    );
    BAIL_ON_FAILURE( hr );

    // Transfering local cache to OUT parameter.
    (*ppvData) = pIhvProfile;
    pIhvProfile = NULL;

error:
    if ( pIhvProfile )
    {
        free( pIhvProfile->pszParam2 ); // NULL Safe.
        free( pIhvProfile );
    }
    SYS_FREE_STRING( bstrParam2 );
    return hr;

}
//
// 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;
}