共用方式為


行動寬頻 API 最佳做法

使用行動寬頻 API 時,應該使用下列一組最佳做法,以達到最佳效能。

不要快取功能物件

功能物件,例如 IMbnInterface 和其他物件,都是使用對應管理員物件的列舉方法,從 IMbnInterfaceManager等管理員物件取得。 請勿快取這些功能物件,因為快取的功能物件包含過時的資料。 在這些功能物件上執行的同步作業會傳回相同的資料,直到再次取得功能物件為止。

相反地,請快取管理員物件,並使用對應管理員物件上的列舉方法再次取得功能物件,以取得最新的資料。

下列程式碼範例示範快取管理員物件的正確方式。

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

處理所有通知

遵循並處理所有通知,即使應用程式未觸發這些通知也一樣。 這需要讓 UI 與裝置的實際狀態保持同步。

電腦上可以有多個連線管理員執行。 Windows 7 所提供的原生檢視可用網路介面 UI 是連線管理員。 任何其他連接管理員都必須回應所有通知,才能保持同步 Windows 原生 UI。 使用者可以選擇在其中一個連線管理員上執行某些作業,這可能會導致行動寬頻裝置的狀態變更。 不過,其他連線管理員必須保持更新狀態,才能正確指出裝置的修改狀態。

例如,使用其中一個連線管理員執行連線,將會將裝置的狀態從可用的變更為已連線。 未起始此動作的連接管理員應該可以看到這項變更。 所有具有 UI 的連線管理員都表示裝置的線上狀態,必須接聽及處理線上狀態通知,才能正確更新其使用者介面。

傳送和接收位元組

使用 IP 協助程式函式 GetlfEntryGetlfEntry2 來傳送和接收位元組。

使用釘選解除封鎖 API

呼叫用戶端應用程式必須提高許可權,才能成功叫用 IMbnPin::Unblock。 此方法是唯一需要系統管理員或 NCO 許可權的行動寬頻 API 部分。

使用 SafeArrays

  • 在存取 SafeArray 中的任何元素之前,請使用 ZeroMemory () 。

  • 請勿檢查 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();
}