www.pudn.com > WINCEOS.zip > hidsdp.cxx


// 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
// 
// 
// This source code is licensed under Microsoft Shared Source License 
// Version 1.0 for Windows CE. 
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223. 
// 
#include  
 
#include  
#include  
 
#include "hidsdp.h" 
 
BTHHIDSdpParser::BTHHIDSdpParser() : 
    m_ppRecords(NULL), 
    m_cRecords(0), 
    m_fInfoLoaded(FALSE) 
{ 
} 
 
BTHHIDSdpParser::~BTHHIDSdpParser() 
{ 
    unsigned int i = 0; 
    if (m_ppRecords) 
    { 
        for (i = 0; i < m_cRecords; i++)  
            m_ppRecords[i]->Release(); 
        CoTaskMemFree(m_ppRecords); 
    } 
} 
 
int BTHHIDSdpParser::Start (const unsigned char* pSdpBuffer, int cBuffer) 
{ 
    int iErr = ERROR_SUCCESS; 
 
    CoInitializeEx(NULL, COINIT_MULTITHREADED);  
 
    HRESULT hrServiceSearch = ServiceAndAttributeSearch((UCHAR*) pSdpBuffer, cBuffer, &m_ppRecords, &m_cRecords); 
    if (SUCCEEDED(hrServiceSearch) && m_cRecords == 1) 
        m_fInfoLoaded = TRUE; 
    else 
        iErr = ERROR_INVALID_PARAMETER; 
 
    return iErr; 
} 
 
int BTHHIDSdpParser::End (void) 
{ 
    this->BTHHIDSdpParser::~BTHHIDSdpParser(); 
    this->BTHHIDSdpParser::BTHHIDSdpParser(); 
 
    CoUninitialize(); 
 
    return 0; 
} 
 
// Accessors 
int BTHHIDSdpParser::GetHIDReconnectInitiate(BOOL* pfReconnectInitiate) 
{ 
    int iErr = ERROR_INVALID_PARAMETER; 
 
    if (m_fInfoLoaded && pfReconnectInitiate) 
    { 
        ISdpRecord* pRecord = m_ppRecords[0]; 
        NodeData    nodeAttrib; 
        HRESULT     hr = pRecord->GetAttribute(SDP_ATTRIB_HID_RECONNECT_INITIATE, &nodeAttrib); 
 
        if (SUCCEEDED(hr)) 
        { 
            *pfReconnectInitiate = nodeAttrib.u.booleanVal; 
            iErr = ERROR_SUCCESS; 
        } 
    } 
 
    return iErr; 
} 
 
int BTHHIDSdpParser::GetHIDNormallyConnectable(BOOL* pfNormallyConnectable) 
{ 
    int iErr = ERROR_INVALID_PARAMETER; 
 
    if (m_fInfoLoaded && pfNormallyConnectable) 
    { 
        ISdpRecord* pRecord = m_ppRecords[0]; 
        NodeData    nodeAttrib; 
        HRESULT     hr = pRecord->GetAttribute(SDP_ATTRIB_HID_NORMALLY_CONNECTABLE, &nodeAttrib); 
 
        if (SUCCEEDED(hr)) 
        { 
            *pfNormallyConnectable = nodeAttrib.u.booleanVal; 
            iErr = ERROR_SUCCESS; 
        } 
    } 
 
    return iErr; 
} 
 
int BTHHIDSdpParser::GetHIDVirtualCable(BOOL* pfVirtualCable) 
{ 
    int iErr = ERROR_INVALID_PARAMETER; 
 
    if (m_fInfoLoaded && pfVirtualCable) 
    { 
        ISdpRecord* pRecord = m_ppRecords[0]; 
        NodeData    nodeAttrib; 
        HRESULT     hr = pRecord->GetAttribute(SDP_ATTRIB_HID_VIRTUAL_CABLE, &nodeAttrib); 
 
        if (SUCCEEDED(hr)) 
        { 
            *pfVirtualCable = nodeAttrib.u.booleanVal; 
            iErr = ERROR_SUCCESS; 
        } 
    } 
 
    return iErr; 
 
} 
 
int BTHHIDSdpParser::GetHIDDeviceSubclass(unsigned char* pucDeviceSubclass) 
{ 
    int iErr = ERROR_INVALID_PARAMETER; 
 
    if (m_fInfoLoaded && pucDeviceSubclass) 
    { 
        ISdpRecord* pRecord = m_ppRecords[0]; 
        NodeData    nodeAttrib; 
        HRESULT     hr = pRecord->GetAttribute(SDP_ATTRIB_HID_DEVICE_SUBCLASS, &nodeAttrib); 
 
        if (SUCCEEDED(hr)) 
        { 
            *pucDeviceSubclass = nodeAttrib.u.uint8; 
            iErr = ERROR_SUCCESS; 
        } 
    } 
 
    return iErr; 
} 
int BTHHIDSdpParser::GetHIDReportDescriptor(LPBLOB pbReportDescriptor) 
{ 
    int                 iErr            = E_FAIL; 
    unsigned long       cElements       = 0; 
    ISdpRecord*         pRecord         = NULL; 
    ISdpNodeContainer*  pContainer      = NULL; 
    NodeData            nodeData, nodeClassDescriptorData; 
    HRESULT             hr; 
 
    nodeClassDescriptorData.u.str.length = 0; 
    nodeClassDescriptorData.u.str.val = NULL; 
 
    if (!m_fInfoLoaded || !pbReportDescriptor) 
    { 
        iErr = ERROR_INVALID_PARAMETER; 
        goto Error; 
    } 
 
    pRecord = m_ppRecords[0]; 
    hr = pRecord->GetAttribute(SDP_ATTRIB_HID_DESCRIPTOR_LIST, &nodeData); 
    if (FAILED(hr)) 
    { 
        iErr = HRESULT_CODE(hr); 
        goto Error; 
    } 
 
    // Validate structure 
    pContainer = nodeData.u.container; 
    pContainer->GetNodeCount(&cElements); 
    if (cElements != 1) 
    { 
        iErr = ERROR_BAD_FORMAT; 
        goto Error; 
    } 
 
    // Move down to only child 
    pContainer->GetNode(0, &nodeData); 
 
    // Validate structure. In future versions of HID,  
    // we might get more than 2 children here. At least 2 are garanteed. 
    pContainer = nodeData.u.container; 
    pContainer->GetNodeCount(&cElements); // on 2nd call, this throws an exception. 
    if (cElements < 2) 
    { 
        iErr = ERROR_BAD_FORMAT; 
        goto Error; 
    } 
 
    // Move down to the first child, the ClassDescriptorType 
    pContainer->GetNodeStringData(1, &nodeClassDescriptorData); 
 
    // We now point to our report descriptor. Fill in the blob. 
    if (pbReportDescriptor->cbSize == 0) 
        pbReportDescriptor->cbSize = nodeClassDescriptorData.u.str.length; 
    else 
    { 
        if (pbReportDescriptor->pBlobData) 
        { 
            pbReportDescriptor->cbSize = nodeClassDescriptorData.u.str.length; 
            memcpy(pbReportDescriptor->pBlobData, nodeClassDescriptorData.u.str.val, pbReportDescriptor->cbSize); 
        } 
        else 
        { 
            iErr = ERROR_INVALID_PARAMETER; 
            goto Error; 
        } 
    } 
 
    iErr = ERROR_SUCCESS; 
 
Error: 
 
    if (nodeClassDescriptorData.u.str.val) 
        CoTaskMemFree(nodeClassDescriptorData.u.str.val); 
 
    return iErr; 
} 
 
//  
// Takes a raw stream ServiceAttribute response from the server and converts  
// it into an array of ISdpRecord elements to facilitate manipulation. 
//  
HRESULT 
BTHHIDSdpParser::ServiceAndAttributeSearch( 
                          UCHAR *szResponse,             // in - response returned from SDP ServiceAttribute query 
                          DWORD cbResponse,            // in - length of response 
                          ISdpRecord ***pppSdpRecords, // out - array of pSdpRecords 
                          ULONG *pNumRecords           // out - number of elements in pSdpRecords 
                          ) 
{ 
    HRESULT hres = E_FAIL; 
     
    *pppSdpRecords = NULL; 
    *pNumRecords = 0; 
     
    ISdpStream *pIStream = NULL; 
     
    hres = CoCreateInstance(__uuidof(SdpStream),NULL,CLSCTX_INPROC_SERVER, 
        __uuidof(ISdpStream),(LPVOID *) &pIStream); 
     
    if (FAILED(hres)) 
        return hres;   
     
    hres = pIStream->Validate(szResponse,cbResponse,NULL); 
     
    if (SUCCEEDED(hres)) { 
        hres = pIStream->VerifySequenceOf(szResponse,cbResponse, 
            SDP_TYPE_SEQUENCE,NULL,pNumRecords); 
         
        if (SUCCEEDED(hres) && *pNumRecords > 0) { 
            *pppSdpRecords = (ISdpRecord **) CoTaskMemAlloc(sizeof(ISdpRecord*) * (*pNumRecords)); 
             
            if (pppSdpRecords != NULL) { 
                hres = pIStream->RetrieveRecords(szResponse,cbResponse,*pppSdpRecords,pNumRecords); 
                 
                if (!SUCCEEDED(hres)) { 
                    CoTaskMemFree(*pppSdpRecords); 
                    *pppSdpRecords = NULL; 
                    *pNumRecords = 0; 
                } 
            } 
            else { 
                hres = E_OUTOFMEMORY; 
            } 
        } 
    } 
     
    if (pIStream != NULL) { 
        pIStream->Release(); 
        pIStream = NULL; 
    } 
     
    return hres; 
}