📄 btsdpcon.cpp
字号:
// retrieve the client's search request
//
SdpPrint(SDP_DBG_CONFIG_INFO,
("L2CA_ConfigInd, we are a server, acquire and read\n"));
status = Acquire(pReadIrp);
if (NT_SUCCESS(status)) {
SdpPrint(SDP_DBG_CONFIG_INFO,
("L2CA_ConfigInd, acquire and read succes\n"));
FireWmiEvent(SdpServerLogTypeConnect, btAddress, outMtu);
ReadAsync();
}
else {
SdpPrint(SDP_DBG_CONFIG_ERROR | SDP_DBG_CONFIG_WARNING,
("L2CA_ConfigInd, acquire and read not successful, 0x%x\n",
status));
disconnect = TRUE;
}
}
return disconnect;
}
void SdpConnection::CompletePendingConnectRequests(NTSTATUS status)
{
CList<IRP, IRP_LE_OFFSET> irps;
KIRQL irql;
LockState(&irql);
while (!connectList.IsEmpty()) {
irps.AddTail(connectList.RemoveHead());
}
UnlockState(irql);
while (!irps.IsEmpty()) {
PIRP irp = irps.RemoveHead();
irp->IoStatus.Status = status;
if (NT_SUCCESS(status)) {
BthSdpConnect *pConnect;
BthConnect *pBthConnect;
pConnect = NULL;
pBthConnect = NULL;
// DJH: remove me later
if (IoGetCurrentIrpStackLocation(irp)->
Parameters.DeviceIoControl.OutputBufferLength ==
sizeof(BthSdpConnect)) {
pConnect = (BthSdpConnect*) irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(pConnect, sizeof(BthSdpConnect));
pConnect->hConnection = hConnection;
irp->IoStatus.Information = sizeof(BthSdpConnect);
}
else {
pBthConnect = (BthConnect*) irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(pBthConnect, sizeof(BthConnect));
pBthConnect->hConnection = hConnection;
irp->IoStatus.Information = sizeof(BthConnect);
}
AddFileObject(IoGetCurrentIrpStackLocation(irp)->FileObject);
}
else {
irp->IoStatus.Information = 0;
}
SdpPrint(SDP_DBG_CONFIG_INFO,
("Completing connect request %p with status 0x%x\n",
irp, status));
Release(irp);
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
}
VOID
SdpConnection::_QueueCancelRoutine(
PVOID Context,
PIRP Irp
)
{
((SdpConnection *) Context)->Release(Irp);
}
#endif // UNDER_CE
NTSTATUS
SdpConnection::SendServiceSearchRequest(
PIRP pIrp
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
, SdpServiceSearch *pSearch
#endif
)
{
// BthSdpServiceSearchRequest *pSearch;
// PIO_STACK_LOCATION stack;
PSDP_NODE pTree = NULL;
PUCHAR stream = NULL, tmpStream;
ULONG streamSize = 0;
NTSTATUS status;
// ULONG outlen;
USHORT maxHandles, totalSize;
UCHAR maxUuids;
ContinuationState cs;
SdpPDU pdu;
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
maxHandles = pSearch->cMaxHandles;
maxUuids = (UCHAR) pSearch->cUUIDs;
pTree = SdpInterface::CreateServiceSearchTree(pSearch->uuids,maxUuids);
#else
stack = IoGetCurrentIrpStackLocation(pIrp);
maxHandles = (USHORT)
(stack->Parameters.DeviceIoControl.OutputBufferLength / sizeof(ULONG));
maxUuids = GetMaxUuidsFromIrp(pIrp);
pSearch = (BthSdpServiceSearchRequest *) pIrp->AssociatedIrp.SystemBuffer;
pTree = SdpInterface::CreateServiceSearchTree(pSearch->uuids, maxUuids);
#endif
if (pTree == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
status = SdpStreamFromTreeEx(pTree,
&stream,
&streamSize,
sizeof(SdpPDU),
sizeof(maxHandles) + sizeof(cs));
//
// Our initial request does not have a continuation state, BUT if we get
// a partial response, we need to send request w/a cont state, so just
// alloc room for it now
//
totalSize = sizeof(SdpPDU) +
(USHORT) streamSize +
sizeof(maxHandles) +
sizeof(cs.size);
SdpFreeTree(pTree);
pTree = NULL;
if (!NT_SUCCESS(status)) {
goto Error;
}
if (totalSize > outMtu) {
//
// Can't xmit the request, sigh
//
status = STATUS_UNSUCCESSFUL;
goto Error;
}
pdu.pduId = SdpPDU_ServiceSearchRequest;
pdu.transactionId = transactionId++;
pdu.parameterLength = totalSize - sizeof(SdpPDU);
//
// Write the PDU, then skip over the already written stream
//
tmpStream = pdu.Write(stream);
//
// increment past already writen search pattern
//
tmpStream += streamSize;
maxHandles = RtlUshortByteSwap(maxHandles);
RtlCopyMemory(tmpStream, &maxHandles, sizeof(maxHandles));
tmpStream += sizeof(maxHandles);
ASSERT(cs.size == 0);
cs.Write(tmpStream);
#if DBG
tmpStream += cs.GetTotalSize();
ASSERT((tmpStream - stream) == totalSize);
#endif
SdpPrint(SDP_DBG_CLIENT_INFO, ("sending initial request for service search\n"));
return SendInitialRequestToServer(pIrp, stream, totalSize, pdu.pduId);
Error:
if (pTree) {
SdpFreeTree(pTree);
}
if (stream) {
ExFreePool(stream);
}
ReleaseAndProcessNextRequest(pIrp);
return status;
}
NTSTATUS
SdpConnection::SendAttributeSearchRequest(
PIRP pIrp
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
, SdpAttributeSearch *pSearch
#endif
)
{
// BthSdpAttributeSearchRequest *pSearch;
PSDP_NODE pTree = NULL;
PUCHAR stream = NULL, tmpStream;
NTSTATUS status;
ULONG streamSize = 0, recordHandle; // maxRange
USHORT totalSize;
SdpPDU pdu;
ContinuationState cs;
USHORT maxByteCount;
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
recordHandle = RtlUlongByteSwap(pSearch->recordHandle);
pTree = SdpInterface::CreateAttributeSearchTree(pSearch->range,
pSearch->numAttributes);
#else
maxRange = GetMaxRangeFromIrp(pIrp);
pSearch = (BthSdpAttributeSearchRequest *) pIrp->AssociatedIrp.SystemBuffer;
pTree = SdpInterface::CreateAttributeSearchTree(pSearch->range, maxRange);
#endif
if (pTree == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
//
// Our initial request does not have a continuation state, BUT if we get
// a partial response, we need to send request w/a cont state, so just
// alloc room for it now by allocating sizeof(cs) instead of sizeof(cs.size)
//
status = SdpStreamFromTreeEx(pTree,
&stream,
&streamSize,
sizeof(SdpPDU) + sizeof(recordHandle) + sizeof(maxByteCount),
sizeof(cs));
totalSize = sizeof(SdpPDU) +
sizeof(recordHandle) +
sizeof(maxByteCount) +
(USHORT) streamSize +
sizeof(cs.size);
SdpFreeTree(pTree);
pTree = NULL;
if (!NT_SUCCESS(status)) {
goto Error;
}
if (totalSize > outMtu) {
//
// Can't xmit the request
//
status = STATUS_UNSUCCESSFUL;
goto Error;
}
// if (g_Support10B) {
// maxByteCount = 0xFFFF;
// }
// else {
// maxByteCount = GetMaxByteCount(inMtu);
// }
maxByteCount = GetMaxByteCount(inMtu);
pdu.pduId = SdpPDU_ServiceAttributeRequest;
pdu.transactionId = transactionId++;
pdu.parameterLength = totalSize - sizeof(SdpPDU);
//
// Write the PDU, then skip over the already written stream
//
tmpStream = pdu.Write(stream);
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
// This is done at top of fcn for WinCE
recordHandle = RtlUlongByteSwap(pSearch->recordHandle);
#endif
RtlCopyMemory(tmpStream, &recordHandle, sizeof(recordHandle));
tmpStream += sizeof(recordHandle);
maxByteCount = RtlUshortByteSwap(maxByteCount);
RtlCopyMemory(tmpStream, &maxByteCount, sizeof(maxByteCount));
tmpStream += sizeof(maxByteCount);
tmpStream += streamSize;
ASSERT(cs.size == 0);
cs.Write(tmpStream);
#if DBG
tmpStream += cs.GetTotalSize();
ASSERT((tmpStream - stream) == totalSize);
#endif // DBG
SdpPrint(SDP_DBG_CLIENT_INFO, ("sending initial request for attribute search\n"));
return SendInitialRequestToServer(pIrp, stream, totalSize, pdu.pduId);
Error:
if (pTree) {
SdpFreeTree(pTree);
}
if (stream) {
ExFreePool(stream);
}
ReleaseAndProcessNextRequest(pIrp);
return status;
}
NTSTATUS
SdpConnection::SendServiceSearchAttributeRequest(
PIRP pIrp
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
, SdpServiceAttributeSearch *pSearch
#endif
)
{
// BthSdpServiceAttributeSearchRequest *pSearch;
PSDP_NODE pTreeService = NULL, pTreeAttrib = NULL;
PUCHAR stream = NULL, tmpStream;
NTSTATUS status;
ULONG maxRange, streamSize, serviceSize, attribSize;
int totalSize;
USHORT maxByteCount;
UCHAR maxUuids;
SdpPDU pdu;
ContinuationState cs;
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
ASSERT(pSearch->cUUIDs <= MAX_UUIDS_IN_QUERY);
maxUuids = (UCHAR) pSearch->cUUIDs;
maxRange = pSearch->numAttributes;
#else
maxUuids = GetMaxUuidsFromIrp(pIrp);
maxRange = GetMaxRangeFromIrp(pIrp);
pSearch = (BthSdpServiceAttributeSearchRequest *)
pIrp->AssociatedIrp.SystemBuffer;
#endif
pTreeService =
SdpInterface::CreateServiceSearchTree(pSearch->uuids, maxUuids);
if (pTreeService == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
pTreeAttrib = SdpInterface::CreateAttributeSearchTree(pSearch->range, maxRange);
if (pTreeAttrib == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Error;
}
status = ComputeNodeListSize(
ListEntryToSdpNode(SdpNode_GetNextEntry(pTreeService)),
&serviceSize);
if (!NT_SUCCESS(status)) {
goto Error;
}
status = ComputeNodeListSize(
ListEntryToSdpNode(SdpNode_GetNextEntry(pTreeAttrib)),
&attribSize);
if (!NT_SUCCESS(status)) {
goto Error;
}
status = SdpStreamFromTreeEx(pTreeService,
&stream,
&streamSize,
sizeof(SdpPDU),
sizeof(maxByteCount) + attribSize + sizeof(cs));
if (!NT_SUCCESS(status)) {
goto Error;
}
status =
NodeToStream(
ListEntryToSdpNode(SdpNode_GetNextEntry(pTreeAttrib)),
stream + sizeof(SdpPDU) + serviceSize + sizeof(maxByteCount) );
if (!NT_SUCCESS(status)) {
goto Error;
}
SdpFreeTree(pTreeService);
SdpFreeTree(pTreeAttrib);
pTreeService = NULL;
pTreeAttrib = NULL;
totalSize = sizeof(SdpPDU) +
serviceSize +
sizeof(maxByteCount) +
attribSize +
sizeof(cs.size);
if (totalSize > outMtu) {
status = STATUS_UNSUCCESSFUL;
goto Error;
}
// if (g_Support10B) {
// maxByteCount = 0xFFFF;
// }
// else {
// maxByteCount = GetMaxByteCount(inMtu);
// }
maxByteCount = GetMaxByteCount(inMtu);
pdu.pduId = SdpPDU_ServiceSearchAttributeRequest;
pdu.transactionId = transactionId++;
pdu.parameterLength = (USHORT) (totalSize - sizeof(SdpPDU));
tmpStream = pdu.Write(stream);
//
// service search pattern was written out by the call to SdpStreamFromTreeEx
//
tmpStream += serviceSize;
maxByteCount = RtlUshortByteSwap(maxByteCount);
RtlCopyMemory(tmpStream, &maxByteCount, sizeof(maxByteCount));
tmpStream += sizeof(maxByteCount);
//
// AttributeIDList was written out by the call to NodeToStream
//
tmpStream += attribSize;
ASSERT(cs.size == 0);
cs.Write(tmpStream);
#if DBG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -