⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdpdbserver.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -