2

Possible Duplicate:
How to compare strings


I want to Compare to registry string values and if they were the same an messagebox appears
Currently I'm using this functions , It returns the value correctly but whenever I want to compare them, The compare result is always wrong

char* GetRegistry(char* StringName)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
char value[1024];
DWORD value_length = 1024;
const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)&value, &value_length);
return  value;
}


I use this to compare them

if (GetRegistry("First") == GetRegistry("Second"))
{
MessageBox(NULL,":|",":|",1);
}


But the MessageBox appears how ever The values are different


Any help is appreciated.

Community
  • 1
  • 1
Shahriyar
  • 1,483
  • 4
  • 24
  • 37

3 Answers3

5

By using std::string, comparison would behave as you expected. Also that would fix another bug that the function returns a pointer to a local buffer.

std::string GetRegistry(const char* StringName)
{
....
return std::string(value);
}
Andriy
  • 8,486
  • 3
  • 27
  • 51
4

GetRegistry() returns a char*, so you are actually comparing pointers with operator==. You should use strcmp() to do raw C-like char* string comparisons, or better use a robust C++ string class, like CString or std::[w]string.

Here is a possible rewrite of your function using ATL's CString:

#include <atlbase.h>
#include <atlstr.h>

CString GetRegistry(LPCTSTR pszValueName)
{
    // Try open registry key
    HKEY hKey = NULL;
    LPCTSTR pszSubkey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI Extensions");
    if ( RegOpenKey(HKEY_LOCAL_MACHINE, pszSubkey, &hKey) != ERROR_SUCCESS )
    {
        // Error:
        // throw an exception or something...
        //
        // (In production code a custom C++ exception 
        // derived from std::runtime_error could be used)
        AtlThrowLastWin32();
    }

    // Buffer to store string read from registry
    TCHAR szValue[1024];
    DWORD cbValueLength = sizeof(szValue);

    // Query string value
    if ( RegQueryValueEx(
            hKey,
            pszValueName, 
            NULL, 
            NULL, 
            reinterpret_cast<LPBYTE>(&szValue), 
            &cbValueLength) 
         != ERROR_SUCCESS )
    {
        // Error
        // throw an exception or something...
        AtlThrowLastWin32();
    }

    // Create a CString from the value buffer
    return CString(szValue);
}

And then you can call it like this:

if ( GetRegistry(_T("First")) == GetRegistry(_T("Second")) )
    ...

Note that this code will compile in both ANSI/MBCS and Unicode builds (it's based on Win32 TCHAR model).

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • cannot open source file "atlstr.h" cannot open source file "atlbase.h" Shoud I download something ? – Shahriyar Oct 18 '12 at 13:33
  • @Shahriyar: You need ATL. If you use some commercial version of Visual Studio, you have it. But ATL is not available on free Express editions. (However, it seems that you can download the WDK and get ATL headers from it: see [Google Chrome building instructions for Windows](http://www.chromium.org/developers/how-tos/build-instructions-windows), which has a section on using Visual C++ 2012 Express.) – Mr.C64 Oct 18 '12 at 13:36
0

You have a couple of problems with this source code.

First of all you have a function with a local variable, a variable on the stack, which is returning the address of that variable yet when the function returns, the variable disappears and the address is no longer valid.

The next problem is that you are not comparing the character strings. You are instead comparing the address returned by the function and if you get lucky, the address could be the same. Since you are calling the function twice in succession, you are getting lucky so the address is the same.

I suggest you do the following: (1) create two local character strings in your function which is calling the function GetRegistry() and (2) modify the GetRegistry() function so that it uses those buffers rather than its own. So the code would look something like:

char registryEntryOne[1024];
char registryEntryTwo[1024];
DWORD dwRegistryEntryOneLen;
DWORD dwRegistryEntryTwoLen;

registryEntryOne[0] = 0;   // init the registry entry to zero length string
registryEntryTwo[0] = 0;

dwRegistryEntryOneLen = sizeof(registryEntryOne);
GetRegistry ("First", registryEntryOne, &dwRegistryEntryOneLen);
dwRegistryEntryTwoLen = sizeof(registryEntryTwo);
GetRegistry ("Second", registryEntryTwo, &dwRegistryEntryTwoLen);

// two strings are equal if:
//   the lengths are the same
//   at least one of the lengths is non-zero
//   the bytes are the same in the same order
if (dwRegistryEntryOneLen && dwRegistryEntryOneLen == dwRegistryEntryTwoLen && memcmp (registryEntryOne, registryEntryTwo, dwRegistryEntryOneLen) == 0) {
    // strings are equal
} else {
    // strings are not equal
}

The GetRegistry() function would look something like:

char* GetRegistry(char* StringName, char *valueBuffer, DWORD *value_length)
{
    DWORD dwType = REG_SZ;
    HKEY hKey = 0;
    const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";

    RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
    RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)valueBuffer, value_length);
    return  valueBuffer;
}
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106