Reputation: 75
Getting error of Access violation at address xxxxxx in module (myApp.exe) Read of address 00000000
, when i tried to read Registry value of type REG_MULTI_SZ.
I want to read REG_MULTI_SZ datatype from windows registry key, and add the results to my TListBox
Component, here is the code i use to do that:
void TSQLInstanceMain::GetSQLInstances(TStrings *AStrings)
{
HKEY hkey;
DWORD vType;
DWORD vLen;
DWORD buffer;
wchar_t *p;
UnicodeString RegKeyName = L"\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\";
UnicodeString RegKeyValue = "InstalledInstances";
try {
if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegKeyName.w_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_SUCCESS )
{
SetLastErrorEx(RegQueryValueExW(hkey, RegKeyValue.w_str(), NULL, &vType, NULL, &vLen), NULL);
if ( GetLastError() == ERROR_SUCCESS && vType == REG_MULTI_SZ )
{
buffer = (DWORD)GetMemory(vLen);
RegQueryValueExW(hkey, RegKeyValue.w_str(), NULL, NULL, PByte(buffer), &vLen);
p = (wchar_t*)buffer;
AStrings->Clear();
while ( &p != 0x0 )
{
AStrings->Add(p);
p += lstrlen(p)+1;
}
}
}
}
__finally
{
FreeMemory(&buffer);
}
}
Note: I found this code in this article and translated it to C++ as best as i could.
Upvotes: 0
Views: 1547
Reputation: 595897
The AV error message is telling you that a NULL pointer is being read from.
One error I see in your code that could cause that is while ( &p != 0x0 )
. Your loop is checking the memory address of the p
pointer itself, not the data it is pointing at. As such, your loop will not terminate correctly when the pointer reaches the end of the string data.
Your loop should be while ( *p != 0 )
instead (in Delphi, p^
is a pointer dereference),
You should also over-allocate your buffer
to include your own null terminator, as RegQueryValueExW()
DOES NOT guarantee that string data is null-terminated. Apps that store string data in the Registry are supposed to include a null terminator in the stored data, but many buggy apps exist that don't actually do that. RegQueryValueExW()
just returns the raw data exactly as it was saved, so the data you read MAY not be properly null-terminated, so append your own terminator, just in case:
wchar_t *buffer; // <-- not DWORD!
...
buffer = (wchar_t*) GetMemory(vLen + sizeof(wchar_t));
...
p = buffer;
...
FreeMemory(buffer); // <-- no &!
Alternatively, use RegGetValueW()
instead, as it will append a null terminator for you if one is missing.
Lastly, you are leaking the HKEY
that RegOpenKeyExW()
returns. You need to call RegCloseKey()
when you are done using the HKEY
.
With all of that said, try this instead:
#include <vector>
void TSQLInstanceMain::GetSQLInstances(TStrings *AStrings)
{
HKEY hkey;
DWORD vType;
DWORD vLen = 0;
std::vector<BYTE> buffer;
wchar_t *p;
const wchar_t *RegKeyName = L"\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\";
const wchar_t *RegKeyValue = L"InstalledInstances";
if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_SUCCESS )
{
try
{
if ( (RegQueryValueExW(hkey, RegKeyValue, NULL, &vType, NULL, &vLen) == ERROR_SUCCESS) && (vType == REG_MULTI_SZ) )
{
vLen += sizeof(wchar_t);
buffer.resize(vLen);
RegQueryValueExW(hkey, RegKeyValue, NULL, &vType, &buffer[0], &vLen);
p = (wchar_t*) &buffer[0];
AStrings->BeginUpdate();
try
{
AStrings->Clear();
while ( *p != 0 )
{
AStrings->Add(p);
p += (lstrlenW(p) + 1);
}
}
__finally
{
AStrings->EndUpdate();
}
}
}
__finally
{
RegCloseKey(hKey);
}
}
}
Or:
#include <vector>
void TSQLInstanceMain::GetSQLInstances(TStrings *AStrings)
{
HKEY hkey;
DWORD vLen = 0;
std::vector<BYTE> buffer;
wchar_t *p;
const wchar_t *RegKeyName = L"\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\";
const wchar_t *RegKeyValue = L"InstalledInstances";
if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &hkey) == ERROR_SUCCESS )
{
try
{
if ( (RegGetValueW(hkey, NULL, RegKeyValue, RRF_RT_REG_MULTI_SZ, NULL, NULL, &vLen) == ERROR_SUCCESS) )
{
buffer.resize(vLen);
RegGetValueW(hkey, NULL, RegKeyValue, RRF_RT_REG_MULTI_SZ, NULL, &buffer[0], &vLen);
p = (wchar_t*) &buffer[0];
AStrings->BeginUpdate();
try
{
AStrings->Clear();
while ( *p != 0 )
{
AStrings->Add(p);
p += (lstrlenW(p) + 1);
}
}
__finally
{
AStrings->EndUpdate();
}
}
}
__finally
{
RegCloseKey(hKey);
}
}
}
Upvotes: 1