📄 sdpdb.cpp
字号:
while (!sdl.IsEmpty()) {
pRecord = sdl.RemoveHead();
delete pRecord;
}
}
#endif // defined (UNDER_CE) || defined (WINCE_EMULATION)
void SdpDatabase::AlterDatabaseState()
{
NTSTATUS status;
ULONG val, size;
PUCHAR pStream;
val = RtlUlongByteSwap(InterlockedIncrement((PLONG) &m_dbState));
//
// DB lock is held while this function is called
//
status = SdpFindAttributeInStream(m_pSdpRecord->pStream,
m_pSdpRecord->streamSize,
SDP_ATTRIB_SDP_DATABASE_STATE,
&pStream,
&size
);
//
// The stream returned is the entire element, not just the element value, so
// we need to increment beyond the header
//
ASSERT(NT_SUCCESS(status));
ASSERT(size == sizeof(val) + sizeof(UCHAR));
#if DBG
UCHAR type, sizeIndex;
SdpRetrieveHeader(pStream, type, sizeIndex);
ASSERT(type == SDP_TYPE_UINT);
ASSERT(sizeIndex == 2);
#endif // DBG
pStream++;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
KeWaitForSingleObject((PVOID) &m_dbStateSemaphore,
Executive,
KernelMode,
FALSE,
NULL);
RtlCopyMemory(pStream, &val, sizeof(val));
KeReleaseSemaphore(&m_dbStateSemaphore, (KPRIORITY) 0, 1, FALSE);
#else
RtlCopyMemory(pStream, &val, sizeof(val));
#endif
}
void SdpDatabase::FireWmiEvent(
HANDLE recordHandle,
SDP_DATABASE_EVENT_TYPE type
)
{
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
PSDP_DATABASE_EVENT pEvent = (PSDP_DATABASE_EVENT)
ExAllocatePoolWithTag(PagedPool, sizeof(*pEvent), SDP_TAG);
if (pEvent) {
DeviceLE *ple;
pEvent->type = type;
pEvent->handle = recordHandle;
m_DeviceList.Lock();
ple = m_DeviceList.GetHead();
if (ple) {
WmiFireEvent(ple->device,
(LPGUID) &GUID_BTHPORT_WMI_SDP_DATABASE_EVENT,
0,
sizeof(*pEvent),
pEvent);
}
else {
ExFreePool(pEvent);
}
m_DeviceList.Unlock();
}
#endif // defined (UNDER_CE) || defined (WINCE_EMULATION)
}
NTSTATUS SdpDatabase::AddProtMux(GUID *protocol)
{
ProtMux * ppm, *ppmIter;
NTSTATUS status = STATUS_SUCCESS;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
ppm = new(NonPagedPool, PM_TAG) ProtMux(protocol);
#else
ppm = new ProtMux(protocol);
#endif
if (ppm) {
m_ServiceRecordList.Lock();
for (ppmIter = m_ProtMuxList.GetHead();
ppmIter != NULL;
ppmIter = m_ProtMuxList.GetNext(ppmIter)) {
if (IsEqualUuid(protocol, &ppmIter->protocol)) {
status = STATUS_OBJECT_NAME_COLLISION;
break;
}
}
if (NT_SUCCESS(status)) {
m_ProtMuxList.AddTail(ppm);
m_ServiceRecordList.Unlock();
}
else {
m_ServiceRecordList.Unlock();
delete ppm;
}
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
return status;
}
NTSTATUS SdpDatabase::RemoveProtMux(GUID *protocol)
{
ProtMux *ppm;
NTSTATUS status = STATUS_NOT_FOUND;
m_ServiceRecordList.Lock();
for (ppm = m_ProtMuxList.GetHead();
ppm != NULL;
ppm = m_ProtMuxList.GetNext(ppm)) {
if (IsEqualUuid(protocol, &ppm->protocol)) {
m_ProtMuxList.RemoveAt(ppm);
break;
}
}
m_ServiceRecordList.Unlock();
if (NT_SUCCESS(status)) {
delete ppm;
}
return status;
}
BOOLEAN SdpDatabase::IsProtocolMuxed(const GUID &protocol)
{
ProtMux *ppm;
for (ppm = m_ProtMuxList.GetHead();
ppm != NULL;
ppm = m_ProtMuxList.GetNext(ppm)) {
if (IsEqualUuid(&ppm->protocol, &protocol)) {
return TRUE;
}
}
return FALSE;
}
NTSTATUS SdpDatabase::GetPsmInfo(USHORT psm, GUID *protocol, ULONG *serviceHandle)
{
ServiceRecord *pRecord;
NTSTATUS status = STATUS_NOT_FOUND;
m_ServiceRecordList.Lock();
for (pRecord = m_ServiceRecordList.GetHead();
pRecord != NULL;
pRecord = m_ServiceRecordList.GetNext(pRecord)) {
for (ULONG i = 0; i < pRecord->psmList.count; i++) {
if (psm == pRecord->psmList.list[i].psm) {
*serviceHandle = pRecord->recordHandle;
RtlCopyMemory(protocol,
&pRecord->psmList.list[i].protocol,
sizeof(GUID));
status = STATUS_SUCCESS;
break;
}
}
if (NT_SUCCESS(status)) {
break;
}
}
m_ServiceRecordList.Unlock();
return status;
}
NTSTATUS SdpDatabase::GetServiceClass(USHORT psm, GUID *serviceClass)
{
// NOTE: If this function is ever called for WinCE, be sure to make sure
// gpSdp (in sdpbase.cxx) has lock held.
ServiceRecord *pRecord;
NTSTATUS status = STATUS_NOT_FOUND;
m_ServiceRecordList.Lock();
for (pRecord = m_ServiceRecordList.GetHead();
pRecord != NULL;
pRecord = m_ServiceRecordList.GetNext(pRecord)) {
for (ULONG i = 0; i < pRecord->psmList.count; i++) {
if (psm == pRecord->psmList.list[i].psm) {
if (IsProtocolMuxed(pRecord->psmList.list[i].protocol)) {
status = STATUS_PENDING;
}
else {
RtlCopyMemory(serviceClass,
&pRecord->serviceClass,
sizeof(GUID));
status = STATUS_SUCCESS;
}
break;
}
}
if (NT_SUCCESS(status)) {
break;
}
}
m_ServiceRecordList.Unlock();
return status;
}
ULONG SdpDatabase::GetNextRecordHandle()
{
ULONG handle = (ULONG) InterlockedIncrement(&m_nextRecordHandle);
if (handle == 0) {
//
// we have wrapped, goto the start, then increment
//
// ISSUE: we should really find a hole in the records list, but we
// worry about that when the time comes
//
#if defined (UNDER_CE)
InterlockedCompareExchange((LONG*)&m_nextRecordHandle,
INIT_HANDLE_VALUE,
0);
#else
InterlockedCompareExchange((void **)&m_nextRecordHandle,
(void *)INIT_HANDLE_VALUE,
(void *)0);
#endif
handle = (ULONG) InterlockedIncrement(&m_nextRecordHandle);
}
return handle;
}
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
extern "C"
NTSTATUS pSdpTreeFromStream(
PUCHAR Stream,
ULONG Size,
PSDP_TREE_ROOT_NODE *Node
)
{
return SdpTreeFromStream(Stream, Size, Node, TRUE);
}
NTSTATUS SdpDatabase::HandleQI(PIRP Irp)
{
PIO_STACK_LOCATION stack;
NTSTATUS status;
const GUID *pInterfaceType;
status = Irp->IoStatus.Status;
stack = IoGetCurrentIrpStackLocation(Irp);
pInterfaceType = stack->Parameters.QueryInterface.InterfaceType;
if (IsEqualUuid(pInterfaceType, &GUID_BTHDDI_SDP_VALIDATE_INTERFACE)) {
PBTHDDI_SDP_VALIDATE_INTERFACE pValidate = (PBTHDDI_SDP_VALIDATE_INTERFACE)
stack->Parameters.QueryInterface.Interface;
if (pValidate->Interface.Size != sizeof(*pValidate) ||
pValidate->Interface.Version < 1 ||
(pValidate->Validator != NULL &&
(pValidate->Flags & RVFI_VALID_FLAGS) == 0)) {
status = STATUS_INVALID_PARAMETER;
}
else if (pValidate->Validator == NULL) {
//
// removal
//
if (pValidate->Cookie == NULL) {
status = STATUS_INVALID_PARAMETER;
}
else {
RecordValidator *prv;
m_RecordValidatorList.Lock();
for (prv = m_RecordValidatorList.GetHead();
prv != NULL;
prv = m_RecordValidatorList.GetNext(prv)) {
if ((PVOID) prv == pValidate->Cookie) {
m_RecordValidatorList.RemoveAt(prv);
break;
}
}
m_RecordValidatorList.Unlock();
if (prv) {
status = STATUS_SUCCESS;
delete prv;
}
else {
status = STATUS_NOT_FOUND;
}
}
}
else {
RecordValidator *prv =
new(NonPagedPool, RV_TAG) RecordValidator(pValidate);
if (prv == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
}
else {
m_RecordValidatorList.Lock();
m_RecordValidatorList.AddTail(prv);
m_RecordValidatorList.Unlock();
status = STATUS_SUCCESS;
}
}
}
else if (IsEqualUuid(pInterfaceType, &GUID_BTHDDI_SDP_PARSE_INTERFACE)) {
PBTHDDI_SDP_PARSE_INTERFACE pParse = (PBTHDDI_SDP_PARSE_INTERFACE)
stack->Parameters.QueryInterface.Interface;
if (pParse->Interface.Size != sizeof(*pParse) ||
pParse->Interface.Version < 1) {
status = STATUS_INVALID_PARAMETER;
}
else {
status = STATUS_SUCCESS;
pParse->SdpValidateStream = SdpDatabase::ValidateStream;
pParse->SdpWalkStream = SdpWalkStream;
pParse->SdpConvertStreamToTree = pSdpTreeFromStream;
pParse->SdpConvertTreeToStream = SdpStreamFromTree;
pParse->SdpByteSwapUuid128 = SdpByteSwapUuid128;
pParse->SdpByteSwapUint128 = SdpByteSwapUint128;
pParse->SdpByteSwapUint64 = SdpByteSwapUint64;
pParse->SdpRetrieveUuid128 = SdpRetrieveUuid128;
pParse->SdpRetrieveUint128 = SdpRetrieveUint128;
pParse->SdpRetrieveUint64 = SdpRetrieveUint64;
pParse->SdpFindAttribute = SdpFindAttributeInStream;
pParse->SdpFindAttributeSequence = SdpFindAttributeSequenceInStream;
pParse->SdpFindAttributeInTree = SdpFindAttributeInTree;
}
}
else if (IsEqualUuid(pInterfaceType, &GUID_BTHDDI_SDP_NODE_INTERFACE)) {
PBTHDDI_SDP_NODE_INTERFACE pNode = (PBTHDDI_SDP_NODE_INTERFACE)
stack->Parameters.QueryInterface.Interface;
if (pNode->Interface.Size != sizeof(*pNode) ||
pNode->Interface.Version < 1) {
status = STATUS_INVALID_PARAMETER;
}
else {
pNode->SdpCreateNodeTree = SdpCreateNodeTree;
pNode->SdpFreeTree = SdpFreeTree;
pNode->SdpCreateNodeNil = SdpCreateNodeNil;
pNode->SdpCreateNodeBoolean = SdpCreateNodeBoolean;
pNode->SdpCreateNodeUint8 = SdpCreateNodeUInt8;
pNode->SdpCreateNodeUint16 = SdpCreateNodeUInt16;
pNode->SdpCreateNodeUint32 = SdpCreateNodeUInt32;
pNode->SdpCreateNodeUint64 = SdpCreateNodeUInt64;
pNode->SdpCreateNodeUint128 = SdpCreateNodeUInt128;
pNode->SdpCreateNodeInt8 = SdpCreateNodeInt8;
pNode->SdpCreateNodeInt16 = SdpCreateNodeInt16;
pNode->SdpCreateNodeInt32 = SdpCreateNodeInt32;
pNode->SdpCreateNodeInt64 = SdpCreateNodeInt64;
pNode->SdpCreateNodeInt128 = SdpCreateNodeInt128;
pNode->SdpCreateNodeUuid16 = SdpCreateNodeUUID16;
pNode->SdpCreateNodeUuid32 = SdpCreateNodeUUID32;
pNode->SdpCreateNodeUuid128 = SdpCreateNodeUUID128;
pNode->SdpCreateNodeString = SdpCreateNodeString;
pNode->SdpCreateNodeUrl = SdpCreateNodeUrl;
pNode->SdpCreateNodeAlternative = SdpCreateNodeAlternative;
pNode->SdpCreateNodeSequence = SdpCreateNodeSequence;
pNode->SdpAddAttributeToTree = SdpAddAttributeToTree;
pNode->SdpAppendNodeToContainerNode = SdpAppendNodeToContainerNode;
status = STATUS_SUCCESS;
}
}
else if (IsEqualUuid(pInterfaceType, &GUID_BTHDDI_MUX_PROTOCOL_INTERFACE)) {
PBTH_MUX_PROTOCOL_INTERFACE pMux = (PBTH_MUX_PROTOCOL_INTERFACE)
stack->Parameters.QueryInterface.Interface;
if (pMux->Interface.Size != sizeof(*pMux) ||
pMux->Interface.Version < 1) {
status = STATUS_INVALID_PARAMETER;
}
else {
status = AddProtMux(&pMux->Protocol);
if (NT_SUCCESS(status)) {
pMux->GetSecurityInfoContext = (PVOID) Globals.pSecDB;
pMux->GetServiceConnectRequirements =
SecurityDatabase::_GetServiceConnectRequirements;
}
}
}
Irp->IoStatus.Status = status;
return status;
}
void
SdpDatabase::AddDevice(
PDEVICE_OBJECT DeviceObject
)
{
DeviceLE *ple = new (PagedPool, SDP_TAG) DeviceLE(DeviceObject);
if (ple) {
}
}
void
SdpDatabase::RemoveDevice(
PDEVICE_OBJECT DeviceObject
)
{
DeviceLE *ple = NULL;
m_DeviceList.Lock();
for (ple = m_DeviceList.GetHead();
ple != NULL;
ple = m_DeviceList.GetNext(ple)) {
if (ple->device == DeviceObject) {
m_DeviceList.RemoveAt(ple);
break;
}
}
m_DeviceList.Unlock();
if (ple) {
delete ple;
}
}
#endif // UNDER_CE
#if defined (UNDER_CE)
// Remove all entries associated with a process when it's being terminated.
void SdpDatabase::RemoveRecordsAssociatedWithProcess(HANDLE hDyingProc) {
ServiceRecord *pRecord = m_ServiceRecordList.GetHead();
m_ServiceRecordList.Lock();
while (pRecord) {
if (hDyingProc == pRecord->hCallerProc) {
ServiceRecord *pNext = m_ServiceRecordList.GetNext(pRecord);
m_ServiceRecordList.RemoveAt(pRecord);
AlterDatabaseState();
delete pRecord;
pRecord = pNext;
}
else
pRecord = m_ServiceRecordList.GetNext(pRecord);
}
m_ServiceRecordList.Unlock();
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -