📄 sdpdbserver.cpp
字号:
}
}
}
}
//
// clean up
//
while (!hl.IsEmpty()) {
phe = hl.RemoveHead();
delete phe;
}
return status;
}
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
NTSTATUS
SdpDatabase::ServiceSearchRequestResponseCached(
HANDLE hDeviceCache,
SdpQueryUuid *pUuid,
UCHAR numUuid,
USHORT maxRecordsRequested,
ULONG **ppResultStream, // must be freed when xmit is finished
USHORT *pRecordCount
)
{
NTSTATUS status;
SdpUuidSearch uuidSrch;
SDP_ERROR sdpError;
ULONG sizeFull, sizePartial;
ULONG numValues;
USHORT numFound;
PKEY_FULL_INFORMATION pKeyFullInfo;
PKEY_VALUE_PARTIAL_INFORMATION pKeyPartialInfo;
PUCHAR pFull, pPartial;
PAGED_CODE();
uuidSrch.SetUuids(pUuid, numUuid);
SdpPrint(SDP_DBG_UUID_TRACE, ("ServiceSearchRequestResponseCached enter\n"));
*ppResultStream = NULL;
*pRecordCount = 0;
numFound = 0;
status = STATUS_SUCCESS;
sizeFull = 0;
status = ZwQueryKey(hDeviceCache, KeyFullInformation, NULL, 0, &sizeFull);
if (!NT_SUCCESS(status)) {
}
pFull = new (PagedPool) UCHAR[sizeFull];
pKeyFullInfo = (PKEY_FULL_INFORMATION) pFull;
if (pKeyFullInfo == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
status = ZwQueryKey(hDeviceCache, KeyFullInformation, pKeyFullInfo, sizeFull, &sizeFull);
if (!NT_SUCCESS(status)) {
delete[] pFull;
return status;
}
// MaxValueDataLen
sizePartial = pKeyFullInfo->MaxValueDataLen +
sizeof (KEY_VALUE_PARTIAL_INFORMATION);
pPartial = new (PagedPool) UCHAR[sizePartial];
pKeyPartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION) pPartial;
numValues = pKeyFullInfo->Values;
//
// Iterate over each cached record. If ALL the UUIDs in the search are found
// then report the search record back to the requestor
//
HandleList hl;
HandleEntry *phe;
for (ULONG i = 0; i < numValues; i++) {
ULONG size;
status = ZwEnumerateValueKey(hDeviceCache,
i,
KeyValuePartialInformation,
pKeyPartialInfo,
sizePartial,
&size);
if (NT_SUCCESS(status)) {
PUCHAR pStream = pKeyPartialInfo->Data;
ULONG sizeStream = pKeyPartialInfo->DataLength;
USHORT id;
status = ValidateStream(pStream, sizeStream, NULL);
if (!NT_SUCCESS(status)) {
continue;
}
status = SdpVerifyServiceRecord(pStream,
sizeStream,
VERIFY_CHECK_MANDATORY_REMOTE,
&id);
if (!NT_SUCCESS(status)) {
continue;
}
if (uuidSrch.SearchStream(pStream, sizeStream)) {
PUCHAR pStreamHandle;
ULONG sizeHandle;
status = SdpFindAttributeInStream(pStream,
sizeStream,
SDP_ATTRIB_RECORD_HANDLE,
&pStreamHandle,
&sizeHandle);
if (NT_SUCCESS(status)) {
ASSERT(sizeHandle == sizeof(ULONG) + sizeof(UCHAR));
pStreamHandle++;
sizeHandle--;
ULONG recordHandle;
RtlRetrieveUlong(&recordHandle, pStreamHandle);
recordHandle = RtlUlongByteSwap(recordHandle);
SdpPrint(SDP_DBG_UUID_INFO,
("uuid search, FOUND match in cached record %08x\n",
recordHandle));
phe = new (PagedPool, SDP_TAG) HandleEntry(recordHandle);
if (phe) {
hl.AddTail(phe);
numFound++;
}
//
// Found as many as the requestor asked for
//
if (numFound == maxRecordsRequested) {
break;
}
}
}
}
}
if (numFound > 0) {
PULONG pResult;
//
// TODO: I can optimize this by just returning the linked list and then
// pulling values off of that instead of allocating pool again here
//
pResult = (ULONG *) ExAllocatePoolWithTag(NonPagedPool,
numFound * sizeof(ULONG),
SDP_TAG);
*ppResultStream = pResult;
if (*ppResultStream == NULL) {
SdpPrint(SDP_DBG_UUID_ERROR,
("could not alloc pool for a cached ServiceSearch response\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
}
else {
*pRecordCount = numFound;
phe = hl.GetHead();
ASSERT(hl.GetCount() == numFound);
for (USHORT i = 0; i < numFound; i++, phe = hl.GetNext(phe)) {
pResult[i] = phe->handle;
}
}
}
//
// clean up
//
while (!hl.IsEmpty()) {
phe = hl.RemoveHead();
delete phe;
}
if (pFull) {
delete[] pFull;
pFull = NULL;
pKeyFullInfo = NULL;
}
if (pPartial) {
delete[] pPartial;
pPartial = NULL;
pKeyPartialInfo = NULL;
}
return status;
}
#endif // UNDER_CE
struct SdpAttribSearch {
SdpAttribSearch() { ZERO_THIS(); }
~SdpAttribSearch()
{
if (pRange && ownRange) {
delete[] pRange;
pRange = NULL;
}
}
void SetAttributes(SdpAttributeRange *pOrigRange, ULONG numRange)
{
ownRange = FALSE;
pRange = pOrigRange;
numAttributes = numRange;
}
NTSTATUS RetrieveAttributes(PUCHAR pStream, ULONG streamSize);
NTSTATUS FindElements(PUCHAR pStream,
ULONG streamSize,
PSDP_STREAM_ENTRY *ppEntry,
PSDP_ERROR pSdpError)
{
PAGED_CODE();
return SdpFindAttributeSequenceInStream(
pStream,
streamSize,
pRange,
numAttributes,
ppEntry,
pSdpError);
}
static NTSTATUS CountAttributesInSearchStreamWalk(
SdpAttribSearch * pAttribSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize);
static NTSTATUS RetrieveAttributesInSearchStreamWalk(
SdpAttribSearch *pAttribSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize);
SdpAttributeRange *pRange;
ULONG numAttributes;
ULONG currentAttribute;
USHORT minAttrib;
BOOLEAN ownRange;
};
NTSTATUS SdpAttribSearch::RetrieveAttributes(PUCHAR pStream, ULONG streamSize)
{
PAGED_CODE();
NTSTATUS status;
status = SdpVerifySequenceOf(
pStream,
streamSize,
SDP_TYPE_UINT,
NULL,
NULL,
(PSDP_STREAM_WALK_FUNC) CountAttributesInSearchStreamWalk,
(PVOID) this);
if (!NT_SUCCESS(status)) {
return status;
}
else if (numAttributes == 0) {
return STATUS_INVALID_PARAMETER;
}
ownRange = TRUE;
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
pRange = new (NonPagedPool, 'ApdS') SdpAttributeRange[numAttributes];
#else
pRange = new SdpAttributeRange[numAttributes];
if (pRange)
memset(pRange,0,sizeof(SdpAttributeRange)*numAttributes);
#endif
if (pRange == NULL) {
SdpPrint(SDP_DBG_ATTRIB_ERROR, ("could not alloc pool for a range list\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
return SdpVerifySequenceOf(
pStream,
streamSize,
SDP_TYPE_UINT,
NULL,
NULL,
(PSDP_STREAM_WALK_FUNC) RetrieveAttributesInSearchStreamWalk,
(PVOID) this);
}
NTSTATUS
SdpAttribSearch::CountAttributesInSearchStreamWalk(
SdpAttribSearch *pAttribSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize
)
{
PAGED_CODE();
if (DataSize == sizeof(USHORT)) {
USHORT uint16;
RtlRetrieveUshort(&uint16, Data);
uint16 = RtlUshortByteSwap(uint16);
if (pAttribSrch->numAttributes != 0 && uint16 <= pAttribSrch->minAttrib) {
SdpPrint(SDP_DBG_ATTRIB_ERROR, ("out of order attrib search (single attrib)\n"));
return STATUS_INVALID_PARAMETER;
}
pAttribSrch->minAttrib = uint16;
pAttribSrch->numAttributes++;
}
else if (DataSize == sizeof(ULONG)) {
ULONG uint32;
USHORT minAttrib, maxAttrib;
RtlRetrieveUlong(&uint32, Data);
uint32 = RtlUlongByteSwap(uint32);
minAttrib = (USHORT) ((uint32 & 0xFFFF0000) >> 16);
maxAttrib = (USHORT) (uint32 & 0xFFFF);
if (maxAttrib <= minAttrib) {
//
// max is less than min???
//
SdpPrint(SDP_DBG_ATTRIB_ERROR, ("out of order attrib search (range attrib)\n"));
return STATUS_INVALID_PARAMETER;
}
else if (pAttribSrch->numAttributes != 0 &&
minAttrib <= pAttribSrch->minAttrib) {
//
// ranges are overlapping
//
SdpPrint(SDP_DBG_ATTRIB_ERROR, ("overlapping attrib search\n"));
return STATUS_INVALID_PARAMETER;
}
pAttribSrch->minAttrib = maxAttrib;
pAttribSrch->numAttributes++;
}
else {
SdpPrint(SDP_DBG_ATTRIB_ERROR, ("wrong size int (%d)\n", DataSize));
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
}
NTSTATUS
SdpAttribSearch::RetrieveAttributesInSearchStreamWalk(
SdpAttribSearch *pAttribSrch,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize
)
{
PAGED_CODE();
if (DataType != SDP_TYPE_UINT) {
return STATUS_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -