📄 sdpdbserver.cpp
字号:
//
// 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.
//
/*++
Module Name:
SdpDBUuidSearch.CPP
Abstract:
This module implemnts BTh SDP core spec.
Doron J. Holan
Notes:
Environment:
Kernel mode only
Revision History:
*/
#include "common.h"
extern ULONG g_Support10B;
struct QueryUuidData {
QueryUuidData() { RtlZeroMemory(this, sizeof(*this)); }
GUID uuid;
UCHAR found;
};
struct SdpUuidSearch {
SdpUuidSearch() { ZERO_THIS(); }
NTSTATUS RetrieveUuids(PUCHAR pStream, ULONG streamSize)
{
PAGED_CODE();
NTSTATUS status =
SdpVerifySequenceOf(pStream,
streamSize,
SDP_TYPE_UUID,
NULL,
NULL,
(PSDP_STREAM_WALK_FUNC) FindUuidsInSearchStreamWalk,
(PVOID) this);
if (NT_SUCCESS(status) && max == 0) {
SdpPrint(SDP_DBG_UUID_ERROR, ("valid UUID search seq, but no UUIDs in it!\n"));
return STATUS_INVALID_PARAMETER;
}
SdpPrint(SDP_DBG_UUID_TRACE,
("UUID search stream has %d elements\n", (ULONG) max+1));
return status;
}
BOOLEAN SearchStream(PUCHAR pStream, ULONG streamSize);
void SetUuids(SdpQueryUuid *pUuid, UCHAR maxUuid);
static NTSTATUS FindUuidsInSearchStreamWalk(SdpUuidSearch * pUuidSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize);
static NTSTATUS FindUuidsInRecordStreamWalk(SdpUuidSearch *pUuidSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data);
ULONG current;
ULONG max;
QueryUuidData queryData[MAX_UUIDS_IN_QUERY];
};
BOOLEAN SdpUuidSearch::SearchStream(PUCHAR pStream, ULONG streamSize)
{
PAGED_CODE();
ULONG i;
//
// reset the search results
//
current = 0;
for (i = 0; i < max; i++) {
queryData[i].found = FALSE;
}
//
// now search the record stream
//
SdpWalkStream(pStream,
streamSize,
(PSDP_STREAM_WALK_FUNC) FindUuidsInRecordStreamWalk,
(PVOID) this);
for (i = 0; i < max; i++) {
if (queryData[i].found != TRUE) {
SdpPrint(SDP_DBG_UUID_INFO | SDP_DBG_UUID_WARNING,
("did not find UUID #%d in stream\n", i));
return FALSE;
}
}
SdpPrint(SDP_DBG_UUID_INFO, ("found all UUIDs in the stream\n"));
return TRUE;
}
void
SdpUuidSearch::SetUuids(
SdpQueryUuid *pUuid,
UCHAR maxUuid
)
{
// GUID uuid;
max = maxUuid;
for (ULONG i = 0; i < max; i++) {
if (pUuid[i].uuidType == SDP_ST_UUID16) {
RtlCopyMemory(&queryData[i].uuid, &Bluetooth_Base_UUID, sizeof(GUID));
queryData[i].uuid.Data1 += pUuid[i].u.uuid16;
}
else if (pUuid[i].uuidType == SDP_ST_UUID32) {
RtlCopyMemory(&queryData[i].uuid, &Bluetooth_Base_UUID, sizeof(GUID));
queryData[i].uuid.Data1 += pUuid[i].u.uuid32;
}
else {
RtlCopyMemory(&queryData[i].uuid, &pUuid[i].u.uuid128, sizeof(GUID));
}
//
// Convert to network byte order so that we can search for it
//
SdpByteSwapUuid128(&queryData[i].uuid, &queryData[i].uuid);
}
}
NTSTATUS
SdpUuidSearch::FindUuidsInSearchStreamWalk(
SdpUuidSearch *pUuidSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize
)
{
PAGED_CODE();
if (pUuidSrch->current >= MAX_UUIDS_IN_QUERY) {
return STATUS_TOO_MANY_GUIDS_REQUESTED;
}
SdpRetrieveUuidFromStream(Data,
DataSize,
&(pUuidSrch->queryData + pUuidSrch->current)->uuid,
TRUE);
pUuidSrch->current++;
pUuidSrch->max++;
return STATUS_SUCCESS;
}
NTSTATUS
SdpUuidSearch::FindUuidsInRecordStreamWalk(
SdpUuidSearch *pUuidSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data
)
{
PAGED_CODE();
if (DataType != SDP_TYPE_UUID) {
//
// not interested in anything but UUIDs
//
return STATUS_SUCCESS;
}
QueryUuidData query;
SdpRetrieveUuidFromStream(Data, DataSize, &query.uuid, TRUE);
for (ULONG i = 0; i < pUuidSrch->max; i++) {
//
// Since we normalize all UUIDs to 128 bits, just to a memcmp on the 2
// values
//
if (IsEqualUuid(&pUuidSrch->queryData[i].uuid, &query.uuid)) {
pUuidSrch->queryData[i].found = TRUE;
//
// Do not break out of the loop. If the client repeated any UUIDs,
// than we should mark those as found as well.
//
// break;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
SdpDatabase::ServiceSearchRequestResponseRemote(
UCHAR *pStream,
ULONG streamSize,
USHORT maxRecordsRequested,
ULONG **ppResultStream, // must be freed when xmit is finished
USHORT *pRecordCount,
PSDP_ERROR pSdpError
)
{
SdpUuidSearch uuidSrch;
//
// Suck all of the UUIDs out of the search list
//
NTSTATUS status = uuidSrch.RetrieveUuids(pStream, streamSize);
if (!NT_SUCCESS(status)) {
SdpPrint(SDP_DBG_UUID_ERROR,
("could not retrieve the uuids from the request, 0x%x\n",
status));
*pSdpError = MapNtStatusToSdpError(status);
return status;
}
return ServiceSearchRequestResponse(&uuidSrch,
maxRecordsRequested,
ppResultStream,
pRecordCount,
pSdpError,
FALSE);
}
NTSTATUS
SdpDatabase::ServiceSearchRequestResponseLocal(
SdpQueryUuid *pUuid,
UCHAR numUuid,
USHORT maxRecordsRequested,
ULONG **ppResultStream, // must be freed when xmit is finished
USHORT *pRecordCount
)
{
SdpUuidSearch uuidSrch;
SDP_ERROR sdpError;
uuidSrch.SetUuids(pUuid, numUuid);
return ServiceSearchRequestResponse(&uuidSrch,
maxRecordsRequested,
ppResultStream,
pRecordCount,
&sdpError,
TRUE);
}
NTSTATUS
SdpDatabase::ServiceSearchRequestResponse(
SdpUuidSearch *pUuidSearch,
USHORT maxRecordsRequested,
ULONG **ppResultStream,
USHORT *pRecordCount,
PSDP_ERROR pSdpError,
BOOLEAN local
)
{
PAGED_CODE();
NTSTATUS status;
SdpPrint(SDP_DBG_UUID_TRACE, ("ServiceSearchRequestResponse enter\n"));
*ppResultStream = NULL;
*pRecordCount = 0;
USHORT numFound;
numFound = 0;
status = STATUS_SUCCESS;
//
// Iterate over each local record. If ALL the UUIDs in the search are found
// then report the search record back to the requestor
//
m_ServiceRecordList.Lock();
HandleList hl;
HandleEntry *phe;
ServiceRecord *pRecord;
for (pRecord = m_ServiceRecordList.GetHead();
pRecord != NULL;
pRecord = m_ServiceRecordList.GetNext(pRecord)) {
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
//
// We do not hide records from local browsing
//
if (local == FALSE &&
pRecord->fOptions & SERVICE_OPTION_DO_NOT_PUBLISH) {
//
// Record sumbitter did not want this SDP record published to the
// world. Skip it.
//
continue;
}
#endif
if (pUuidSearch->SearchStream(pRecord->pStream, pRecord->streamSize)) {
SdpPrint(SDP_DBG_UUID_INFO,
("uuid search, FOUND match in record 0x%x\n",
pRecord->recordHandle));
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
phe = new (PagedPool, SDP_TAG) HandleEntry(pRecord->recordHandle);
#else
phe = new HandleEntry(pRecord->recordHandle);
#endif
if (phe) {
hl.AddTail(phe);
numFound++;
}
//
// Found as many as the requestor asked for
//
if (numFound == maxRecordsRequested) {
break;
}
}
else {
SdpPrint(SDP_DBG_UUID_INFO,
("did not find any matches in record 0x%x\n",
pRecord->recordHandle));
}
}
m_ServiceRecordList.Unlock();
if (numFound > 0) {
PULONG pResult;
//
// TODO: I can optimize this by just returning the linked list and then
// pulling values off of that instead of allocating pool again here
//
pResult = (ULONG *) ExAllocatePoolWithTag(NonPagedPool,
numFound * sizeof(ULONG),
SDP_TAG);
*ppResultStream = pResult;
if (*ppResultStream == NULL) {
SdpPrint(SDP_DBG_UUID_ERROR,
("could not alloc pool for a ServiceSearch response\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
*pSdpError = MapNtStatusToSdpError(status);
}
else {
*pRecordCount = numFound;
phe = hl.GetHead();
ASSERT(hl.GetCount() == numFound);
for (USHORT i = 0; i < numFound; i++, phe = hl.GetNext(phe)) {
if (local) {
pResult[i] = phe->handle;
}
else {
pResult[i] = RtlUlongByteSwap(phe->handle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -