📄 btsdp.cpp
字号:
NTSTATUS
SdpInterface::VerifyServiceSearch(
SdpQueryUuid *pUuids,
UCHAR *pMaxUuids
)
{
//
// Verify that the entries are all well formed
//
GUID zeroGuid;
RtlZeroMemory(&zeroGuid, sizeof(GUID));
UCHAR i = 0;
for (i = 0; i < MAX_UUIDS_IN_QUERY; i++, (*pMaxUuids)++)
{
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
if (0 == memcmp(&pUuids[i].u.uuid128,&zeroGuid,sizeof(GUID)))
break;
#else
if (RtlCompareMemory(&pUuids[i].u.uuid128,
&zeroGuid,
sizeof(GUID)) == sizeof(GUID)) {
break;
}
#endif
if (pUuids[i].uuidType != SDP_ST_UUID128 &&
pUuids[i].uuidType != SDP_ST_UUID32 &&
pUuids[i].uuidType != SDP_ST_UUID16) {
return STATUS_INVALID_PARAMETER;
}
}
if (*pMaxUuids == 0) {
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
}
PSDP_NODE
SdpInterface::CreateServiceSearchTree(
SdpQueryUuid *pUuids,
UCHAR maxUuids
)
/*++
Given an array of SdpQueryUuids, create an SDP tree that represents the
data within it so that later we can create a stream.
--*/
{
PSDP_NODE pTree;
PSDP_NODE pNode, pSequence;
pTree = SdpCreateNodeTree();
if (pTree == NULL) {
return NULL;
}
pSequence = SdpCreateNodeSequence();
if (pSequence == NULL) {
SdpFreeTree(pTree);
return NULL;
}
SdpAppendNodeToContainerNode(pTree, pSequence);
ULONG invalidUuid = 0;
#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"InvalidUUID",
&tmp,
sizeof(ULONG))) && tmp != 0) {
invalidUuid = 1;
SdpPrint(0, ("***UPF*** using an invalid UUID for search\n"));
}
ZwClose(hKey);
}
#endif // UPF
for (UCHAR i = 0; i < maxUuids; i++) {
if (pUuids[i].uuidType == SDP_ST_UUID128) {
pNode = SdpCreateNodeUUID128(&pUuids[i].u.uuid128);
}
else if (pUuids[i].uuidType == SDP_ST_UUID32) {
if (invalidUuid) {
pNode = SdpCreateNodeUInt32(pUuids[i].u.uuid32);
}
else {
pNode = SdpCreateNodeUUID32(pUuids[i].u.uuid32);
}
}
else {
// SDP_ST_UUID16
if (invalidUuid) {
pNode = SdpCreateNodeUInt16(pUuids[i].u.uuid16);
}
else {
pNode = SdpCreateNodeUUID16(pUuids[i].u.uuid16);
}
}
if (pNode == NULL) {
SdpFreeTree(pTree);
pTree = NULL;
break;
}
else {
SdpAppendNodeToContainerNode(pSequence, pNode);
}
}
return pTree;
}
NTSTATUS
SdpInterface::VerifyAttributeSearch(
SdpAttributeRange *pRange,
ULONG *pMaxRange,
ULONG_PTR bufferLength
)
{
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
*pMaxRange = 0;
#endif
//
// Must be in even mulitples of SdpAttributeRange
//
if ((bufferLength % sizeof(SdpAttributeRange)) != 0) {
return STATUS_INVALID_BUFFER_SIZE;
}
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
*pMaxRange = (ULONG) (bufferLength / sizeof(SdpAttributeRange));
#endif
ULONG i = 0;
USHORT minAttrib = 0;
for ( ; i < *pMaxRange; i++) {
if (pRange[i].maxAttribute < pRange[i].minAttribute) {
return STATUS_INVALID_PARAMETER;
}
//
// We now know that pRange[i].minAttribute <= pRange[i].maxAttribute
//
if (i != 0 && pRange[i].minAttribute <= minAttrib) {
return STATUS_INVALID_PARAMETER;
}
minAttrib = pRange[i].maxAttribute;
}
return STATUS_SUCCESS;
}
PSDP_NODE
SdpInterface::CreateAttributeSearchTree(
SdpAttributeRange *pRange,
ULONG maxRange
)
/*++
Given an array of SdpAttributeRange elements, convert them into an SDP tree
so that we can later convert the tree into a stream
--*/
{
ULONG i = 0;
PSDP_NODE pTree;
PSDP_NODE pNode, pSequence;
pTree = SdpCreateNodeTree();
if (pTree == NULL) {
return NULL;
}
pSequence = SdpCreateNodeSequence();
if (pSequence == NULL) {
SdpFreeTree(pTree);
return NULL;
}
SdpAppendNodeToContainerNode(pTree, pSequence);
for ( ; i < maxRange; i++) {
if (pRange[i].minAttribute == pRange[i].maxAttribute) {
pNode = SdpCreateNodeUInt16(pRange[i].minAttribute);
}
else {
ULONG tmp = pRange[i].minAttribute;
//
// move the value into the high word
//
tmp <<= 16;
pNode = SdpCreateNodeUInt32(tmp | pRange[i].maxAttribute );
}
if (pNode == NULL) {
SdpFreeTree(pTree);
pTree = NULL;
break;
}
SdpAppendNodeToContainerNode(pSequence, pNode);
}
return pTree;
}
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
NTSTATUS
SdpInterface::AcquireConnectionInternal(
SdpConnection *pCon,
PVOID tag
)
{
if (pCon) {
NTSTATUS status = STATUS_SUCCESS;
KIRQL irql;
pCon->LockState(&irql);
if (pCon->channelState == SdpChannelStateClosed) {
status = STATUS_DEVICE_NOT_CONNECTED;
}
pCon->UnlockState(irql);
if (NT_SUCCESS(status)) {
return pCon->Acquire(tag);
}
return status;
}
else {
return STATUS_INVALID_PARAMETER;
}
}
NTSTATUS
SdpInterface::AcquireConnection(
PVOID hConnection,
SdpConnection** ppCon,
PVOID tag
)
/*++
Finds an active SdpConnection based on the handle to the connection. If
a valid connection is returned, it will have been Acquired with tag
--*/
{
NTSTATUS status;
m_SdpConnectionList.Lock();
*ppCon = FindConnection(hConnection);
status = AcquireConnectionInternal(*ppCon, tag);
m_SdpConnectionList.Unlock();
return status;
}
NTSTATUS
SdpInterface::AcquireConnection(
const bt_addr& btAddress,
SdpConnection** ppCon,
PVOID tag
)
/*++
Finds an active SdpConnection based on the address of the connection. If
a valid connection is returned, it will have been Acquired with tag
--*/
{
NTSTATUS status;
m_SdpConnectionList.Lock();
*ppCon = FindConnection(btAddress);
status = AcquireConnectionInternal(*ppCon, tag);
m_SdpConnectionList.Unlock();
return status;
}
NTSTATUS SdpInterface::Connect(PIRP pIrp, ULONG_PTR& info)
{
SdpConnection *pCon, *pConFind;
BthSdpConnect tmpConnect, *pConnect;
BthConnect *pBthConnect;
PIO_STACK_LOCATION stack;
HANDLE hConnection;
NTSTATUS status;
ULONG inLen, outLen;
KIRQL irql;
hConnection = NULL;
stack = IoGetCurrentIrpStackLocation(pIrp);
info = 0;
inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
//
// DJH: remove the check for BthConnect later
//
CAssertF(sizeof(BthSdpConnect) != sizeof(BthConnect));
if ((inLen != sizeof(BthSdpConnect) && outLen != sizeof(BthSdpConnect)) &&
(inLen != sizeof(BthConnect) && outLen != sizeof(BthConnect))) {
return STATUS_BUFFER_TOO_SMALL;
}
if (inLen == sizeof(BthSdpConnect)) {
pConnect = (BthSdpConnect*) pIrp->AssociatedIrp.SystemBuffer;
}
else {
pBthConnect = (BthConnect*) pIrp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(&tmpConnect, sizeof(tmpConnect));
tmpConnect.btAddress = pBthConnect->btAddress;
tmpConnect.fSdpConnect = 0;
tmpConnect.requestTimeout = SDP_REQUEST_TO_DEFAULT;
pConnect = &tmpConnect;
}
if ((pConnect->requestTimeout != SDP_REQUEST_TO_DEFAULT) &&
(pConnect->requestTimeout < SDP_REQUEST_TO_MIN ||
pConnect->requestTimeout > SDP_REQUEST_TO_MAX)) {
return STATUS_INVALID_PARAMETER;
}
if (pConnect->fSdpConnect & ~SDP_CONNECT_VALID_FLAGS) {
return STATUS_INVALID_PARAMETER;
}
if (pConnect->fSdpConnect & SDP_CONNECT_CACHE) {
SdpPrint(SDP_DBG_CONFIG_WARNING,
("Connect, cached searches not implemented yet!\n"));
}
pCon = new (NonPagedPool, SDPI_TAG) SdpConnection(m_pDevice, TRUE);
if (pCon == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
else if (pCon->Init() == FALSE) {
delete pCon;
return STATUS_INSUFFICIENT_RESOURCES;
}
m_SdpConnectionList.Lock();
pConFind = FindConnection(pConnect->btAddress);
if (pConFind) {
pConFind->Acquire(pIrp);
SdpPrint(SDP_DBG_CONFIG_WARNING, ("Connect, found a connection\n"));
if (pConFind->IsClient()) {
SdpPrint(SDP_DBG_CONFIG_WARNING | SDP_DBG_CONFIG_ERROR,
("Connect, connection is a client\n"));
}
else {
SdpPrint(SDP_DBG_CONFIG_WARNING | SDP_DBG_CONFIG_INFO,
("Connect, connection is a server\n"));
}
}
else {
SdpPrint(SDP_DBG_CONFIG_INFO, ("Connect, did not find a connection\n"));
}
BOOLEAN useExistingConnection = FALSE;
status = STATUS_SUCCESS;
if (pConFind) {
if (pConFind->IsClient()) {
useExistingConnection = TRUE;
m_SdpConnectionList.Unlock();
if (pConFind->closing == FALSE) {
pConFind->LockState(&irql);
if (pConFind->channelState == SdpChannelStateConnecting) {
IoMarkIrpPending(pIrp);
pCon->connectList.AddTail(pIrp);
status = STATUS_PENDING;
}
pConFind->UnlockState(irql);
//
// We will complete this irp when the connection is finalized or if
// the connection dies
//
if (status == STATUS_PENDING) {
return status;
}
if (pConFind->AddFileObject(stack->FileObject)) {
hConnection = pConFind->hConnection;
status = STATUS_SUCCESS;
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
else {
status = STATUS_DELETE_PENDING;
}
}
else {
pCon->btAddress = pConnect->btAddress;
SdpPrint(SDP_DBG_CONFIG_TRACE,
("Adding new server connection %p to connection list\n",
pCon));
m_SdpConnectionList.AddTail(pCon);
m_SdpConnectionList.Unlock();
}
pConFind->Release(pIrp);
}
else {
//
// Either there were no active connections to this address or there is a
// client connection
//
pCon->btAddress = pConnect->btAddress;
SdpPrint(SDP_DBG_CONFIG_TRACE,
("Adding new client connection %p to connection list\n", pCon));
m_SdpConnectionList.AddTail(pCon);
m_SdpConnectionList.Unlock();
}
//
// If we found a connection and it is still alive, delete our temp connection
// object and return
//
if (useExistingConnection) {
delete pCon;
if (NT_SUCCESS(status)) {
if (outLen == sizeof(BthSdpConnect)) {
RtlZeroMemory(pConnect, sizeof(*pConnect));
pConnect->hConnection = hConnection;
info = sizeof(*pConnect);
}
else {
// DJH: remove me later
RtlZeroMemory(pBthConnect, sizeof(*pBthConnect));
pBthConnect->hConnection = hConnection;
info = sizeof(*pBthConnect);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -