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

📄 sdpdb.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:

   SdpDB.CPP

Abstract:

    This module implemnts BTh SDP core spec.



   Doron J. Holan

   Notes:

   Environment:

   Kernel mode only


Revision History:
*/

#include "common.h"

#if defined (UNDER_CE)
#include <bt_os.h>
#endif


///////////////////////////////////////////////////////////////////////////
// INTERNAL Defines
///////////////////////////////////////////////////////////////////////////

const ULONG SdpDatabase::SDP_TAG = 'CpdS';
const ULONG PM_TAG = 'xMtP';
const ULONG RV_TAG = 'VceR';

#if SDP_VERBOSE
ULONG SDP_DBG_FLAGS = DEFAULT_SDP_DBG_FLAGS;
#endif // SDP_VERBOSE

//
// Service record stream whose form is (Attrib ID, AttibValue)
// SDP_ATTRIB_RECORD_HANDLE
//      UINT32 0x0
//
// SDP_ATTRIB_CLASS_ID_LIST,
//      SEQ 
//          UUID16 ServiceDiscoveryServerServiceClassID_UUID16
//
// SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST
//      SEQ 
//          SEQ
//              UUID16 L2CAP_PROTOCOL_UUID16
//              UINT 16 0x00001
//          SEQ
//              UUID16 SDP_PROTOCOL_UUID16
//
// (SDP_ATTRIB_BROWSE_GROUP_LIST has been removed for WinCE)
// SDP_ATTRIB_BROWSE_GROUP_LIST
//  SEQ
//      UUID16 PublicBrowseGroupServiceClassID_UUID16 
//
// SDP_ATTRIB_LANG_BASE_ATTIB_ID_LIST
//  SEQ
//      UINT16      0x656e      (language, english "en")
//      UINT16      0x0061      (encoding, utf-8)
//      UINT16      0x0100      (offset)
//
// 0x100 + STRING_NAME_OFFSET
//  STRING "Service Discovery"
//
// 0x100 + STRING_DESCRIPTION_OFFSET
//  STRING "Publishes services to remote devices"
//
// 0x100 + STIRNG_PROVIDER_NAME_OFFSET
//  STRING "Microsoft"
//
// SDP_ATTRIB_PRIV_VERSION_NUMBER_LIST
//  SEQ
//      UINT16 0x0100
//
// SDP_ATTRIB_SDP_DATABASE_STATE
//      UINT32 0x00 (this is only an initial value and changes every time a 
//                   record is added or removed)
// 

#if defined (UNDER_CE)
// WinCE doesn't include SDP_ATTRIB_BROWSE_GROUP_LIST or PublicBrowseGroupServiceClassID_UUID16.
const UCHAR g_ServiceStream[] = {
    0x35, 0x90, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
    0x01, 0x35, 0x03, 0x19, 0x10, 0x00, 0x09, 0x00, 0x04, 0x35, 0x0d, 0x35,
    0x06, 0x19, 0x01, 0x00, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 0x00, 0x01,
    0x09, 0x00, 0x06, 0x35,
    0x09, 0x09, 0x65, 0x6e, 0x09, 0x00, 0x6a, 0x09, 0x01, 0x00, 0x09, 0x01,
    0x00, 0x25, 0x12, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x44,
    0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x00, 0x09, 0x01, 0x01,
    0x25, 0x25, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x73, 0x20,
    0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20,
    0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63,
    0x65, 0x73, 0x00, 0x09, 0x01, 0x02, 0x25, 0x0a, 0x4d, 0x69, 0x63, 0x72,
    0x6f, 0x73, 0x6f, 0x66, 0x74, 0x00, 0x09, 0x02, 0x00, 0x35, 0x03, 0x09,
    0x01, 0x00, 0x09, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00,
};
#else
const UCHAR g_ServiceStream[] = {
    0x35, 0x98, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
    0x01, 0x35, 0x03, 0x19, 0x10, 0x00, 0x09, 0x00, 0x04, 0x35, 0x0d, 0x35,
    0x06, 0x19, 0x01, 0x00, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 0x00, 0x01,
    0x09, 0x00, 0x05, 0x35, 0x03, 0x19, 0x10, 0x02, 0x09, 0x00, 0x06, 0x35,
    0x09, 0x09, 0x65, 0x6e, 0x09, 0x00, 0x6a, 0x09, 0x01, 0x00, 0x09, 0x01,
    0x00, 0x25, 0x12, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x44,
    0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x00, 0x09, 0x01, 0x01,
    0x25, 0x25, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x73, 0x20,
    0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20,
    0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63,
    0x65, 0x73, 0x00, 0x09, 0x01, 0x02, 0x25, 0x0a, 0x4d, 0x69, 0x63, 0x72,
    0x6f, 0x73, 0x6f, 0x66, 0x74, 0x00, 0x09, 0x02, 0x00, 0x35, 0x03, 0x09,
    0x01, 0x00, 0x09, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00,
};
#endif // UNDER_CE

ULONG g_ServiceStreamSize = sizeof(g_ServiceStream)/sizeof(g_ServiceStream[0]); 

#define INVALID_RECORD_HANDLE  1
#define INVALID_ID             ((PVOID) 1)
#define INIT_HANDLE_VALUE      0xFFFF

SdpDatabase::ServiceRecord::ServiceRecord() : handle(INVALID_ID), streamSize(0),
    pStream(NULL), recordHandle(INVALID_RECORD_HANDLE)
{
    InitializeListHead(&link);
    RtlZeroMemory(&psmList, sizeof(psmList));

#if defined (UNDER_CE)
    hCallerProc = GetCallerProcess();
#endif
}



SdpDatabase::ServiceRecord::~ServiceRecord()
{
    if (pStream) {
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
        delete[] pStream;
#else
        SdpFreePool(pStream);
#endif
    }
    pStream = NULL;
}

SdpDatabase::ServiceRecord * SdpDatabase::GetServiceRecord(HANDLE handle)
{
    ServiceRecord *pRecord;
//  PLIST_ENTRY entry;

	for (pRecord = m_ServiceRecordList.GetHead();
         pRecord != NULL;
         pRecord = m_ServiceRecordList.GetNext(pRecord)) {

	    if (pRecord->handle == handle) {
		    return pRecord; 
        }
    }

	return NULL;
}

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
SdpDatabase::RecordValidator::RecordValidator(PBTHDDI_SDP_VALIDATE_INTERFACE pValInterface) 
{
    flags = pValInterface->Flags;

    pValidator = pValInterface->Validator;
    pRemoteValidator = pValInterface->RemoteValidator;
    pUpdateValidator = pValInterface->UpdateValidator;

    pContext = pValInterface->ValidatorContext;

    pValInterface->Cookie = (PVOID) this;

    InitializeListHead(&link);
}
#endif // UNDER_CE

SdpDatabase::ProtMux::ProtMux(GUID *prot) : protocol(*prot)
{
    InitializeListHead(&link);
}


SdpDatabase::SdpDatabase() :  m_nextRecordHandle(INIT_HANDLE_VALUE)
{
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    KeInitializeSemaphore(&m_dbStateSemaphore, 1, 1);
#else
    #define INITIAL_DB_STATE 0
    m_dbState = INITIAL_DB_STATE;
#endif
}

SdpDatabase::~SdpDatabase()
{
    while (!m_ServiceRecordList.IsEmpty()) {
        ServiceRecord *pRecord = m_ServiceRecordList.RemoveHead();
        delete pRecord;
    }

    while (!m_ProtMuxList.IsEmpty()) {
        ProtMux *ppm = m_ProtMuxList.RemoveHead();
        delete ppm;
    }
}

NTSTATUS SdpDatabase::Init()
{
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    NTSTATUS status;
#endif

    #if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    m_pSdpRecord = new (NonPagedPool, SDP_TAG) ServiceRecord; 
#else
    m_pSdpRecord = new ServiceRecord;
#endif
    if (m_pSdpRecord == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    m_pSdpRecord->pStream  = new (NonPagedPool, SDP_TAG) UCHAR[g_ServiceStreamSize];
#else
    m_pSdpRecord->pStream  = (UCHAR*) SdpAllocatePool(g_ServiceStreamSize * sizeof(UCHAR));
    m_pSdpRecord->handle   = 0;
#endif
    if (m_pSdpRecord->pStream == NULL) {
        delete m_pSdpRecord;
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyMemory(&m_pSdpRecord->serviceClass,
                  &ServiceDiscoveryServerServiceClassID_UUID,
                  sizeof(GUID));

    m_pSdpRecord->psmList.count = 1;
    m_pSdpRecord->psmList.list[0].psm = PSM_SDP;
    RtlCopyMemory(&m_pSdpRecord->psmList.list[0].protocol,
                  &SDP_PROTOCOL_UUID,
                  sizeof(GUID));

    m_pSdpRecord->streamSize = g_ServiceStreamSize;
    RtlCopyMemory(m_pSdpRecord->pStream, g_ServiceStream, g_ServiceStreamSize);
    m_pSdpRecord->recordHandle = 0x0;
    
    m_ServiceRecordList.AddHead(m_pSdpRecord);

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    //
    // Add the service to the security database, we do not want to prompt the
    // user when a remote device connects
    //
    status = Globals.pSecDB->AddService(ServiceDiscoveryServerServiceClassID_UUID,
                                        SERVICE_SECURITY_NONE);
#endif // UNDER_CE


        AddProtMux((LPGUID) &RFCOMM_PROTOCOL_UUID);

    return STATUS_SUCCESS;
}

NTSTATUS SdpDatabase::ValidateStream(UCHAR *pStream, ULONG streamSize, PULONG_PTR err)
{
    return ::ValidateStream(pStream, streamSize, NULL, NULL, err);
}


#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
NTSTATUS
SdpDatabase::ValidateRecordExternal(
    PUCHAR pStream,
    ULONG streamSize,
    PSDP_TREE_ROOT_NODE pTreeRoot,
    PPSM_LIST pPsmList,
    ULONG flags,
    GUID* pServiceClassUuid
    )
{
    NTSTATUS status = STATUS_SUCCESS;

    m_RecordValidatorList.Lock();

    RecordValidator *prv;
    RECORD_VALIDATOR_INFO rvi;

    RtlZeroMemory(&rvi, sizeof(rvi));

    rvi.pPsmList = pPsmList;
    RtlCopyMemory(&rvi.serviceClass, pServiceClassUuid, sizeof(GUID));

    for (prv = m_RecordValidatorList.GetHead();
         prv != NULL;
         prv = m_RecordValidatorList.GetNext(prv)) {

        if (prv->flags & RVFI_STREAM) {
            rvi.pStream = pStream;
            rvi.streamSize = streamSize;
        }
        else {
            rvi.pStream = NULL;
            rvi.streamSize = 0;
        }

        if (prv->flags & RVFI_TREE) {
            rvi.pTreeRoot = pTreeRoot;
        }
        else {
            rvi.pTreeRoot = NULL;
        }

        status = prv->pValidator(prv->pContext,
                                 &rvi,
                                 flags);

        if (!NT_SUCCESS(status)) {
            break;
        }
    }

    m_RecordValidatorList.Unlock();

    return status;
}
#endif // UNDER_CE

#define SERVICE_SECURITY_ENCRYPT_BOTH (SERVICE_SECURITY_ENCRYPT_REQUIRED | SERVICE_SECURITY_ENCRYPT_OPTIONAL)
#define SERVICE_SECURITY_AUTH_TYPES (SERVICE_SECURITY_NONE | SERVICE_SECURITY_AUTHORIZE | SERVICE_SECURITY_AUTHENTICATE)


// NTSTATUS SdpDatabase::AddRecord(PIRP pIrp, PHANDLE pHandle, ULONG *pfService)
NTSTATUS SdpDatabase::AddRecord(PUCHAR pStream, ULONG streamSize, PHANDLE pHandle, ServiceRecord *pRecordOriginal)  // UNDER_CE
{
    NTSTATUS        status;
    PUCHAR          pNewStream = NULL;
    ULONG           newStreamSize = 0;
    ServiceRecord*  pRecord = NULL;
    ULONG           count, size;
    PSDP_NODE       pCont = NULL;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    BOOLEAN         protIsMux;
    stack = IoGetCurrentIrpStackLocation(pIrp);
    inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
    
    if (stack->Parameters.DeviceIoControl.IoControlCode ==
        IOCTL_BTH_SDP_SUBMIT_RECORD_WITH_INFO) {
        BthSdpRecord*       pBthSdpRecord;

        if (inLen < sizeof(BthSdpRecord)) {
            return STATUS_INVALID_BUFFER_SIZE;
        }

        pBthSdpRecord = (BthSdpRecord *) pIrp->AssociatedIrp.SystemBuffer;
        pStream = pBthSdpRecord->record;
        streamSize = pBthSdpRecord->recordLength;

        //
        // Validity check for all IN params
        //
        // Make sure only the supported flags are being sent
        //
        if ((pBthSdpRecord->fCodService & ~COD_SERVICE_VALID_MASK) != 0             ||
            (pBthSdpRecord->fSecurity & ~SERVICE_SECURITY_VALID_MASK) != 0   ||
            (pBthSdpRecord->fOptions & ~SERVICE_OPTION_VALID_MASK) != 0) {
            return STATUS_INVALID_PARAMETER;
        }

        fSecurity = pBthSdpRecord->fSecurity;

        //
        // Only bthport controls the limited discovery bit
        //
        if (fSecurity & COD_SERVICE_LIMITED) {
            _DbgPrintF(DBG_SDP_ERROR,
                       ("clients are not allowed to set limited COD service"));
            return STATUS_INVALID_PARAMETER;
        }

        //
        // Make sure exclusive flags are not being sent together
        //
        if ((fSecurity & SERVICE_SECURITY_ENCRYPT_BOTH) ==
            SERVICE_SECURITY_ENCRYPT_BOTH) {
            _DbgPrintF(
                DBG_SDP_ERROR,
                ("encryption can only be required or optional, not both!"));
            return STATUS_INVALID_PARAMETER;
        }

        //              
        // To have an encrypted channel, you must be authenticated first
        //
        if ((fSecurity & SERVICE_SECURITY_ENCRYPT_BOTH) != 0 && 
            (fSecurity & SERVICE_SECURITY_AUTHENTICATE) == 0) {
            _DbgPrintF(DBG_SDP_ERROR, ("encryption requires authentication"));
            return STATUS_INVALID_PARAMETER;
        }

        //
        // Check to see that only one of the AUTH security flags is set.  If more
        // than one flag is set, then subtracting one will not create the logical
        // and inverse of itself.  For instance:
        //  0x101 & (0x101-1) == 0x100 ... invalid
        //  0x100 & (0x100-1) == 0x000 ... valid
        //
        if (((fSecurity & SERVICE_SECURITY_AUTH_TYPES) &
             ((fSecurity & SERVICE_SECURITY_AUTH_TYPES) - 1)) != 0) {
            _DbgPrintF(DBG_SDP_ERROR,
                       ("more than one authentication type was specified"));
            return STATUS_INVALID_PARAMETER;
        }

        //
        // Make sure the size reported in the structure is the size of the
        // stream buffer
        //
        if (inLen - (sizeof(BthSdpRecord) - sizeof(pBthSdpRecord->record)) !=
            streamSize) {
            _DbgPrintF(
                DBG_SDP_ERROR,
                ("BthSdpRecord::recordLength (%d) does not match buffer"
                 " size (%d)", streamSize,
                 inLen - (sizeof(BthSdpRecord) - sizeof(pBthSdpRecord->record))
                 ));
            return STATUS_INVALID_PARAMETER;
        }

        fService = pBthSdpRecord->fCodService;
        fOptions = pBthSdpRecord->fOptions;

                if (fOptions & SERVICE_OPTION_PERMANENT) {
            _DbgPrintF(DBG_SDP_ALL,
                       ("%c%cpermanent records are not yet supported!", 7, 7));
        }
    }
    else {
        pStream = (UCHAR *) pIrp->AssociatedIrp.SystemBuffer;
        streamSize = inLen;
        fSecurity = SERVICE_SECURITY_USE_DEFAULTS; 
        fService = 0;
        fOptions = 0;
    }
#endif

    //
    // Make sure it is well formed (ie a sequence of ushort (attrib id) + one
    // element (attrib value)
    //
    status = SdpIsStreamRecord(pStream, streamSize);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Make sure all of the universal attributes have the correct syntax and 
    // that all of the attributes we require locally are present
    //
    USHORT err = 0xFFFF;
    status = SdpVerifyServiceRecord(pStream,
                                    streamSize, 
                                    VERIFY_CHECK_MANDATORY_LOCAL,
                                    &err);

    if (!NT_SUCCESS(status)) {
        return status;
    }
    
    PSDP_NODE tree = NULL;
    PSDP_NODE uint32;
    PVOID pv = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -