📄 sdpcommon.cpp
字号:
while (size) {
PUCHAR pElementInfo = NULL;
ULONG recordSize = 0;
BOOL fFirstPass = TRUE;
pSdpStream->RetrieveElementInfo(pStream,&type,&specType,&recordSize,&storageSize,&pElementInfo);
if (type != SDP_TYPE_SEQUENCE) {
pfnPrint(pvContext,TRUE,L"Protocol stream invalid, element is not a Data Element Sequence\n");
goto done;
}
// Adjust the main traversal pointer
ULONG fullRecordSize = recordSize + 1 + storageSize;
pStream += fullRecordSize;
size -= fullRecordSize;
sdpProtocol = SDP_PROTOCOL_UNKNOWN;
// Walk through the given sequence.
while (recordSize) {
ULONG subRecordSize;
PUCHAR pSubElementInfo = NULL;
pSdpStream->RetrieveElementInfo(pElementInfo,&type,&specType,&subRecordSize,&storageSize,&pSubElementInfo);
subRecordSize += 1 + storageSize;
pElementInfo += subRecordSize;
recordSize -= subRecordSize;
if (sdpProtocol == SDP_PROTOCOL_UNKNOWN) {
if (type != SDP_TYPE_UUID) {
pfnPrint(pvContext,TRUE,L" First element in sequence is not a protocol UUID, skipping parsing on current sequence\n");
break;
}
SdpPrintUUID(specType,pSdpStream,pSubElementInfo,0,pfnPrint,pvContext,SDP_PRINT_FLAG_INDENT);
ULONG ulGUID = FindUUIDType(specType, pSdpStream, pSubElementInfo);
if ((ulGUID != L2CAP_PROTOCOL_UUID16) && (ulGUID != RFCOMM_PROTOCOL_UUID16) &&
(ulGUID != OBEX_PROTOCOL_UUID16)) {
pfnPrint(pvContext,TRUE,L" Do not know how to parse protocol UUID... skipping.\n");
break;
}
sdpProtocol = ulGUID;
continue;
}
if (sdpProtocol == L2CAP_PROTOCOL_UUID16) {
if (fFirstPass) {
if (specType != SDP_ST_UINT16) {
pfnPrint(pvContext,TRUE,L" L2CAP Channel ID type is not UINT16, skipping rest of processing of this entry.\n");
break;
}
USHORT cid;
pSdpStream->RetrieveUint16(pSubElementInfo,&cid);
pfnPrint(pvContext,FALSE,L" L2CAP Channel ID = 0x%04x\n",cid);
fFirstPass = FALSE;
}
else {
pfnPrint(pvContext,TRUE,L" Do not know how to parse remainder of L2CAP information... skipping.\n");
break;
}
}
else if (sdpProtocol == RFCOMM_PROTOCOL_UUID16) {
if (fFirstPass) {
if (specType != SDP_ST_UINT8) {
pfnPrint(pvContext,TRUE,L" RFCOMM Channel ID type is not UINT8, skipping rest of processing of this entry.\n");
break;
}
pfnPrint(pvContext,FALSE,L" RFCOMM Channel ID = 0x%02x\n",*pSubElementInfo);
fFirstPass = FALSE;
}
else {
pfnPrint(pvContext,TRUE,L" Do not know how to parse remainder of RFCOMM information... skipping.\n");
break;
}
}
else {
assert(sdpProtocol == OBEX_PROTOCOL_UUID16);
pfnPrint(pvContext,TRUE,L" Do not know how to parse remainder of OBEX information... skipping.\n");
break;
}
}
}
done:
if (pSdpStream)
FreeSdpStream(pSdpStream);
}
// Language base is a data element containing one or more group of 3 UINT16's.
void SdpPrintAttribLanguageBase(UCHAR *pStream, ULONG size, PFN_SDPPRINT pfnPrint, PVOID pvContext) {
ISdpStream *pSdpStream = NULL;
SDP_TYPE type;
SDP_SPECIFICTYPE specType;
ULONG storageSize;
int iIndex = 0;
if (! LoadAndValidate(&pSdpStream,&pStream,&size,TRUE)) {
pfnPrint(pvContext,TRUE,L"Attribute Object misformatted\n");
goto done;
}
while (size) {
USHORT rgusAttribs[3];
ULONG recordSize = 0;
UCHAR *pAttrib;
for (DWORD i = 0; i < SVSUTIL_ARRLEN(rgusAttribs); i++) {
if (FAILED(pSdpStream->RetrieveElementInfo(pStream,&type,&specType,&recordSize,&storageSize,&pAttrib) ||
(specType != SDP_ST_UINT16))) {
PrintMisformatted(pfnPrint,pvContext);
goto done;
}
pSdpStream->RetrieveUint16(pAttrib,&rgusAttribs[i]);
recordSize += 1 + storageSize;
pStream += recordSize;
size -= recordSize;
if (size == 0 && i != (SVSUTIL_ARRLEN(rgusAttribs)-1)) {
PrintMisformatted(pfnPrint,pvContext);
goto done;
}
}
pfnPrint(pvContext,FALSE,L" Entry(%d)\n",iIndex);
pfnPrint(pvContext,FALSE,L" Language = 0x%04x\n",RtlUshortByteSwap(rgusAttribs[0]));
pfnPrint(pvContext,FALSE,L" Character Encoding = 0x%04x\n",RtlUshortByteSwap(rgusAttribs[1]));
pfnPrint(pvContext,FALSE,L" Base AttributeID = 0x%04x\n",RtlUshortByteSwap(rgusAttribs[2]));
iIndex++;
}
done:
if (pSdpStream)
FreeSdpStream(pSdpStream);
}
void SdpPrintAttribServiceInfoTTL(UCHAR *pStream, ULONG size, PFN_SDPPRINT pfnPrint, PVOID pvContext) {
ISdpStream *pSdpStream = NULL;
int iIndex = 0;
ULONG infoTTL;
if (! LoadAndValidate(&pSdpStream,&pStream,&size,FALSE)) {
pfnPrint(pvContext,TRUE,L"Attribute Record misformatted\n");
goto done;
}
if ( ! GetIntFromStream(pSdpStream,pStream,size,&infoTTL)) {
pfnPrint(pvContext,TRUE,L" Element is not a UINT32\n");
goto done;
}
pfnPrint(pvContext,FALSE,L" ServiceInfoTimeToLive = 0x%08x\n",infoTTL);
done:
if (pSdpStream)
FreeSdpStream(pSdpStream);
}
void SdpPrintAttribServiceAvailability(UCHAR *pStream, ULONG size, PFN_SDPPRINT pfnPrint, PVOID pvContext) {
SDP_TYPE type;
SDP_SPECIFICTYPE specType = SDP_ST_NONE;
ULONG storageSize;
ULONG recordSize;
ISdpStream *pSdpStream = NULL;
if (! LoadAndValidate(&pSdpStream,&pStream,&size,FALSE)) {
pfnPrint(pvContext,TRUE,L"Attribute Record misformatted\n");
goto done;
}
pSdpStream->RetrieveElementInfo(pStream,&type,&specType,&recordSize,&storageSize,&pStream);
if (specType != SDP_ST_UINT8) {
pfnPrint(pvContext,TRUE,L" Element is not a UINT8\n");
goto done;
}
pfnPrint(pvContext,FALSE,L" Service Availability = 0x%02x\n",*pStream);
done:
if (pSdpStream)
FreeSdpStream(pSdpStream);
}
void SdpPrintAttribBluetoothProfileDescriptorList(UCHAR *pStream, ULONG size, PFN_SDPPRINT pfnPrint, PVOID pvContext) {
ISdpStream *pSdpStream = NULL;
SDP_TYPE type;
SDP_SPECIFICTYPE specType;
ULONG storageSize;
ULONG sdpProtocol;
int iIndexNumber = 0;
if (! LoadAndValidate(&pSdpStream,&pStream,&size,TRUE)) {
pfnPrint(pvContext,TRUE,L"Attribute Object misformatted\n");
goto done;
}
// The Profile descriptor list is a data element sequence containing
// one or more data element sequences containing information about a BT profile
// supported by this record. The first element of each list is a UUID specifying
// the service, the second is a UINT16 representing the version #.
while (size) {
PUCHAR pElementInfo = NULL;
ULONG recordSize = 0;
BOOL fFirstPass = TRUE;
pSdpStream->RetrieveElementInfo(pStream,&type,&specType,&recordSize,&storageSize,&pElementInfo);
if (type != SDP_TYPE_SEQUENCE) {
pfnPrint(pvContext,TRUE,L"Protocol stream invalid, element is not a Data Element Sequence\n");
goto done;
}
// Adjust the main traversal pointer
ULONG fullRecordSize = recordSize + 1 + storageSize;
pStream += fullRecordSize;
size -= fullRecordSize;
sdpProtocol = SDP_PROTOCOL_UNKNOWN;
pfnPrint(pvContext,FALSE,L" Protocol Descriptor(%d)\n",iIndexNumber);
// Walk through the given sequence.
while (recordSize) {
ULONG subRecordSize;
PUCHAR pSubElementInfo = NULL;
pSdpStream->RetrieveElementInfo(pElementInfo,&type,&specType,&subRecordSize,&storageSize,&pSubElementInfo);
subRecordSize += 1 + storageSize;
pElementInfo += subRecordSize;
recordSize -= subRecordSize;
if (fFirstPass) {
if (type != SDP_TYPE_UUID) {
pfnPrint(pvContext,TRUE,L" First element is not a UUID, skipping this entry\n");
break;
}
SdpPrintUUID(specType, pSdpStream, pSubElementInfo, 0, pfnPrint, pvContext,SDP_PRINT_FLAG_INDENT);
fFirstPass = FALSE;
}
else {
if (specType != SDP_ST_UINT16) {
pfnPrint(pvContext,TRUE,L" Second element is not a UINT16, skipping this entry\n");
break;
}
USHORT usVersion;
pSdpStream->RetrieveUint16(pSubElementInfo,&usVersion);
usVersion = RtlUshortByteSwap(usVersion);
pfnPrint(pvContext,FALSE,L" Version = %d.%d\n",HIBYTE(usVersion),LOBYTE(usVersion));
}
}
iIndexNumber++;
}
done:
if (pSdpStream)
FreeSdpStream(pSdpStream);
}
void SdpPrintAttribURL(UCHAR *pStream, ULONG size, PFN_SDPPRINT pfnPrint, PVOID pvContext) {
SDP_TYPE type;
SDP_SPECIFICTYPE specType = SDP_ST_NONE;
ULONG storageSize;
ULONG recordSize;
ISdpStream *pSdpStream = NULL;
int iIndex = 0;
if (! LoadAndValidate(&pSdpStream,&pStream,&size,FALSE)) {
pfnPrint(pvContext,TRUE,L"Attribute Record misformatted\n");
goto done;
}
pSdpStream->RetrieveElementInfo(pStream,&type,&specType,&recordSize,&storageSize,&pStream);
if (type != SDP_TYPE_URL) {
pfnPrint(pvContext,TRUE,L" Element is not a URL\n");
goto done;
}
pfnPrint(pvContext,FALSE,L" URL=");
SdpPrintString(pStream,recordSize,pfnPrint,pvContext);
done:
if (pSdpStream)
FreeSdpStream(pSdpStream);
}
static const PFN_SDPPRINT_ATTRIB g_PrintTable[] = {
SdpPrintAttribRecordHandle,
SdpPrintAttribUUIDs, // Class ID is a list of UUIDs
SdpPrintAttribRecordState,
SdpPrintAttribServiceId,
SdpPrintAttribProtDescrList,
SdpPrintAttribUUIDs, // Browse group list is a list of UUIDs
SdpPrintAttribLanguageBase,
SdpPrintAttribServiceInfoTTL,
SdpPrintAttribServiceAvailability,
SdpPrintAttribBluetoothProfileDescriptorList,
SdpPrintAttribURL, // document URL is an URL
SdpPrintAttribURL, // client exe URL is an URL
SdpPrintAttribURL // icon URL is an URL
};
void PrintRecordInfo(ISdpRecord *pRecord, int iRecordIndex, PFN_SDPPRINT pfnPrint, PVOID pvContext) {
USHORT *pAttributeList = NULL;
ULONG nAttributes;
ULONG i;
pfnPrint(pvContext,FALSE,L"*** Record %d ***\n",iRecordIndex+1);
if (FAILED(pRecord->GetAttributeList(&pAttributeList,&nAttributes))) {
pfnPrint(pvContext,TRUE,L"Unable to retrieve attributes from record\n");
goto done;
}
for (i = 0; i < nAttributes; i++) {
USHORT usAttribId = pAttributeList[i];
UCHAR *pStream = NULL;
ULONG size;
pfnPrint(pvContext,FALSE,L"AttribID 0x%04x (%s)\n",usAttribId,GetAttribFromID(usAttribId));
if (FAILED(pRecord->GetAttributeAsStream(usAttribId,&pStream,&size))) {
if (pStream)
CoTaskMemFree(pStream);
// since this is almost certainly an OOM or an internal error, no point continuing processing.
pfnPrint(pvContext,TRUE,L"Unable to parse attribute stream for attribute id %d. Stopping processing.\n",usAttribId);
goto done;
}
if (usAttribId > SDP_ATTRIB_ICON_URL) {
SdpPrintUnknownAttribute(pStream,size,pfnPrint,pvContext,1);
}
else {
g_PrintTable[usAttribId](pStream,size,pfnPrint,pvContext);
}
CoTaskMemFree(pStream);
}
done:
if (pAttributeList)
CoTaskMemFree(pAttributeList);
}
// Error code -> string lookup
static const WCHAR *g_szErrorCodes[] = {
L"Invalid/unsupported SDP version",
L"Invalid Service Record Handle",
L"Invalid request syntax",
L"Invalid PDU size",
L"Invalid Continuation State",
L"Insufficient Resources to satisfy request"
};
static const WCHAR cszUnknownErr[] = L"Unknown Error Code";
const WCHAR *GetErrorFromId(USHORT usErrCode) {
if ((usErrCode >= SDP_ERROR_INVALID_SDP_VERSION) && (usErrCode <= SDP_ERROR_INSUFFICIENT_RESOURCES))
return g_szErrorCodes[usErrCode-1];
return cszUnknownErr;
}
// Protocol packet type -> string lookup
static const WCHAR *g_szPDUTypes[] = {
L"Error PDU",
L"Service Search Request PDU",
L"Service Search Response PDU",
L"Attribute Request PDU",
L"Attribute Response PDU",
L"Service Attribute Search Request PDU",
L"Service Attribute Search Response PDU"
};
static const WCHAR cszUnknownPDU[] = L"Unknown PDU packet";
const WCHAR *GetPduNameFromId(UCHAR id) {
if ((id >= 1) && (id <= SVSUTIL_ARRLEN(g_szPDUTypes))) // PDU Error to PDU Service Attribute Response
return g_szPDUTypes[id-1];
return cszUnknownPDU;
}
ISdpStream * AllocateSdpStream(void) {
ISdpStream *pIStream = NULL;
if (FAILED(CoCreateInstance(__uuidof(SdpStream),NULL,CLSCTX_INPROC_SERVER,
__uuidof(ISdpStream),(LPVOID *) &pIStream))) {
return NULL;
}
return pIStream;
}
void FreeSdpStream(ISdpStream *pStream) {
pStream->Release();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -