📄 node.cpp
字号:
case SDP_TYPE_LISTHEAD:
InsertTailList(&Parent->hdr.Link, &Node->hdr.Link);
break;
default:
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
}
ULONG GetListLength(PLIST_ENTRY Head)
{
PLIST_ENTRY current;
ULONG size = 0;
current = Head->Flink;
while (1) {
size++;
current = current->Flink;
if (current == Head) {
return size;
}
}
}
NTSTATUS SdpFreeTree(PSDP_NODE Tree)
{
if (Tree->hdr.Type != SDP_TYPE_LISTHEAD) {
return STATUS_INVALID_PARAMETER;
}
if (!IsListEmpty(&Tree->hdr.Link)) {
SdpFreeNode(CONTAINING_RECORD(Tree->hdr.Link.Flink, SDP_NODE, hdr.Link));
}
if (Tree->Reserved != NULL) {
DecrementNodeRef((PSDP_NODE_REF) Tree->Reserved);
}
else {
//
// We have freed everything that is attached to this, free it
//
SdpFreePool(Tree);
}
return STATUS_SUCCESS;
}
NTSTATUS SdpFreeOrphanedNode(PSDP_NODE Node)
{
SDP_NODE tmpHead;
SdpInitializeNodeTree(&tmpHead);
SdpAppendNodeToContainerNode(&tmpHead, Node);
return SdpFreeNode(Node);
}
NTSTATUS SdpFreeNode(PSDP_NODE Node)
{
SdpStack stack;
SD_STACK_ENTRY *stackEntry;
PLIST_ENTRY current;
PSDP_NODE node;
current = &Node->hdr.Link;
while (1) {
node = CONTAINING_RECORD(current, SDP_NODE, hdr.Link);
if ((node->hdr.Type == SDP_TYPE_SEQUENCE ||
node->hdr.Type == SDP_TYPE_ALTERNATIVE)
&&
(!IsListEmpty(&node->u.sequence.Link) ||
!IsListEmpty(&node->u.alternative.Link))
) {
if (!NT_SUCCESS(stack.Push(node))) {
//
// recover as gracefully as possible
//
return STATUS_INSUFFICIENT_RESOURCES;
}
if (node->hdr.Type == SDP_TYPE_ALTERNATIVE) {
current = node->u.alternative.Link.Flink;
}
else {
current = node->u.sequence.Link.Flink;
}
continue;
}
//
// Advance to the next link in the list
//
current = current->Flink;
//
// Remove the node from the list.
//
RemoveEntryList(&node->hdr.Link);
// When a container is created by a user APP, it doesn't matter what
// its SpecificType is, most likely it will by SDP_ST_NONE. In the
// SdpInitializeNodeContainer we set Type=SDP_TYPE_CONTAINER and
// SpecificType = SDP_ST_CONTAINER_STREAM and have this be a pointer
// to a stream, rather than an ISdpNodeContainer. In this case we
// can't release ISdpNodeContainer object.
if ((node->hdr.Type == SDP_TYPE_CONTAINER) && (node->hdr.SpecificType != SDP_ST_CONTAINER_STREAM)) {
// hitting this ASSERT shouldn't be harmful, but it means someone is
// setting up their node in an unexpected way (and possibly wrong way),
// needs investigation.
SVSUTIL_ASSERT((node->hdr.SpecificType == SDP_ST_CONTAINER_INTERFACE) || (node->hdr.SpecificType == SDP_ST_NONE));
SdpReleaseContainer(node->u.container);
}
//
// Finally, free the node
//
if (node->Reserved == NULL) {
SdpFreePool(node);
} else {
DecrementNodeRef((PSDP_NODE_REF) node->Reserved);
}
//
// Check to see if we have reached the end of the linked list
//
while (IsListEmpty(current)) {
//
// Check to see if we have pushed any items. If not, then we are
// done.
//
if (stack.Depth() == 0) {
return STATUS_SUCCESS;
}
//
// Get the stored values. Since we are now removing an node,
// decrement size.
//
stackEntry = stack.Pop();
node = stackEntry->Node;
//
// Get the next link in the chain before removing the node from the
// list
//
current = node->hdr.Link.Flink;
RemoveEntryList(&node->hdr.Link);
//
// Finally, free the node
//
if (node->Reserved == NULL) {
SdpFreePool(node);
} else {
DecrementNodeRef((PSDP_NODE_REF) node->Reserved);
}
}
}
}
NTSTATUS SdpAddAttributeToNodeHeader(PSDP_NODE_HEADER Header, USHORT AttribId, PSDP_NODE AttribValue)
{
PSDP_NODE nodeId, nodeValue, attrib;
PLIST_ENTRY current;
nodeId = CONTAINING_RECORD(Header->Link.Flink, SDP_NODE, hdr.Link);
nodeValue = CONTAINING_RECORD(nodeId->hdr.Link.Flink, SDP_NODE, hdr.Link);
current = &nodeValue->hdr.Link;
//
// iterate over the attribute id / value pairs in the list and see where
// this entry goes.
//
// Attribute IDs are added in increasing numerical order!
//
while (1) {
//
// Do the following
// 1 make sure we have a USHORT node AND
// 2 if we are replacing a value OR
// 3 if we are inserting a value OR
// 4 going to the next pair in the list AND
// 5 checking if we are at the end of the list, and if so, appending
// the pair
//
// Initial insertion
if (IsListEmpty(&Header->Link)) {
if (AttribValue == NULL) {
return STATUS_NOT_FOUND;
}
attrib = SdpCreateNodeUInt16(AttribId);
if (attrib == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
InsertTailList(&Header->Link, &attrib->hdr.Link);
InsertTailList(&Header->Link, &AttribValue->hdr.Link);
return STATUS_SUCCESS;
}
//
// Check to see if we have a valid attrib id node
//
else if (nodeId->hdr.Type != SDP_TYPE_UINT ||
nodeId->hdr.SpecificType != SDP_ST_UINT16 ||
nodeId->DataSize != sizeof(AttribId)) {
return STATUS_INVALID_PARAMETER;
}
else if (AttribId == nodeId->u.uint16) {
//
// We are replacing or removing a value
//
//
// Remove the value from the tree in both cases
//
RemoveEntryList(&nodeValue->hdr.Link);
SdpFreeOrphanedNode(nodeValue);
//
// Check to see if we are removing
//
if (AttribValue == NULL) {
//
// Remove the ID as well
//
RemoveEntryList(&nodeId->hdr.Link);
SdpFreeOrphanedNode(nodeId);
}
else {
InsertEntryList(&nodeId->hdr.Link, &AttribValue->hdr.Link);
}
return STATUS_SUCCESS;
}
else if (AttribId < nodeId->u.uint16) {
//
// We are inserting a value into the middle of the list
//
//
// Must have a valid AttribValue in this case
//
if (AttribValue == NULL) {
return STATUS_INVALID_PARAMETER;
}
attrib = SdpCreateNodeUInt16(AttribId);
if (attrib == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// hdr.Link in the attribute ID before the current entry and
// then link in the attribute value after the newly placed
// ID
//
InsertEntryList(nodeId->hdr.Link.Blink, &attrib->hdr.Link);
InsertEntryList(&attrib->hdr.Link, &AttribValue->hdr.Link);
return STATUS_SUCCESS;
}
else {
current = current->Flink;
//
// Check to see if we have wrapped to the end of the list. If
// so, insert the ID / value pair at the end of the list
//
if (current == &Header->Link) {
if (AttribValue == NULL) {
return STATUS_NOT_FOUND;
}
attrib = SdpCreateNodeUInt16(AttribId);
if (attrib == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
InsertTailList(&Header->Link, &attrib->hdr.Link);
InsertTailList(&Header->Link, &AttribValue->hdr.Link);
return STATUS_SUCCESS;
}
else {
nodeId = CONTAINING_RECORD(current, SDP_NODE, hdr.Link);
ASSERT(nodeId->hdr.Type != SDP_TYPE_LISTHEAD);
current = current->Flink;
nodeValue = CONTAINING_RECORD(current, SDP_NODE, hdr.Link);
}
}
}
}
NTSTATUS SdpAddAttributeToTree(PSDP_NODE Root, USHORT AttribId, PSDP_NODE AttribValue)
{
PSDP_NODE attrib, sequence;
if (IsListEmpty(&Root->hdr.Link)) {
if (AttribValue == NULL) {
return STATUS_INVALID_PARAMETER;
}
sequence = SdpCreateNodeSequence();
SdpAppendNodeToContainerNode((PSDP_NODE) Root, sequence);
}
else {
sequence = CONTAINING_RECORD(Root->hdr.Link.Flink, SDP_NODE, hdr.Link);
}
if (sequence->hdr.Type != SDP_TYPE_SEQUENCE) {
return STATUS_INVALID_PARAMETER;
}
if (IsListEmpty(&sequence->u.sequence.Link)) {
if (AttribValue == NULL) {
return STATUS_INVALID_PARAMETER;
}
attrib = SdpCreateNodeUInt16(AttribId);
if (attrib == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
SdpAppendNodeToContainerNode(sequence, attrib);
SdpAppendNodeToContainerNode(sequence, AttribValue);
return STATUS_SUCCESS;
}
else {
// PLIST_ENTRY current;
// PSDP_NODE nodeId, nodeValue;
if ((GetListLength(&sequence->u.sequence.Link) % 2) != 0) {
//
// Invalid list, must be a multiple of 2
//
return STATUS_INVALID_PARAMETER;
}
return SdpAddAttributeToNodeHeader(&sequence->u.sequence, AttribId, AttribValue);
}
}
void DecrementNodeRef(PSDP_NODE_REF NodeRef)
{
if (SdpInterlockedDecrement(&NodeRef->RefCount) == 0) {
SdpFreePool(NodeRef->Alloc);
SdpFreePool(NodeRef);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -