📄 btsdp.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:
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;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
SdpInterface* pSdp = NULL;
#endif
USHORT SDP_DEFAULT_MTU = 1024;
#define CONFIG_RETRY_DEFAULT (5)
BOOLEAN ContinuationState::Read(UCHAR *pStream, ULONG streamSize)
{
// PAGED_CODE();
size = *pStream;
// check for out of range size
if (size > 16) {
return FALSE;
}
// cont state always at end, so size must match
if (size != (streamSize - 1)) {
return FALSE;
}
if (size) {
memcpy(state, pStream + 1, size);
}
return TRUE;
}
void ContinuationState::Write(UCHAR *pStream)
{
// PAGED_CODE();
*pStream = size;
if (size) {
memcpy(pStream + 1, state, size);
}
}
void ContinuationState::Init(PVOID p)
{
size = sizeof(p);
RtlCopyMemory(state, &p, size);
}
PVOID SdpPDU::Read(PVOID pBuffer)
/*++
Reads an SDP PDU header from the stream and returns an unaligned pointer
to the beginning of the data in the packet
PDU format is
byte 1: PDU id
byte 2-3: PDU transaction id
byte 4-5: PDU parameter length (the remaining size of the buffer)
PDU is in network byte order so we must byte swap the >1 byte values so that
they make sense
--*/
{
PUCHAR stream = (PUCHAR) pBuffer;
pduId = *stream;
stream++;
RtlRetrieveUshort(&transactionId, stream);
transactionId = RtlUshortByteSwap(transactionId);
stream += sizeof(transactionId);
RtlRetrieveUshort(¶meterLength, stream);
parameterLength = RtlUshortByteSwap(parameterLength);
stream += sizeof(parameterLength);
return (PVOID) stream;
}
PUCHAR SdpPDU::Write(PUCHAR pBuffer)
/*++
Writes out an SDP PDU header to the unaligned buffer.
--*/
{
#if DBG
PUCHAR pOrig = pBuffer;
#endif
USHORT tmp;
*pBuffer = pduId;
pBuffer++;
tmp = RtlUshortByteSwap(transactionId);
RtlCopyMemory(pBuffer, &tmp, sizeof(tmp));
pBuffer += sizeof(tmp);
#if UPF
HANDLE hKey;
if (NT_SUCCESS(BthPort_OpenKey(NULL,
STR_REG_MACHINE STR_SOFTWARE_KEYW,
&hKey))) {
ULONG tmp = 0;
if (NT_SUCCESS(QueryKeyValue(hKey,
L"InvalidPDU",
&tmp,
sizeof(ULONG))) && tmp != 0) {
SdpPrint(0, ("***UPF*** using an invalid pdu size (orig %d, override %d) for search\n",
(ULONG) parameterLength, (ULONG) parameterLength * 2));
parameterLength *= 2;
}
ZwClose(hKey);
}
#endif // UPF
tmp = RtlUshortByteSwap(parameterLength);
RtlCopyMemory(pBuffer, &tmp, sizeof(tmp));
pBuffer += sizeof(tmp);
#if DBG
//
// Make sure that we did our pointer math correctly
//
ASSERT(pBuffer - pOrig == sizeof(*this));
#endif DBG
return pBuffer;
}
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
NTSTATUS
SendBrbCompletion(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
/*++
Simple completion routine which sets an event so we can send an irp synch
--*/
{
if (Context != NULL) {
KeSetEvent((PKEVENT) Context, 0, FALSE);
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
SdpInterface::SdpInterface()
{
IoInitializeRemoveLock(&m_RemoveLock, 'DSTB', 0, 0);
IoAcquireRemoveLock(&m_RemoveLock, (PVOID)-1);
}
SdpInterface::~SdpInterface()
{
SdpConnection *pCon;
CList<SdpConnection, FIELD_OFFSET(SdpConnection, entry)> list;
SdpPrint(SDP_DBG_CONFIG_TRACE, ("~SdpInterface\n"));
//
// There should never be any connections in our list when we are destroyed
// because they should have all been cleared out when we were Stop()'ed
//
m_SdpConnectionList.Lock();
ASSERT(m_SdpConnectionList.IsEmpty());
while (!m_SdpConnectionList.IsEmpty()) {
pCon = m_SdpConnectionList.RemoveHead();
list.AddTail(pCon);
}
m_SdpConnectionList.Unlock();
while (!list.IsEmpty()) {
pCon = list.RemoveHead();
delete pCon;
}
}
NTSTATUS SdpInterface::Start(BThDevice *pBthDevice)
{
m_pDevice = pBthDevice;
m_pDevice->AddRef();
return STATUS_SUCCESS;
}
NTSTATUS SdpInterface::Stop()
/*++
Iterates over the active connection list and terminates each one
--*/
{
m_pDevice->Release();
_DbgPrintF(DBG_PNP_INFO, ("SDP: waiting on remlock %p\n", &m_RemoveLock));
IoReleaseRemoveLockAndWait(&m_RemoveLock, (PVOID)-1);
return STATUS_SUCCESS;
}
SdpConnection*
SdpInterface::FindConnection(
PVOID hConnection
)
/*++
Assumes that the list has been locked. Will return an SdpConnection based
on the passed in hConnection.
--*/
{
SdpConnection *pCon;
for (pCon = m_SdpConnectionList.GetHead();
pCon != NULL;
pCon = m_SdpConnectionList.GetNext(pCon)) {
if (pCon->hConnection == hConnection) {
SdpPrint(SDP_DBG_CON_INFO,
("found SdpConnection %p for connection %p\n",
pCon, hConnection));
return pCon;
}
}
SdpPrint(SDP_DBG_CON_WARNING,
("found no SdpConnection for connection %p\n", hConnection));
return NULL;
}
SdpConnection*
SdpInterface::FindConnection(
const bt_addr& address,
BOOLEAN onlyServer
)
/*++
Assumes that the list has been locked. Will return an SdpConnection based
on the passed in address. If onlyServer is TRUE, then an SdpConnection
will only be returned f
--*/
{
SdpConnection *pCon;
for (pCon = m_SdpConnectionList.GetHead();
pCon != NULL;
pCon = m_SdpConnectionList.GetNext(pCon)) {
if (pCon->btAddress == address &&
( !onlyServer || (onlyServer && pCon->IsServer()) ) ) {
SdpPrint(SDP_DBG_CON_INFO,
("found SdpConnection %p for address %04x%08x\n",
pCon, GET_NAP(address), GET_SAP(address)));
return pCon;
}
}
SdpPrint(SDP_DBG_CON_WARNING,
("found no SdpConnection for address %04x%08x\n",
GET_NAP(address), GET_SAP(address)));
return NULL;
}
void
SdpInterface::FireWmiEvent(
SDP_SERVER_LOG_TYPE Type,
bt_addr *pAddress,
USHORT Mtu
)
/*++
Fires a WMI event if SDP_LOGGING is defined
--*/
{
#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;
if (pAddress) {
pLog->info.btAddress = *pAddress;
}
pLog->mtu = Mtu;
pLog->dataLength = 0;
WmiFireEvent(m_pDevice->m_Struct.FunctionalDeviceObject,
(LPGUID) &GUID_BTHPORT_WMI_SDP_SERVER_LOG_INFO,
0,
sizeof(*pLog),
pLog);
}
#endif SDP_LOGGING
}
NTSTATUS SdpInterface::SendBrb(PBRB pBrb)
/*++
Sends a BRB synchronously down the stack.
--*/
{
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
PIRP irp =
IoAllocateIrp(m_pDevice->m_Struct.FunctionalDeviceObject->StackSize,
FALSE);
if (irp) {
PIO_STACK_LOCATION stack;
KEVENT event;
stack = IoGetNextIrpStackLocation(irp);
stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
stack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_BTH_SUBMIT_BRB;
stack->Parameters.Others.Argument1 = pBrb;
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
IoSetCompletionRoutine(irp,
SendBrbCompletion,
(PVOID) &event,
TRUE,
TRUE,
TRUE);
status = IoCallDriver(m_pDevice->m_Struct.FunctionalDeviceObject, irp);
if (status == STATUS_PENDING) {
SdpPrint(SDP_DBG_BRB_INFO,
("SendBrb pended, waiting on event %p for BRB %p (type %d)\n",
&event, pBrb, pBrb->BrbHeader.Type));
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
SdpPrint(SDP_DBG_BRB_INFO,
("SendBrb pended, end wait on event %p\n", &event));
status = irp->IoStatus.Status;
}
IoFreeIrp(irp);
}
else {
SdpPrint(SDP_DBG_BRB_ERROR, ("SendBrb could not alloc an irp\n"));
}
SdpPrint(SDP_DBG_BRB_INFO, ("SendBrb (%p - %d) status 0x%x\n",
pBrb, pBrb->BrbHeader.Type, status));
return status;
}
NTSTATUS
SdpInterface::SendBrbAsync(
PIRP pIrp,
PBRB pBrb,
PIO_COMPLETION_ROUTINE Routine,
PVOID pContext,
PVOID pArg1,
PVOID pArg2,
PVOID pArg3,
PVOID pArg4
)
{
PIO_STACK_LOCATION stack;
KEVENT event;
NTSTATUS status;
SdpPrint(SDP_DBG_BRB_INFO, ("SendBrbAsync, irp %p, brb %p, routine %p\n",
pIrp, pBrb, Routine));
IoReuseIrp(pIrp, STATUS_SUCCESS);
stack = IoGetNextIrpStackLocation(pIrp);
stack->Parameters.Others.Argument1 = pArg1;
stack->Parameters.Others.Argument2 = pArg2;
stack->Parameters.Others.Argument3 = pArg3;
stack->Parameters.Others.Argument4 = pArg4;
IoSetNextIrpStackLocation(pIrp);
stack = IoGetNextIrpStackLocation(pIrp);
stack->Parameters.Others.Argument1 = pBrb;
stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
stack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_BTH_SUBMIT_BRB;
IoSetCompletionRoutine(pIrp,
Routine,
pContext,
TRUE,
TRUE,
TRUE);
status = IoCallDriver(m_pDevice->m_Struct.FunctionalDeviceObject, pIrp);
SdpPrint(SDP_DBG_BRB_INFO, ("SendBrbAsync returns 0x%x\n", status));
return status;
}
#endif // UNDER_CE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -