obexbthtransport.cpp

来自「Windows CE 6.0 Server 源码」· C++ 代码 · 共 1,341 行 · 第 1/4 页

CPP
1,341
字号
        //
        while(pUUIDList)
        {
            BT_UUID16_LIST *pDel = pUUIDList;
            pUUIDList = pUUIDList->pNext;
            delete pDel;
        }
    }

done:
    pIStream->Release();

    for (i = 0; i < ulRecords; i++) 
        pRecordArg[i]->Release();

    CoTaskMemFree(pRecordArg);

    *pBTCList = pChannList;
    return hres;
}




static void InitWSAQuerySet(WSAQUERYSET *pw, BT_ADDR *pba=NULL, CSADDR_INFO *pcsaBuffer=NULL, SOCKADDR_BTH *psockBT=NULL, LPBLOB pBlob=NULL)  {
    memset(pw,0,sizeof(WSAQUERYSET));
    pw->dwSize      = sizeof(WSAQUERYSET);
    pw->dwNameSpace = NS_BTH;
    pw->lpBlob      = pBlob;

    if (pba)  {
        pw->lpcsaBuffer = pcsaBuffer;
        
        memset(pcsaBuffer,0,sizeof(CSADDR_INFO));
        memset(psockBT,0,sizeof(SOCKADDR_BTH));
        memcpy(&psockBT->btAddr,pba,sizeof(BT_ADDR));
        pcsaBuffer->RemoteAddr.lpSockaddr       = (LPSOCKADDR) psockBT;
        pcsaBuffer->RemoteAddr.iSockaddrLength  = sizeof(SOCKADDR_BTH);
    }
}




