Reading Registry in Windows 7 behaving strangely - c++

I am trying to read registry's "(Default)" values in Windows 7 in c++, and following is the code I am using:
string GetSZValueUnique( HKEY openKey, const char* regkey, const char* keyName )
{
HKEY hKey = 0;
BYTE data[512] ;
DWORD szsize = 512 ;
string value ;
LONG retValue = RegOpenKeyEx( openKey, regkey, 0, KEY_READ, &hKey ) ;
if ( retValue == ERROR_SUCCESS )
{
LONG retV = RegQueryValueEx( hKey, keyName, 0, 0, data, &szsize ) ;
if ( retV == ERROR_SUCCESS )
{
char* _value = reinterpret_cast<char*>(data) ;
value = _value ;
RegCloseKey (hKey) ;
return value ;
}
else
{
char msg[512] ;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,(DWORD)retV,0,&msg[0],512,0) ;
error_string = &msg[0];
MessageBox( 0, error_string.c_str(), "Query : GetSZValueUnique", 0 );
}
}
else
{
char msg[512] ;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,(DWORD)retV,0,&msg[0],512,0) ;
error_string = &msg[0];
MessageBox( 0, error_string.c_str(), "Open : GetSZValueUnique", 0 );
}
RegCloseKey (hKey) ;
return "" ;
}
And this is how I am calling the above function :
string ts3 = GetSZValueUnique( HKEY_LOCAL_MACHINE, "SOFTWARE\\TeamSpeak 3 Client\\", "" );
if ( !ts3.empty() )
MessageBox( 0, ts3.c_str(), "GetSZValueUnique", 0 );
For some Keys it works for some it doesn't : For example, it works for "Adobe", "TrendMicro", "CheckPoint", "RegisteredApplications" but not for "7-Zip", "RTLSetup", "Sonic", "TeamSpeak 3 Client"
I am out of ideas now, can somebody point out what's wrong ?
EDIT: I have checked the code with "(Default)" values and other values as well, for keys its not working it never goes past the *"if ( retValue == ERROR_SUCCESS )"* check and I always get "Specified file not found" error. For keys its working, it gets past the "*if ( retValue == ERROR_SUCCESS )*" check and returns the value if its present, if its not present it simply displays the error message "Specified file not found".
EDIT 2: I Checked again : and it seems the keys it works for have their corresponding clone in "Wow6432Node" subkey under SOFTWARE... hmmm... so how do I get it working ?

You can specify the flag::
"KEY_WOW64_32KEY" in "samDesired" parameter of the RegOpenKeyEx if you want to access Wow6432Node Keys i.e., 32-bit keys from your app.
"KEY_WOW64_64KEY" in "samDesired" parameter of the RegOpenKeyEx if you want to access normal Keys i.e., 64-bit keys from your app.
Note:: Your doubt has already been cleared by #WhozCraig in comments with the suitable links. If he answers, do accept his answer over mine.

Related

Is it possible to read and write cookies using BHO in internet explorer

I am working an extension for Internet explorer to read network traffic using BHO in C++. My code is based on the following,
https://github.com/salsita/passthruapp
Is there a way that I can access cookies that are stored on the browser? I want to be able to read a cookie set for a particular domain and also store a cookie for the domain.
I used InternetGetCookieEx and InternetSetCookieEx. My goal was just to expire cookies so I had the following:
#define EXPIRED_COOKIE_DATE L"expires = Sat,01-Jan-2000 00:00:00 GMT"
void ExpireCookies( const CString& strUrl )
{
DWORD dwSize;
BOOL bResult = InternetGetCookieEx( strUrl, NULL, NULL, &dwSize, INTERNET_COOKIE_HTTPONLY, NULL );
if ( !bResult || dwSize <= 0 )
return;
TCHAR *lpszData = new TCHAR[dwSize];
LPCWSTR usrauth = NULL;
bResult = InternetGetCookieEx( strUrl, usrauth, lpszData, &dwSize, INTERNET_COOKIE_HTTPONLY, NULL );
if ( !bResult )
goto Exit;
{
CString cookieDataString( lpszData );
int nTokenPos = 0;
CString cookie = cookieDataString.Tokenize( _T( "; " ), nTokenPos );
while ( nTokenPos >= 0 )
{
int separator = cookie.Find( _T( '=' ) );
CString cookieName = cookie.Left( separator );
CString value = cookie.Mid( separator + 1 );
VERIFY( InternetSetCookieEx( strUrl, cookieName, EXPIRED_COOKIE_DATE, INTERNET_COOKIE_HTTPONLY, NULL ) );
cookie = cookieDataString.Tokenize( _T( "; " ), nTokenPos );
}
}
Exit:
SAFE_DELETE_ARR( lpszData );
}
Hope it helps you some!

RegSetValueEx() not changing the key value

In my application, when I first set the key-value using RegSetValueEx() it works, but when I try to change the value using the same function it doesn't work, the value remains same. What am I doing wrong ?
Here is the code :
SetSZValue( "MyAppData", "versionInfo", "1.0.0" );
HKEY CreateKey( string regkey )
{
HKEY hKey ;
DWORD disValue ;
char msg[512] ;
string _key = "HKEY_LOCAL_MACHINE\\" ;
_key += regkey ;
LONG retValue = RegCreateKeyEx( HKEY_LOCAL_MACHINE, regkey.c_str(), 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, &disValue ) ;
if (retValue != ERROR_SUCCESS)
{
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, &msg[0], 512, 0 ) ;
MessageBox( 0, &msg[0], "CreateKey", MB_OK | MB_ICONEXCLAMATION );
}
return hKey ;
}
void SetSZValue( string regkey, string keyName, string keyValue )
{
HKEY hKey;
DWORD disValue;
char msg[512];
hKey = CreateKey(regkey);
if (hKey)
{
LONG retValue = RegSetValueEx( hKey, keyName.c_str(), 0, REG_SZ, ( const BYTE* )( keyValue.c_str() ), keyValue.size()+1 );
if ( retValue != ERROR_SUCCESS )
{
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, &msg[0], 512, 0 );
MessageBox( 0, &msg[0], "SetSZValue", MB_OK | MB_ICONEXCLAMATION );
}
RegCloseKey ( hKey );
}
}
RegSetValueEx accepts the name of the value inside the key to change; not the name of the key. Supply the value name instead; the key name comes from the HKEY itself.
Is your app a 32-bit process running on a 64-bit Windows version? If so, does your app have a UAC manifest with a "requestedExecutionLevel" value in it? If not, your key may be getting virtualized to another section of the Registry and you are simply not looking in the right place. Registry Virtualization is a feature of WOW64 so legacy 32-bit and 64-bit processes do not step over each other in the Registry. You should install SysInternals Process Monitor, it will show you which keys and values your app is actually accessing.

Why does the RegQueryValueEx() function return ERROR_FILE_NOT_FOUND while trying to read from a registry key?

System: Windows 7 32bit
Language: C++
I have tried to access register HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0, key Driver (type REG_SZ) -- no problem.
The same for reading from HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM, all keys (types REG_SZ) got slashes, for example \Device\Serial0.
While reading such keys it always returns 2 (no such file) with following example code:
HKEY hKey = 0;
DWORD dwType = REG_SZ;
char buf[255] = {0};
DWORD dwBufSize = sizeof(buf);
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS )
{
auto ret = RegQueryValueEx( hKey, TEXT("\Device\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize );
// ret always == 2 for key with slashes
--- CUT ---
What is the proper way to read key values with slashes in name?
Above has been properly answered by Cody Gray.
Below another issue.
Im getting the same problem when Im using variable instead of a text string.
Iv considered both approaches with single and double slashes:
HKEY hKey = 0;
DWORD keyType = REG_SZ;
TCHAR buf[255] = {0};
DWORD bufSize = sizeof(buf);
QSettings winReg("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM", QSettings::NativeFormat);
auto comsKey = winReg.allKeys();
FOREACH( auto com, comsKey )
{
// FOREACH - boost macro
// comsKey = QList<QString> (list of key names) [from Qt framework]
// com = QString (single key name) [from Qt framework]
if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS )
{
wchar_t* keyw = new wchar_t();
//com.replace("/", "\\\\"); <- checked both variants commented and not commented; com == /Device/Serial0 so im converting to \\Device\\Serial0
int size = com.size();
mbstowcs( keyw, com.toStdString().data(), size );
//auto ret = RegQueryValueEx( hKey, TEXT("\\Device\\Serial0"), 0, &keyType, (LPBYTE)buf, &bufSize ); // <- this works!
auto ret = RegQueryValueExW( hKey, (LPCWSTR)&keyw, 0, &keyType, (LPBYTE)buf, &bufSize ); // <- this one not works!
I have tried all variants with "\Device..", "/Device", "\Device", etc.
You have to escape the slashes, just like you did in the first line...
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS )
{
auto ret = RegQueryValueEx( hKey, TEXT("\\Device\\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize );
// ret always == 2 for key with slashes
If you don't, the RegQueryValueEx function can't find the specified key, and it returns ERROR_FILE_NOT_FOUND (== 2).
But there's another problem. You should be declaring the buffer array as type wchar_t (or TCHAR), rather than char:
TCHAR buf[255] = {0};
Otherwise, the RegQueryValueEx function is going to attempt to fill the array with a Unicode string read from the specified registry key, and you're going to get something unreadable.

Getting a proper value from RegQueryValueEx

I am trying to extract a value from the windows registry of type REG_SZ, using RegQueryValueEx, I got the value except it was riddled with strange "\000" before each letter.To show you what I mean here are some images:
Value I want(It is a device name of a wireless adapter)
Value I got:
here is the code:
HKEY hlistkey = NULL;
HKEY hkey = NULL;
int dwIndex=0;
string devName = returndevName(); //return current selected device name using iphlpapi.h
WCHAR KeyNameBuf[512];
DWORD keyNameSizBuf = 512;
char buffer[512];
RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}") ,0,KEY_READ, &hlistkey );
if(!hlistkey)
{
cout << "failed" << endl;
}
while(RegEnumKeyEx(hlistkey,dwIndex++,KeyNameBuf,&keyNameSizBuf,0,NULL,NULL,NULL) == ERROR_SUCCESS )
{
RegOpenKeyEx(hlistkey, KeyNameBuf, 0, KEY_READ | KEY_SET_VALUE, &hkey);
if(hkey)
{
keyNameSizBuf = 512;
if(RegQueryValueEx(hkey,TEXT("NetCfgInstanceId"), 0,NULL,(LPBYTE)buffer,&keyNameSizBuf ) == ERROR_SUCCESS )
{
if(strcmp(buffer,devName.c_str() ) ==0)
{
//set value here
}
}
RegCloseKey(hkey);
}
}
}
comparing buffer and devName would not be the same because of the extra null characters .If I cast buffer to a string I simply got a "{" which is the first value.I need to get the value of the devename in the registry before I can change the "NetworkAddress" in the registry.
Since you are using WCHAR, I assume you are compiling with Unicode support. If this is true, then also the buffer needs to be WCHAR.

Difference in memory allocation in WIn 7/Vista compared to WinXP/Win2k3 in following code

I have the following piece of code. This is written for getting the list of timezones from registry and populating into an array. This piece of code works fine in Win7 and Vista OS but not in WinXp and Win2k3.
The reason is because of the size of array getting overflown. I have defined only 100 elements. However there are more than 100 elements in the registry.
Now my question is why this does not fail in Vista or Win7 machines. Is there any difference in allocation of memory between Xp and Vista OS.
It crashes in the line while getting 100the element from registry
while( RegEnumKeyEx( Key, nTimezones, tzKeyNames[nTimezones].GetBuffer( size ), &size, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS )
Full code
CString sRegKey;
HKEY Key;
HKEY subKey;
int nTimezones = 0;
CArray< CString, CString > tzKeyNames;
tzOffset.SetSize( 100, 10 );
tzKeyNames.SetSize( 100, 10 );
tzDisplayNames.SetSize( 100, 10 );
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx(&osvi);
if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
sRegKey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
}
else
{
sRegKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones");
}
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, sRegKey, 0, KEY_READ , &Key ) == ERROR_SUCCESS )
{
DWORD size;
DWORD type = REG_SZ;
TZINFO tz;
_TCHAR name[ 128 ];
BYTE data[ 128 ];
size = 128;
while( RegEnumKeyEx( Key, nTimezones, tzKeyNames[nTimezones].GetBuffer( size ), &size, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS )
{
tzKeyNames[nTimezones].ReleaseBuffer();
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, sRegKey + _T("\\") + (LPCTSTR)tzKeyNames[nTimezones], 0, KEY_READ , &subKey ) == ERROR_SUCCESS )
{
size = 128;
if( RegQueryValueEx( subKey, _T("Display"), NULL, &type, (unsigned char*)name, &size ) == ERROR_SUCCESS )
{
tzDisplayNames[nTimezones] = name;
}
size = 128;
if( RegQueryValueEx( subKey, _T("TZI"), NULL, &type, data, &size ) == ERROR_SUCCESS )
{
memcpy( &tz, data, size );
tzOffset[ nTimezones ] = (int)(( tz.Bias / -60.0 ) * 2.0 ) + 24;
}
RegCloseKey( subKey );
}
nTimezones++;
}
RegCloseKey( Key );
}
Exception is raised when application tries to read/write a piece of memory that is not in it's address space. In one case after the array there was addressed memory, in other there wasn't. This is random. And yes, various allocation algorithm will lead to various results but this is only one element causing randomness. The results are also dependent on how many bytes are allocated and where they are allocated by your application, other applications and the OS itself.
// EDIT
tzKeyNames[nTimezones].ReleaseBuffer();
Probably the problem is not in reading after the array's end (it's usually within addressed space) but that some garbage was read. This garbage is used as a pointer, when dereferenced causes exception.