I am wondering if allocating the buffer on the stack requires the correct alignment for any type, similar to how malloc works, or if I have to use something like std::aligned_storage .
Consider the following code block:
typedef enum _KEY_VALUE_INFORMATION_CLASS { KeyValueBasicInformation = 0, // Others } KEY_VALUE_INFORMATION_CLASS; typedef struct _KEY_VALUE_BASIC_INFORMATION { ULONG TitleIndex; ULONG Type; ULONG NameLength; WCHAR Name[1]; } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; std::vector<std::wstring> RegistryKey::EnumerateValueNames() const { std::vector<std::wstring> result; ULONG index = 0; const ULONG valueNameStructSize = 16384 * sizeof(wchar_t) + sizeof(KEY_VALUE_BASIC_INFORMATION); // Stack buffer here unsigned char buff[valueNameStructSize]; // Casted here KEY_VALUE_BASIC_INFORMATION const* basicValueInformation = reinterpret_cast<KEY_VALUE_BASIC_INFORMATION const*>(buff); for(;;) { ULONG resultLength; NTSTATUS errorCheck = PNtEnumerateValueKeyFunc( hKey_, index++, KeyValueBasicInformation, buff, valueNameStructSize, &resultLength); if (NT_SUCCESS(errorCheck)) { result.emplace_back(std::wstring(basicValueInformation->Name, basicValueInformation->NameLength / sizeof(wchar_t))); } else if (errorCheck == STATUS_NO_MORE_ENTRIES) { break; } else { Win32Exception::ThrowFromNtError(errorCheck); } } return result; }
Notice how buff is a character buffer pushed onto the stack to hold a given maximum amount of data. However, I am concerned that the cast needed to interpret the buffer as a string may result in an alignment error if this code needs to be ported to another platform (e.g. ARM or IA64).
EDIT: If anyone is interested, I will redo this with std::aligned_storage and std::alignment_of :
std::vector<std::wstring> RegistryKey::EnumerateValueNames() const { std::vector<std::wstring> result; ULONG index = 0; const ULONG valueNameStructSize = 16384 * sizeof(wchar_t) + sizeof(KEY_VALUE_BASIC_INFORMATION); std::aligned_storage<valueNameStructSize, std::alignment_of<KEY_VALUE_BASIC_INFORMATION>::value>::type buff; auto basicValueInformation = reinterpret_cast<KEY_VALUE_BASIC_INFORMATION*>(&buff); for(;;) { ULONG resultLength; NTSTATUS errorCheck = PNtEnumerateValueKeyFunc( hKey_, index++, KeyValueBasicInformation, basicValueInformation, valueNameStructSize, &resultLength); if (NT_SUCCESS(errorCheck)) { result.emplace_back(std::wstring(basicValueInformation->Name, basicValueInformation->NameLength / sizeof(wchar_t))); } else if (errorCheck == STATUS_NO_MORE_ENTRIES) { break; } else { Win32Exception::ThrowFromNtError(errorCheck); } } return std::move(result); }
Billy oneal
source share