📄 stream.cpp
字号:
SdpInitializeNodeInt8(node, (CHAR) *Stream);
break;
case 1:
dataSize = 2;
RtlRetrieveUshort(&uint16, Stream);
SdpInitializeNodeInt16(node, (SHORT) RtlUshortByteSwap(uint16));
break;
case 2:
dataSize = 4;
RtlRetrieveUlong(&uint32, Stream);
SdpInitializeNodeInt32(node, (LONG) RtlUlongByteSwap(uint32));
break;
case 3:
dataSize = 8;
SdpRetrieveUlonglong(&uint64, Stream);
SdpInitializeNodeInt64(node, (LONGLONG) SdpUlonglongByteSwap(uint64));
break;
case 4:
dataSize = 16;
SdpRetrieveUint128(Stream, (PSDP_ULARGE_INTEGER_16) &int128);
int128.HighPart =
(LONGLONG) SdpUlonglongByteSwap((LONGLONG) int128.HighPart);
int128.LowPart = SdpUlonglongByteSwap(int128.LowPart);
SdpInitializeNodeInt128(node, &int128);
break;
default:
ASSERT(FALSE);
return NULL;
}
LINK_IN_NODE(head, node);
INC_STREAM(dataSize);
break;
case SDP_TYPE_UUID:
//
// valid indecies are 1,2,4
//
switch (sizeIndex) {
case 1:
dataSize = 2;
RtlRetrieveUshort(&uint16, Stream);
SdpInitializeNodeUUID16(node, RtlUshortByteSwap(uint16));
break;
case 2:
dataSize = 4;
RtlRetrieveUlong(&uint32, Stream);
SdpInitializeNodeUUID32(node, RtlUlongByteSwap(uint32));
break;
case 4:
dataSize = 16;
//
// Retrieve the whole structure ...
//
SdpRetrieveUuid128(Stream, &uuid128Tmp);
//
// ... and then convert into little endian
//
SdpByteSwapUuid128(&uuid128Tmp, &uuid128);
SdpInitializeNodeUUID128(node, &uuid128);
break;
default:
ASSERT(FALSE);
return NULL;
}
LINK_IN_NODE(head, node);
INC_STREAM(dataSize);
break;
case SDP_TYPE_URL:
case SDP_TYPE_STRING:
case SDP_TYPE_SEQUENCE:
case SDP_TYPE_ALTERNATIVE:
//
// valid indecies are 5, 6 ,7
//
// Retrieve the size, convert it to little endian, and then compute
// the total size for this element (amount of storage for the size
// + the size itself).
//
// Furthermore, make sure we have enough storage for the stored size.
//
SdpRetrieveVariableSize(Stream, sizeIndex, &elementSize, &storageSize);
switch (type) {
case SDP_TYPE_URL:
SdpInitializeNodeUrl(node,
(PCHAR) Stream + storageSize,
elementSize,
ExtraPool);
ExtraPool += ROUND_SIZE(elementSize);
break;
case SDP_TYPE_STRING:
SdpInitializeNodeString(node,
(PCHAR) Stream + storageSize,
elementSize,
ExtraPool);
ExtraPool += ROUND_SIZE(elementSize);
break;
case SDP_TYPE_SEQUENCE:
case SDP_TYPE_ALTERNATIVE:
if (FullParse) {
if (type == SDP_TYPE_SEQUENCE) {
SdpInitializeNodeSequence(node);
newHead = &node->u.sequence.Link;
}
else {
SdpInitializeNodeAlternative(node);
newHead = &node->u.alternative.Link;
}
node->DataSize = elementSize;
if (elementSize > 0) {
INC_STREAM(storageSize);
status = stack.Push(node, Size, head);
if (!NT_SUCCESS(status)) {
return NULL;
}
LINK_IN_NODE(head, node);
//
// LINK_IN_NODE incremented node, so it is now pointing to a
// new and unused slot in the array
//
head = newHead;
Size = elementSize;
continue;
}
}
else {
//
// don't recurse on the container, just store the stream for
// it, including the element header (which we just incremented
// past)
//
SdpInitializeNodeContainer(
node,
Stream - 1,
elementSize + 1 // we subtracted 1 for element header above
+ storageSize
);
}
break;
}
LINK_IN_NODE(head, node);
INC_STREAM(storageSize + elementSize);
break;
default:
// there is an error in the stream
ASSERT(FALSE);
return NULL;
}
if ((int) Size < 0) {
return NULL;
}
while (Size == 0) {
//
// Check to see if we have pushed any items. If not, then we are
// done
//
if (stack.Depth() == 0) {
return Nodes;
}
stackEntry = stack.Pop();
Size = stackEntry->Size - stackEntry->Node->DataSize;
head = stackEntry->Head;
}
}
return Nodes;
#undef INC_STREAM
#undef LINK_IN_NODE
}
NTSTATUS
SdpTreeFromStream(
PUCHAR Stream,
ULONG Size,
PSDP_NODE_HEADER Header,
PSDP_NODE *Root,
UCHAR FullParse
)
{
PSDP_NODE_REF ref;
PSDP_NODE node, result;
PCHAR extra;
ULONG numEntries, extraPool, i, nodeSize; // valid,
NTSTATUS status;
ULONG_PTR errorByte;
numEntries = 0;
extraPool = 0;
status = ValidateStream(Stream, Size, &numEntries, &extraPool, &errorByte);
if (!NT_SUCCESS(status)) {
return status;
}
//
// recompute the number of required entries if we are not parsing the entire
// tree
//
if (!FullParse) {
numEntries = ComputeNumberOfEntries(Stream, Size, FullParse);
}
//
// Need to have a tree head as well if the caller doesn't provide a list head
//
if (Header == NULL) {
numEntries++;
}
ref = (PSDP_NODE_REF) SdpAllocatePool(sizeof(SDP_NODE_REF));
if (!ref) {
return STATUS_INSUFFICIENT_RESOURCES;
}
nodeSize = ROUND_SIZE(sizeof(SDP_NODE) * numEntries);
node = (PSDP_NODE) SdpAllocatePool(nodeSize + extraPool);
if (!node) {
SdpFreePool(ref);
return STATUS_INSUFFICIENT_RESOURCES;
}
extra = NULL;
if (extraPool > 0) {
extra = ((PCHAR) node) + nodeSize;
}
ref->Alloc = node;
ref->RefCount = (LONG) numEntries;
for (i = 0; i < numEntries; i++) {
InitializeListHead(&node[i].hdr.Link);
node[i].Reserved = ref;
}
result = StreamToNode(Stream, Size, Header, node, extra, FullParse);
if (result) {
if (Root) {
*Root = result;
}
return STATUS_SUCCESS;
}
else {
if (Header) {
SdpInitializeNodeHeader(Header);
}
SdpFreePool(node);
if (Root) {
*Root = NULL;
}
return STATUS_INVALID_PARAMETER;
}
}
NTSTATUS NodeToStream(PSDP_NODE Node, PUCHAR Stream)
{
PSD_STACK_ENTRY stackEntry;
PSDP_NODE_HEADER header;
PLIST_ENTRY current;
PSDP_NODE node;
SdpStack stack;
NTSTATUS status;
UCHAR byte;
current = &Node->hdr.Link;
while (1) {
node = CONTAINING_RECORD(current, SDP_NODE, hdr.Link);
byte = 0x00;
switch (node->hdr.Type) {
case SDP_TYPE_SEQUENCE:
case SDP_TYPE_ALTERNATIVE:
Stream = WriteVariableSizeToStream((UCHAR) node->hdr.Type,
node->DataSize,
Stream);
//
// node->DataSize == 0 if there is no sublist
//
if (node->DataSize) {
status = stack.Push(node);
if (!NT_SUCCESS(status)) {
return status;
}
if (node->hdr.Type == SDP_TYPE_SEQUENCE) {
node = CONTAINING_RECORD(node->u.sequence.Link.Flink,
SDP_NODE,
hdr.Link);
}
else {
node = CONTAINING_RECORD(node->u.alternative.Link.Flink,
SDP_NODE,
hdr.Link);
}
current = &node->hdr.Link;
continue;
}
break;
default:
Stream = WriteLeafToStream(node, Stream);
break;
}
//
// Advance to the next
//
current = current->Flink;
header = CONTAINING_RECORD(current, SDP_NODE_HEADER, Link);
while (header->Type == SDP_TYPE_LISTHEAD) {
//
// Check to see if we have pushed any items. If not, then we are
// done
//
if (stack.Depth() == 0) {
return STATUS_SUCCESS;
}
stackEntry = stack.Pop();
node = stackEntry->Node;
current = node->hdr.Link.Flink;
header = CONTAINING_RECORD(current, SDP_NODE_HEADER, Link);
}
}
return STATUS_SUCCESS;
}
NTSTATUS SdpStreamFromTree(PSDP_NODE Root, PUCHAR *Stream, PULONG Size)
{
return SdpStreamFromTreeEx(Root, Stream, Size, 0, 0);
}
NTSTATUS SdpStreamFromTreeEx(PSDP_NODE Root, PUCHAR *Stream, PULONG Size, ULONG HeaderSize, ULONG TailSize)
{
PUCHAR stream;
PSDP_NODE first;
NTSTATUS status;
*Stream = NULL;
if (Root->hdr.Type != SDP_TYPE_LISTHEAD) {
return STATUS_INVALID_PARAMETER;
}
if (IsListEmpty(&Root->hdr.Link)) {
*Size = 0;
return STATUS_SUCCESS;
}
first = CONTAINING_RECORD(Root->hdr.Link.Flink, SDP_NODE, hdr.Link);
status = ComputeNodeListSize(first, Size);
if (!NT_SUCCESS(status)) {
return status;
}
stream = (PUCHAR) SdpAllocatePool(HeaderSize + *Size + TailSize);
if (stream == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
status = NodeToStream(first, stream + HeaderSize);
if (!NT_SUCCESS(status)) {
SdpFreePool(stream);
return status;
}
*Stream = stream;
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -