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

📄 btsdpcon.cpp

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

   BTSDP.CPP

Abstract:

    This module implemnts BTh SDP core spec.



   Doron Holan 

   Notes:

   Environment:

   Kernel mode only


Revision History:

*/

#include "common.h"
#include "sdplib.h"

#define SDPI_TAG 'IpdS'

extern SdpDatabase *pSdpDB;

#define SDPC_TAG 'CpdS'

#define SDP_DEFAULT_TIMEOUT 30      // in seconds
#define SDP_SCAN_INTERVAL 1

#if  ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
LIST_ENTRY SdpConnection::_TimeoutListHead;
KSPIN_LOCK SdpConnection::_TimeoutListLock;
KTIMER SdpConnection::_TimeoutTimer;
KDPC SdpConnection::_TimeoutTimerDpc;
#endif

#if UPF
USHORT GetMaxByteCount(USHORT inMtu)
{
    HANDLE hKey;
    USHORT rVal = 0;
    if (NT_SUCCESS(BthPort_OpenKey(NULL,
                                   STR_REG_MACHINE STR_SOFTWARE_KEYW,
                                   &hKey))) {
        ULONG tmp = 0;
        if (NT_SUCCESS(QueryKeyValue(hKey,
                                     L"OverrideMaxByteCount",
                                     &tmp,
                                     sizeof(ULONG))) && tmp != 0) {
            rVal = (USHORT) tmp;
        }

        ZwClose(hKey);
    }

    if (rVal == 0) {
        //
        // Compute max byte count by taking the maximum buffer the server can send me
        // and taking out all the fixed fields
        //
        rVal = (USHORT) inMtu -
                                (sizeof(SdpPDU)    +
                                 sizeof(USHORT)    + // AttribyteListsByteCount
                                 sizeof(UCHAR));     // cont state of zero
    }
    else {
        SdpPrint(0, ("***UPF*** overrding max byte count with %d\n", (ULONG) rVal));
    }

    return rVal;
}
#else
//
// USHORT =  AttribyteListsByteCount
// UCHAR  =  cont state of zero
//
#define GetMaxByteCount(mbc) ((USHORT) (mbc) - (sizeof(SdpPDU) + sizeof(USHORT) + sizeof(UCHAR)))
#endif // UPF



NTSTATUS
SendBrbCompletion(
    PDEVICE_OBJECT DeviceObject, 
    PIRP Irp,
    PVOID Context
    );

#if SDP_VERBOSE
NTSTATUS TestWalkStream(PVOID Context, UCHAR DataType, ULONG DataSize, PUCHAR Stream);
#endif


// On WinCE we malloc blocks of these structs at a time, so the constructor is never called.
SdpConnection::SdpConnection(BThDevice *pDev, BOOLEAN isClient)  
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    : fileObjectList(), clientQueue(), channelState(SdpChannelStateClosed),
    pDevice(pDev), client(isClient)
#endif
{
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    ZERO_THIS();
    _DbgPrintF(DBG_SDP_TRACE, ("SdpConnection created 0x%x", this));

    InitializeListHead(&entry);
    KeInitializeSpinLock(&stateSpinLock);
    IoInitializeRemoveLock(&remLock, 0, 0, 0);
    
    clientQueue.SetQueueCancelRoutine(_QueueCancelRoutine, this);

    Acquire(REASON(AcquireCreate));
#endif  // UNDER_CE
}

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
void
SdpConnection::ReleaseAndProcessNextRequest(
    PIRP pIrp
    )
{
    PIRP pNextRequest = NULL;
     
    clientQueue.RemoveIfAvailable(&pNextRequest);

    //
    // pNextRequest already has a reference taken out on this connection, so 
    // this object is still valid if there is another request
    //
    Release(pIrp);

    if (pNextRequest) {
        PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pNextRequest);
        switch (stack->Parameters.DeviceIoControl.IoControlCode) {
        case IOCTL_BTH_SDP_SERVICE_SEARCH:
            SendServiceSearchRequest(pIrp);
            break;

        case IOCTL_BTH_SDP_ATTRIBUTE_SEARCH:
            SendAttributeSearchRequest(pIrp);
            break;

        case IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH:
            SendServiceSearchAttributeRequest(pIrp);
            break;

        default:
            ASSERT(FALSE);
        }
    }
}

void SdpConnection::ReleaseAndWait()
{
    IoReleaseRemoveLockAndWait(&remLock, REASON(AcquireCreate));
}
#endif

SdpConnection::~SdpConnection()
{
    SdpPrint(SDP_DBG_CON_TRACE, ("SdpConnection destroyed %p\n", this));

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    CompletePendingConnectRequests(STATUS_UNSUCCESSFUL);

        if (pReadBuffer) {
        ExFreePool(pReadBuffer);
        pReadBuffer = NULL;
    }

    if (pReadIrp) {
        IoFreeIrp(pReadIrp);
        pReadIrp = NULL;
    }

    if (pWriteIrp) {
        IoFreeIrp(pWriteIrp);
        pWriteIrp = NULL;
    }

    if (pReadBrb) {
        delete pReadBrb;
        pReadBrb = NULL;
    }
#endif    
}

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
BOOLEAN SdpConnection::Init()
{
    pReadIrp = IoAllocateIrp(pDevice->m_Struct.FunctionalDeviceObject->StackSize+1, FALSE);
    pWriteIrp = IoAllocateIrp(pDevice->m_Struct.FunctionalDeviceObject->StackSize+1, FALSE);

    pReadBrb = new (NonPagedPool, SDPC_TAG) BRB;

    return (pReadIrp != NULL) && (pWriteIrp != NULL);
}

void
SdpConnection::FireWmiEvent(
    SDP_SERVER_LOG_TYPE Type,
    PVOID Buffer,
    ULONG Length
    )
{
#ifdef SDP_LOGGING
    PSDP_SERVER_LOG_INFO pLog;
    ULONG size = sizeof(*pLog) + Length -1;

    pLog = (PSDP_SERVER_LOG_INFO)
        ExAllocatePoolWithTag(PagedPool, size, SDPC_TAG);

    if (pLog) {
        RtlZeroMemory(pLog, size);

        pLog->type = Type;
        pLog->info.btAddress = btAddress;
        pLog->mtu = outMtu;
        pLog->dataLength = Length;
        RtlCopyMemory(pLog->data, Buffer, Length);

        WmiFireEvent(pDevice->m_Struct.FunctionalDeviceObject,
                     (LPGUID) &GUID_BTHPORT_WMI_SDP_SERVER_LOG_INFO,
                     0,
                     size,
                     pLog);
    }
#endif // SDP_LOGGING
}

void
SdpConnection::FireWmiEvent(
    SDP_SERVER_LOG_TYPE Type,
    const bt_addr& Address,
    USHORT Mtu
    )
{
#ifdef SDP_LOGGING
    PSDP_SERVER_LOG_INFO pLog;

    pLog = (PSDP_SERVER_LOG_INFO)
        ExAllocatePoolWithTag(PagedPool, sizeof(*pLog), SDPI_TAG);

    if (pLog) {
        RtlZeroMemory(pLog, sizeof(*pLog));

        pLog->type = Type;
        pLog->info.btAddress = Address;
        pLog->mtu = Mtu;
        pLog->dataLength = 0;

        WmiFireEvent(pDevice->m_Struct.FunctionalDeviceObject,
                     (LPGUID) &GUID_BTHPORT_WMI_SDP_SERVER_LOG_INFO,
                     0,
                     sizeof(*pLog),
                     pLog);
    }
#endif SDP_LOGGING
}

BOOLEAN
SdpConnection::AddFileObject(PFILE_OBJECT pFileObject)
{
    FileObjectEntry *pEntry = new(PagedPool, SDPC_TAG) FileObjectEntry(pFileObject);

    if (pEntry == NULL) {
        return FALSE;
    }

    ASSERT(closing == FALSE);

    _DbgPrintF(DBG_SDP_INFO, ("Adding file object %p\n", pEntry));

    fileObjectList.AddTail(pEntry);

    InterlockedIncrement(&createCount);
    ASSERT(createCount > 0);

    return TRUE;
}

LONG
SdpConnection::RemoveFileObject(PFILE_OBJECT pFileObject)
{
    FileObjectEntry *pEntry = FindFileObject(pFileObject);
    if (pEntry == NULL) {
        //
        // Somebody send a disconnect for a connection they did not own
        //
        return -1;
    }

    return RemoveFileObject(pEntry);
}


LONG
SdpConnection::RemoveFileObject(FileObjectEntry *pEntry)
{
    ULONG c;

    ASSERT(closing == FALSE);

    _DbgPrintF(DBG_SDP_INFO, ("Removing file object %p\n", pEntry));

    fileObjectList.RemoveAt(pEntry);
    delete pEntry;

    c = InterlockedDecrement(&createCount);

    if (c == 0) {
        _DbgPrintF(DBG_SDP_INFO, ("Closing on %p is TRUE\n", this));
        closing = TRUE;
        ASSERT(fileObjectList.IsEmpty());
    }

    return c;
}

FileObjectEntry *
SdpConnection::FindFileObject(
    PFILE_OBJECT pFileObject
    )
{
    FileObjectEntry *pEntry;
    for (pEntry = fileObjectList.GetHead();
         pEntry != NULL;
         pEntry = fileObjectList.GetNext(pEntry)) {
        if (pEntry->pFileObject == pFileObject) {
            return pEntry;
        }
    }

    return NULL;
}

void
SdpConnection::Cleanup(
    PFILE_OBJECT pFileObject
    )
{
    PIRP irp;
    CIRP_LIST list;

    clientQueue.Cleanup(&list, pFileObject);

    while (!list.IsEmpty()) {
        irp = list.RemoveHead();

        Release(irp);

        irp->IoStatus.Information = 0;
        irp->IoStatus.Status = STATUS_CANCELLED;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }
}

BOOLEAN
SdpConnection::SetupReadBuffer()
{
    pReadBuffer = ExAllocatePoolWithTag(NonPagedPool, inMtu, SDPC_TAG);
    return pReadBuffer != NULL;
}

BOOLEAN
SdpConnection::InMtuDone(
    USHORT mtu
    )
{
    KIRQL irql;
    BOOLEAN resp = FALSE;

    LockState(&irql);

    SdpPrint(SDP_DBG_CONFIG_INFO, ("InMtuDone, %d\n", mtu));

    inMtu = mtu;
    configInDone = TRUE;
    if (configOutDone) {
        SdpPrint(SDP_DBG_CONFIG_INFO, ("all done!\n"));
        channelState = SdpChannelStateOpen;
        configInDone = configOutDone = FALSE;
        resp = TRUE;
    }
    else {
        SdpPrint(SDP_DBG_CONFIG_INFO, ("waiting for out!\n"));
    }

    UnlockState(irql);

    return resp;
}

BOOLEAN
SdpConnection::OutMtuDone(
    USHORT mtu
    )
{
    KIRQL irql;
    BOOLEAN resp = FALSE;

    LockState(&irql);

    SdpPrint(SDP_DBG_CONFIG_INFO, ("OutMtuDone, %d\n", mtu));

    if (mtu == 0) {
        mtu = L2CAP_DEFAULT_MTU;
        SdpPrint(SDP_DBG_CONFIG_INFO, ("Converting 0 to default mtu (%d)\n", (ULONG) mtu));
    }

    outMtu = mtu;
    configOutDone = TRUE;
    if (configInDone) {
        SdpPrint(SDP_DBG_CONFIG_INFO, ("all done!\n"));
        channelState = SdpChannelStateOpen;
        configInDone = configOutDone = FALSE;
        resp = TRUE;
    }
    else {
        SdpPrint(SDP_DBG_CONFIG_INFO, ("waiting for in!\n"));
    }

    UnlockState(irql);

    return resp;
}

BOOLEAN SdpConnection::FinalizeConnection()
{
    NTSTATUS status;
    BOOLEAN disconnect = FALSE;

    if (SetupReadBuffer() == FALSE) {
        SdpPrint(SDP_DBG_CONFIG_ERROR | SDP_DBG_CONFIG_WARNING,
                 ("FinalizeConnection, config done, no buffers!\n"));
        disconnect = TRUE;
    }
    else if (IsClient()) {
        SdpPrint(SDP_DBG_CONFIG_INFO,
                 ("FinalizeConnection, completing all pended connect requests\n"));

        CompletePendingConnectRequests(STATUS_SUCCESS);
    }
    else {
        //
        // We are the server in this connection, send down a read to

⌨️ 快捷键说明

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