📄 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 <windows.h>
#include <bt_sdp.h>
#include <bthapi.h>
#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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -