行動寬頻 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 協助程式函式 GetlfEntry 和 GetlfEntry2 來傳送和接收位元組。
使用釘選解除封鎖 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();
}