Поделиться через


Рекомендации по API мобильной широкополосной связи

При работе с API мобильной широкополосной связи следует использовать приведенный ниже набор рекомендаций для достижения максимальной производительности.

Не кэшировать функциональные объекты

Функциональные объекты, такие как IMbnInterface и другие, получаются из управляющих объектов, таких как IMbnInterfaceManager, с помощью метода перечисления соответствующего объекта диспетчера. Не кэшируйте эти функциональные объекты, так как кэшированные функциональные объекты содержат устаревшие данные. Синхронные операции, выполняемые с этими функциональными объектами, будут возвращать те же данные, пока функциональные объекты не будут получены снова.

Вместо этого кэшируйте объекты диспетчера и получите функциональные объекты из объекта manager с помощью метода перечисления соответствующего объекта диспетчера, чтобы получить последние данные.

В следующем примере кода демонстрируется правильный способ кэширования объектов диспетчера.

#include <atlbase.h>
#include "mbnapi.h"
#include <tchar.h>

int main()
{
    HRESULT hr = E_FAIL;
    int returnVal = 0;

    do
    {
        hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);    
        if (FAILED(hr))
        {
            returnVal = hr; 
            break;
        }

        CComPtr<IMbnInterfaceManager>  g_InterfaceMgr = NULL;

        //Do the below once(cache the manager objects)
        hr = CoCreateInstance(CLSID_MbnInterfaceManager,
            NULL, 
            CLSCTX_ALL, 
            IID_IMbnInterfaceManager, 
            (void**)&g_InterfaceMgr);
        if (FAILED(hr))
        {
            returnVal = hr; 
            break;
        }

        SAFEARRAY *psa = NULL;

        //Do the below each time(do not cache functional objects)
        hr = g_InterfaceMgr->GetInterfaces(&psa);
        if (FAILED(hr))
        {
            returnVal = hr; 
            break;
        }

        LONG lLower;
        LONG lUpper;

        hr = SafeArrayGetLBound(psa, 1, &lLower);
        if (FAILED(hr))
        {
            returnVal = hr; 
            break;
        }

        hr = SafeArrayGetUBound(psa, 1, &lUpper);
        if (FAILED(hr))
        {
            returnVal = hr; 
            break;
        }

        CComPtr<IMbnInterface>  pInf = NULL;
        MBN_READY_STATE readyState;

        for (LONG l = lLower; l <= lUpper; l++)
        {
            hr = SafeArrayGetElement(psa, &l, (void*)(&pInf));
            if (FAILED(hr))
            {
                returnVal = hr; 
                break;
            }

            hr = pInf->GetReadyState(&readyState);
            if (FAILED(hr))
            {
                returnVal = hr; 
                break;
            }

            _tprintf(_T("Ready State = %d"), readyState); 
        }

        if (FAILED(hr))
        {
            break;
        }
    } while (FALSE);


    CoUninitialize();
    return returnVal;
}

Обработка всех уведомлений

Следите за всеми уведомлениями и обрабатывайте их, даже если они не активируются приложением. Это необходимо для синхронизации пользовательского интерфейса с фактическим состоянием устройства.

На компьютере может быть запущено несколько диспетчеров соединений. Собственный пользовательский интерфейс представления доступного сетевого интерфейса, предоставляемый Windows 7, является диспетчером подключений. Все другие диспетчеры соединений должны реагировать на все уведомления, чтобы оставаться в состоянии синхронизации собственного пользовательского интерфейса Windows. Пользователь может выбрать выполнение некоторых операций с одним из диспетчеров соединений, что может привести к изменению состояния устройства мобильной широкополосной связи. Однако другие диспетчеры соединений должны обновляться, чтобы правильно указать измененное состояние устройства.

Например, при выполнении подключения с помощью одного из диспетчеров подключений состояние устройства изменится с доступного на подключенное. Это изменение должно быть видно диспетчерам соединений, которые не инициировали это действие. Все диспетчеры соединений с пользовательским интерфейсом, указывающим состояние подключения устройства, должны прослушивать и обрабатывать уведомления о состоянии подключения, чтобы правильно обновить пользовательский интерфейс.

Отправка и получение байтов

Используйте вспомогательные функции IP GetlfEntry и GetlfEntry2 для отправки и получения байтов.

Использование API разблокировки контактов

Вызывающее клиентское приложение должно быть повышено, чтобы успешно вызвать IMbnPin::Unblock. Этот метод является единственной частью API мобильной широкополосной связи, для которой требуются права администратора или NCO.

Работа с SafeArrays

  • Используйте ZeroMemory() перед доступом к любым элементам в SafeArray.

  • Не проверка индексы SafeArray. Они могут быть отрицательными.

В следующем примере кода показано, как правильно обрабатывать SafeArray.

#include <atlbase.h>
#include "mbnapi.h"

void CreateVisibleProviderList(LPCWSTR interfaceID)
{
    CComPtr<IMbnInterfaceManager>  g_InterfaceMgr = NULL;
    SAFEARRAY *visibleProviders = NULL;
    long visibleLower = 0;
    long visibleUpper = 0;
    MBN_PROVIDER *pProvider = NULL;
    CComPtr<IMbnInterface> pInterface = NULL;

    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

    if (FAILED(hr))
    {
        goto ERROR_0;
    }

    hr = CoCreateInstance(CLSID_MbnInterfaceManager,
            NULL, 
            CLSCTX_ALL, 
            IID_IMbnInterfaceManager, 
            (void**)&g_InterfaceMgr);
    
    if (FAILED(hr))
    {
        goto ERROR_0;
    }

    hr = g_InterfaceMgr->GetInterface(interfaceID, & pInterface);
    if (FAILED(hr)) 
    {
        goto ERROR_0;
    }

    ULONG age;

    hr = pInterface->GetVisibleProviders(&age, &visibleProviders);
    if (FAILED(hr)) 
    {
        goto ERROR_0;
    }

    hr = SafeArrayGetLBound(visibleProviders, 1, &visibleLower);
    if (FAILED(hr)) 
    {
        goto ERROR_0;
    }

    hr = SafeArrayGetUBound(visibleProviders, 1, &visibleUpper);
    if (FAILED(hr)) 
    {
        goto ERROR_0;
    }

    //don't check on the indexes of safearray to be positive
    if (visibleLower > visibleUpper) 
    {
        // There are no visible providers in this case.
        hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
        goto ERROR_0;
    }

    DWORD size = (visibleUpper - visibleLower + 1) * sizeof(BOOL);
    DBG_UNREFERENCED_LOCAL_VARIABLE(size); 
    
    pProvider = (MBN_PROVIDER *)CoTaskMemAlloc(sizeof(MBN_PROVIDER));
    if (!pProvider) 
    {
        hr = E_OUTOFMEMORY;
        goto ERROR_0;
    }

    for (LONG vIndex = visibleLower; vIndex <= visibleUpper; vIndex++) 
    {
        //use zeromemory before accessing any elements in a safearray
        ZeroMemory(pProvider, sizeof(MBN_PROVIDER));
        hr = SafeArrayGetElement(visibleProviders, &vIndex, (void *)pProvider);
        if (FAILED(hr)) 
        {
            continue;
        }
    }

ERROR_0:
    if (visibleProviders) 
    {
        SafeArrayDestroy(visibleProviders);
        visibleProviders = NULL;
    }

    CoUninitialize();
}