Práticas recomendadas da API de Banda Larga Móvel
Ao trabalhar com a API de Banda Larga Móvel, o seguinte conjunto de práticas recomendadas deve ser usado para obter o melhor desempenho possível.
Não armazenar objetos funcionais em cache
Objetos funcionais, como IMbnInterface e outros, são obtidos de objetos de gerente, como IMbnInterfaceManager, usando o método de enumeração no objeto de gerente correspondente. Não armazene esses objetos funcionais em cache, pois os objetos funcionais armazenados em cache contêm dados obsoletos. As operações síncronas executadas nesses objetos funcionais retornarão os mesmos dados até que os objetos funcionais sejam obtidos novamente.
Em vez disso, armazene em cache os objetos do gerenciador e obtenha os objetos funcionais do objeto manager usando o método de enumeração no objeto gerenciador correspondente novamente para obter os dados mais recentes.
O exemplo de código a seguir demonstra a maneira adequada de armazenar objetos do gerenciador de cache.
#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;
}
Manipular todas as notificações
Siga e manipule todas as notificações, mesmo que elas não sejam disparadas pelo aplicativo. Isso é necessário para manter a interface do usuário em sincronia com o estado real do dispositivo.
Pode haver mais de um gerenciador de conexões em execução em um computador. A interface do usuário do Adaptador de Rede Disponível de Exibição nativa fornecida pelo Windows 7 é um gerenciador de conexões. Qualquer outro gerenciador de conexões precisa responder a todas as notificações para permanecer em sincronia com a interface do usuário nativa do Windows. Um usuário pode optar por executar alguma operação em um dos gerenciadores de conexões, o que pode resultar em uma alteração de estado do dispositivo de Banda Larga Móvel. No entanto, outros gerenciadores de conexões precisam permanecer atualizados para indicar corretamente o estado modificado do dispositivo.
Por exemplo, executar uma conexão usando um dos gerenciadores de conexões alterará o estado do dispositivo de disponível para conectado. Essa alteração deve estar visível para os gerenciadores de conexões que não iniciaram essa ação. Todos os gerenciadores de conexões que têm interface do usuário que indica o estado de conexão do dispositivo precisam escutar e lidar com as notificações de estado de conexão para atualizar corretamente a interface do usuário.
Envio e recebimento de bytes
Use as funções auxiliares de IP GetlfEntry e GetlfEntry2 para enviar e receber bytes.
Usando a API de desbloqueio de pinos
Um aplicativo cliente de chamada deve ser elevado para invocar IMbnPin::Unblock com êxito. Esse método é a única parte da API de Banda Larga Móvel que requer privilégios de administrador ou NCO.
Trabalhando com SafeArrays
Use ZeroMemory() antes de acessar quaisquer elementos em um SafeArray.
Não marcar nos índices de um SafeArray. Eles podem ser negativos.
O exemplo de código a seguir mostra como lidar corretamente com um 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();
}