+ /* Loop as long as the array still has strings */
+ while (*BcdString)
+ {
+ /* Don't read beyond the registry data */
+ if (Length >= DataLength)
+ {
+ break;
+ }
+
+ /* One more GUID -- does the caller have space? */
+ ReturnedLength += sizeof(GUID);
+ if (ReturnedLength <= *ElementSize)
+ {
+ /* Convert and add it in */
+ RtlInitUnicodeString(&GuidString, BcdString);
+ Status = RtlGUIDFromString(&GuidString, ElementGuid);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ /* Move to the next GUID in the caller's buffer */
+ ElementGuid++;
+ }
+
+ /* Move to the next string in the registry array */
+ Size = (wcslen(BcdString) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
+ Length += Size;
+ BcdString = (PWCHAR)((ULONG_PTR)BcdString + Length);
+ }
+
+ /* Check if we failed anywhere */
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ /* Check if we consumed more space than we have */
+ if (ReturnedLength > *ElementSize)
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /* All good here */
+ break;
+
+ /* Integer -- stored as binary */
+ case BCD_TYPE_INTEGER:
+
+ /* BCD data is a ULONGLONG, registry data is 8 bytes binary */
+ ElementInteger = (PULONGLONG)Element;
+ ReturnedLength = sizeof(*ElementInteger);
+
+ /* Make sure the registry data makes sense */
+ if (DataLength > ReturnedLength)
+ {
+ return STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ /* Make sure the caller has space */
+ if (*ElementSize < ReturnedLength)
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ /* Write the integer result */
+ *ElementInteger = 0;
+ RtlCopyMemory(ElementInteger, Data, DataLength);
+ Status = STATUS_SUCCESS;
+ break;
+
+ /* Boolean -- stored as binary */
+ case BCD_TYPE_BOOLEAN:
+
+ /* BCD data is a BOOLEAN, registry data is 2 bytes binary */
+ ElementWord = (PUSHORT)Element;
+ BcdBoolean = (PBOOLEAN)Data;
+ ReturnedLength = sizeof(ElementWord);
+
+ /* Make sure the registry data makes sense */
+ if (DataLength != sizeof(*BcdBoolean))
+ {
+ return STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ /* Make sure the caller has space */
+ if (*ElementSize < ReturnedLength)
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ /* Write the boolean result */
+ *ElementWord = 0;
+ *ElementWord = *BcdBoolean != 0;
+ Status = STATUS_SUCCESS;
+ break;
+
+ /* Integer list --stored as binary */
+ case BCD_TYPE_INTEGER_LIST:
+
+ /* BCD Data is n ULONGLONGs, registry data is n*8 bytes binary */
+ ReturnedLength = DataLength;
+ if (!(DataLength) || (DataLength & 7))
+ {
+ return STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ /* Make sure the caller has space */
+ if (*ElementSize < ReturnedLength)
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ /* Write the integer list result */
+ RtlCopyMemory(Element, Data, DataLength);
+ Status = STATUS_SUCCESS;
+ break;
+
+ /* Arbitrary data */
+ default:
+
+ /* Registry data is copied binary as-is */
+ ReturnedLength = DataLength;
+
+ /* Make sure it's not empty */
+ if (!DataLength)
+ {
+ return STATUS_OBJECT_TYPE_MISMATCH;
+ }
+
+ /* Make sure the caller has space */
+ if (*ElementSize < ReturnedLength)
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ /* Write the result */
+ RtlCopyMemory(Element, Data, DataLength);
+ Status = STATUS_SUCCESS;
+ break;