diff --git a/rejistry++/src/RegistryByteBuffer.cpp b/rejistry++/src/RegistryByteBuffer.cpp index 1322ea0e72adb4d8002b2dc6e16d16a8e0424f9e..5e036383a829dbfc8de9a4d45518e640a0ef6b83 100644 --- a/rejistry++/src/RegistryByteBuffer.cpp +++ b/rejistry++/src/RegistryByteBuffer.cpp @@ -85,9 +85,13 @@ namespace Rejistry { return getASCIIString(0, _byteBuffer->limit()); } - /** - * Throws exception if offset or length is too large. - */ + /** + * Reads data from the registry and returns the data as a string + * as it is represented in the registry, including Null characters. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ std::string RegistryByteBuffer::getASCIIString(const uint32_t offset, const uint32_t length) const { if (length == 0) { return ""; @@ -102,60 +106,52 @@ namespace Rejistry { return getUTF16String(0, _byteBuffer->limit()); } + /** + * Reads data from the registry and returns a wstring of the data + * as it is represented in the registry, including Null characters. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ std::wstring RegistryByteBuffer::getUTF16String(const uint32_t offset, const uint32_t length) const { - if (length == 0) { - return L""; - } - - ByteBuffer::ByteArray &data = getData(offset, length); - // If the size of the array is not a multiple of 2 it is - // likely to not be UTF16 encoded. The most common case is that - // the string is simply missing a terminating null so we add it. - if (data.size() % 2 != 0) { - data.push_back('\0'); - } - - // Find UTF16 null terminator. - uint32_t nullPos = 0; - for (; nullPos < data.size(); nullPos += 2) { - if (data[nullPos] == '\0' && data[nullPos+1] == '\0') { - break; - } - } - - // empty string - if (nullPos == 0) { - return L""; - } + if (length == 0) { + return L""; + } - // UFT16 NULL char not found so add it - // Non-ascii registry key names seem to not be NULL terminated - // which leads to conversion errors in from_bytes() (CT-2917) - else if (nullPos == data.size()) { - data.push_back('\0'); + ByteBuffer::ByteArray &data = getData(offset, length); + // There are cases where an odd number of bytes are returned which + // leads to errors during conversion. See CT-2917 test12 for more details. + if (data.size() % 2 != 0) { data.push_back('\0'); } - std::wstring result; + // Empty value data (single UTF16 null char) + if (data.size() == 2 && data[0] == '\0' && data[1] == '\0') { + return L""; + } - try { - result = conv.from_bytes(reinterpret_cast<const char*>(&data[0]), reinterpret_cast<const char*>(&data[nullPos])); - } - catch (std::exception&) - { - throw RegistryParseException("Error: Failed to convert string"); - } + std::wstring result; + try { + result = conv.from_bytes(reinterpret_cast<const char*>(&data[0]), reinterpret_cast<const char*>(&data[data.size()])); + } + catch (std::exception&) + { + throw RegistryParseException("Error: Failed to convert string"); + } - return result; - } + return result; + } ByteBuffer::ByteArray RegistryByteBuffer::getData() const { return getData(0, _byteBuffer->limit()); } - /** - * Throws exception if offset and length are too large. - */ + /** + * Reads data from the registry based off of the given offset and length of data to read. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ ByteBuffer::ByteArray RegistryByteBuffer::getData(const uint32_t offset, const uint32_t length) const { uint32_t savedPosition = _byteBuffer->position(); _byteBuffer->position(offset); @@ -170,6 +166,12 @@ namespace Rejistry { return getStringList(0, _byteBuffer->limit()); } + /** + * Reads data from the registry based off of the given offset and length of data to read. + * + * @param offset: Offset where data begins + * @param length: Number of bytes to read + */ std::vector<std::wstring> RegistryByteBuffer::getStringList(const uint32_t offset, const uint32_t length) const { std::vector<std::wstring> stringList; ByteBuffer::ByteArray data = getData(offset, length);