static HRESULT QueryForChannel(BT_ADDR bt, BT_CHANNEL_LIST **pBTCList)
{
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::QueryForChannel()\n"));
    
    SVSUTIL_ASSERT(pBTCList);

    SdpQueryUuid   uuidObex;
    uuidObex.u.uuid16 = OBEX_PROTOCOL_UUID16;
    uuidObex.uuidType = SDP_ST_UUID16;

    HRESULT hr = E_FAIL;
    SdpAttributeRange     attribRange[2];
    attribRange[0].minAttribute = attribRange[0].maxAttribute = SDP_ATTRIB_CLASS_ID_LIST;
    attribRange[1].minAttribute = attribRange[1].maxAttribute = SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST;


    WSAQUERYSET         wsaQuery;
    PBTHNS_RESTRICTIONBLOB prBlob;
    BLOB blob;
    unsigned long ulBlobLen = sizeof(BTHNS_RESTRICTIONBLOB) + sizeof(SdpAttributeRange);
    CHAR BTHNSStruct[sizeof(BTHNS_RESTRICTIONBLOB) + sizeof(SdpAttributeRange)];
    
    if(NULL == BTHNSStruct)
        return E_OUTOFMEMORY;
    
    prBlob = (PBTHNS_RESTRICTIONBLOB) BTHNSStruct;
    memset(BTHNSStruct,0,ulBlobLen); //required to have all UUID's following last
                                 //  valid UUID of prBlob->uuids be 0!
                                 
    prBlob->type          = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
    prBlob->numRange      =  2; //tells that there are 2 attribRange's

    //PREFAST NOTE:  this should be okay - note prBlob points to BTHNSStruct and thats large
    PREFAST_SUPPRESS(203, "PREfast error - the following line is valid");
    memcpy(prBlob->pRange, attribRange, sizeof(SdpAttributeRange) * 2);
    memcpy(prBlob->uuids, &uuidObex, sizeof(SdpQueryUuid));

    blob.cbSize    = ulBlobLen;
    blob.pBlobData = (BYTE*)prBlob;

    CSADDR_INFO csAddr;
    SOCKADDR_BTH sockBT;
    
    
    HINSTANCE hLib = LoadLibrary(L"btdrt.dll");
    if (!hLib) {
        DEBUGMSG(OBEX_BTHTRANSPORT_ZONE, (L"CObexBTHTransport::QueryForChannel(): Failed to load btdrt.dll. GetLastError()=0x%08x\n", GetLastError()));
        return hr;
    }

    typedef int (*BTHNSLOOKUPSERVICEBEGIN)(LPWSAQUERYSET, DWORD, LPHANDLE );
    typedef int (*BTHNSLOOKUPSERVICENEXT)(HANDLE, DWORD, LPDWORD, LPWSAQUERYSET );
    typedef int (*BTHNSLOOKUPSERVICEEND)(HANDLE);
    BTHNSLOOKUPSERVICEBEGIN pfnBthNsLookupServiceBegin = (BTHNSLOOKUPSERVICEBEGIN )GetProcAddress(hLib, L"BthNsLookupServiceBegin");
    BTHNSLOOKUPSERVICENEXT pfnBthNsLookupServiceNext = (BTHNSLOOKUPSERVICENEXT )GetProcAddress(hLib, L"BthNsLookupServiceNext");
    BTHNSLOOKUPSERVICEEND pfnBthNsLookupServiceEnd = (BTHNSLOOKUPSERVICEEND )GetProcAddress(hLib, L"BthNsLookupServiceEnd");
    if ((!pfnBthNsLookupServiceBegin) || (!pfnBthNsLookupServiceNext) || (!pfnBthNsLookupServiceEnd))
    {
        DEBUGMSG(OBEX_BTHTRANSPORT_ZONE, (L"CObexBTHTransport::QueryForChannel(): BthNsLookupServiceXXX functions not found in btdrt.dll\n"));
        FreeLibrary(hLib);
        return hr;
    }

    InitWSAQuerySet(&wsaQuery,&bt,&csAddr,&sockBT,&blob);

    DWORD dwFlags = 0;
    ULONG lChannel = 0;
    long lRet;
    HANDLE hLookup;
   
    lRet = pfnBthNsLookupServiceBegin(&wsaQuery,dwFlags,&hLookup);
           
    if (ERROR_SUCCESS == lRet) 
    {
        DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::QueryForChannel()  BthNsLookupServiceBegin returned 0x%08x\r\n",lRet));
        // Get Results
        DWORD dwSize  = 5000;
        CHAR *pQueryResults = new char[dwSize];
        
        if(!pQueryResults)
            hr = E_OUTOFMEMORY;
        else
        {
            LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) pQueryResults;
            
            dwFlags = LUP_RETURN_ALL;

            lRet = pfnBthNsLookupServiceNext(hLookup,dwFlags,&dwSize,pwsaResults);
           
            DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::QueryForChannel()   BthNsLookupServiceNext returned 0x%08x \r\n",lRet));
           
            pfnBthNsLookupServiceEnd(hLookup);  
            
            if (lRet == ERROR_SUCCESS || lRet == ERROR_NO_MORE_ITEMS && pwsaResults->lpBlob)
            {
                hr = GetRFCOMMChannel(pwsaResults->lpBlob->pBlobData, pwsaResults->lpBlob->cbSize, pBTCList);                
                if(FAILED(hr))
                {
                    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::QueryForChannel -- GetRFCOMMChannel failed\n"));            
                }
            }
        }
        
        if(pQueryResults)
            delete [] pQueryResults;    
    }  
   
    FreeLibrary(hLib);
    return hr;
}

CObexBTHTransport::CObexBTHTransport() : _refCount(1), pNameCache(NULL), fIsAborting(FALSE)
{
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::CObexBTHTransport()\n"));   
    
    //initilize the socket libs
    WSADATA wsd;
    WSAStartup (MAKEWORD(2,2), &wsd); 
}

CObexBTHTransport::~CObexBTHTransport()
{
    //
    //  clean out name cache
    //
    while(pNameCache)
    {
        NAME_CACHE_NODE *pDel = pNameCache;
        VariantClear(&pDel->var);
        pNameCache = pNameCache->pNext;
        delete pDel;
    }

    //clean up winsock
    WSACleanup();
    
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::~CObexBTHTransport()\n"));   
}

HRESULT STDMETHODCALLTYPE 
CObexBTHTransport::Init(void)
{
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::Init()\n"));
    return S_OK;
}

HRESULT STDMETHODCALLTYPE 
CObexBTHTransport::Shutdown(void)
{
        return S_OK;
}

HRESULT STDMETHODCALLTYPE
//singleton that holds a socket object 
CObexBTHTransport::CreateSocket(LPPROPERTYBAG2 pPropertyBag,
                                 LPSOCKET  *ppSocket)
{
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::CreateSocket()\n"));
   
    *ppSocket = new CBTHTransportSocket(); 
    if( !(*ppSocket) )
    {
        return E_OUTOFMEMORY;
    } 
    return S_OK;
}


HRESULT STDMETHODCALLTYPE 
CObexBTHTransport::CreateSocketBlob(unsigned long ulSize,
                                     byte __RPC_FAR *pbData,
                                     LPSOCKET __RPC_FAR *ppSocket)
{
        return E_NOTIMPL;
}


typedef int (*TBthPerformInquiry) (unsigned int LAP, unsigned char length, unsigned char num_responses, unsigned int cBuffer, unsigned int *pcRequired, BthInquiryResult *pir);
 
HRESULT STDMETHODCALLTYPE 
CObexBTHTransport::EnumDevices(LPPROPERTYBAGENUM *ppDevices)
{
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::EnumDevices()\n"));
    HRESULT hRet = E_FAIL;
    HINSTANCE hLib = NULL; 
    TBthPerformInquiry pBthPerformInquiry = NULL;
    BthInquiryResult *pIR = NULL;
    int iNumDevices = 0;
    int i;
    CPropertyBagEnum *pPropEnum = NULL;
    CPropertyBag *pPropBag = NULL;
    VARIANT var;
    VariantInit(&var);
    
    //
    // verify input params
    if (!ppDevices)
    {
        hRet = E_POINTER;
        goto Cleanup;
    }

    //
    // initialize input param
    *ppDevices = 0;


    //
    // load the btdrt dll, and get the BthPerformInquiry function
    if (NULL == (hLib = LoadLibrary (L"btdrt.dll")))
    {
        hRet = E_FAIL;
        goto Cleanup;
    }   

    if (NULL == (pBthPerformInquiry = (TBthPerformInquiry)GetProcAddress (hLib, L"BthPerformInquiry")))
    {     
        hRet = E_FAIL;
        goto Cleanup;
    }

    if(NULL == (pIR = new BthInquiryResult[BTH_INQUIRY_SIZE]))
    {
        hRet = E_OUTOFMEMORY;
        goto Cleanup;
    }

    if (ERROR_SUCCESS != pBthPerformInquiry(BT_ADDR_GIAC, BTH_INQUIRY_LEN, 0, BTH_INQUIRY_SIZE, (unsigned int *)&iNumDevices, pIR))
    {
        hRet = E_FAIL;
        goto Cleanup;
    }
    
    DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::EnumDevices - Inquiry returned following devices...:\n"));
#if defined (DEBUG) || defined (_DEBUG)
    for (i = 0 ; i < iNumDevices ; ++i)
       DEBUGMSG(OBEX_BTHTRANSPORT_ZONE,(L"CObexBTHTransport::EnumDevices - (%04x%08x)\n", GET_NAP(pIR[i].ba), GET_SAP(pIR[i].ba)));
#endif


    if (NULL == (pPropEnum = new CPropertyBagEnum()))
    {
        hRet = E_OUTOFMEMORY;
        goto Cleanup;
    }

    
    for(i=0; i < iNumDevices; ++i)
    {    
        if (NULL == (pPropBag = new CPropertyBag()))
        {            
            hRet = E_OUTOFMEMORY;
            goto Cleanup;
        }

        // 
        //  The name and the port will be the same (VB style BSTR here)
        //
        USHORT name[30];
        swprintf(name, L"%04x%08x", GET_NAP(pIR[i].ba), GET_SAP(pIR[i].ba));
        var.vt = VT_BSTR;
        var.bstrVal = SysAllocString(name);          

        // set the name and the address (again, they are the same)
        hRet = pPropBag->Write(c_szDevicePropAddress, &var);
            SVSUTIL_ASSERT(SUCCEEDED(hRet));
        hRet = pPropBag->Write(c_szDevicePropName, &var);            
            SVSUTIL_ASSERT(SUCCEEDED(hRet));

        //
        //  Put a marker in saying that the name has NOT been completed
        //
        VariantClear(&var);        
        var.vt = VT_I4;
        var.lVal = 0;
        hRet = pPropBag->Write(c_szDevicePropNameCompleted, &var);

        // add the transport ID
        LPOLESTR pszClsid = NULL;
        hRet = StringFromCLSID((REFCLSID) CLSID_BthTransport, &pszClsid);
           SVSUTIL_ASSERT(SUCCEEDED(hRet));
        var.vt = VT_BSTR;
        var.bstrVal = SysAllocString(pszClsid);   
        CoTaskMemFree(pszClsid);
        
        hRet = pPropBag->Write(c_szDevicePropTransport, &var);        
        SVSUTIL_ASSERT(SUCCEEDED(hRet));
        
        VariantClear (&var);

        // add to the enumeration
        pPropEnum->Insert(pPropBag);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?