views:

427

answers:

2

What code add to this function to work good? (ERROR_SUCCESS)

I have code, that check value in registry.

In function RegQueryValueEx is bug. When oldValue is few letters longer than newValue, function shows ERROR_MORE_DATA, but I want want ERROR_SUCCESS

What code add to this function to do this?

void function(string newValue, string key, string name)

{

 // string key - key in registry, ie Myapp\\Options
 // string name - name in registry
 // string newValue - data in REG_SZ


 string oldValue;
 DWORD keytype = REG_SZ;
    HKEY keyHandle;
 DWORD size = sizeof(string);
 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, key.c_str(),0L,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
 {


  LONG isgood = RegQueryValueEx(keyHandle, name.c_str(), 0, &keytype, (LPBYTE)&oldValue, &size);
  if(isgood == ERROR_MORE_DATA)
   {
    cout << "Error more data\n"; 
   }
  if(isgood == ERROR_SUCCESS)
  {
   cout << "Old data is " << oldValue.c_str() << endl;
   cout << "New data is " << newValue.c_str() << endl;
   if(strcmp(newValue.c_str(), oldValue.c_str()) != 0) // compare 2 strings, if
   {
    cout << "String 1 and string 2 are different";

   }
   else
   {
    cout << "String 1 and string 2 are the same";
   }
  }
  if(isgood == ERROR_FILE_NOT_FOUND)
  {
   cout << "Name in registry not found!";
  }
 }

}
A: 

ERROR_MORE_DATA means that you need to pass in a larger string buffer. The typical pattern you'll need to use is to call once to get the size, then allocate a properly-sized buffer, then call again. Or, alternatively, you can guess at a size, pass in that-sized buffer, and increase size if you get ERROR_MORE_DATA back.

BTW, you are also computing size incorrectly. And you're not closing the registry key. And you're not prepared to support being compiled under unicode or non-unicode modes.

Here's some revised code which addresses these issues.

#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
using namespace std;

namespace std
{
#ifdef _UNICODE
    #define tcout wcout
    #define tcin wcin
    typedef wstring tstring;
#else
    #define tcout cout
    #define tcin cin
    typedef string tstring;
#endif
};

void function(tstring newValue, tstring key, tstring name)
{
    // string key - key in registry, ie Myapp\\Options
    // string name - name in registry
    // string newValue - data in REG_SZ
    HKEY keyHandle;
    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, key.c_str(),0L,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
    {
     DWORD size = 500; // initial size
     vector<TCHAR> buf(size);
     tstring oldValue;
     DWORD keytype = REG_SZ;

     LONG isgood = RegQueryValueEx(keyHandle, name.c_str(), 0, &keytype, (LPBYTE) &buf[0], &size);
     if(isgood == ERROR_SUCCESS)
     {
      oldValue.assign (&buf[0], size);
     }
     else if(isgood == ERROR_MORE_DATA)
     {
      buf.reserve (size); // expand to however large we need
      isgood = RegQueryValueEx(keyHandle, name.c_str(), 0, &keytype, (LPBYTE)&buf[0], &size);
      if(isgood == ERROR_SUCCESS)
       oldValue.assign (&buf[0], size);
     }
     RegCloseKey (keyHandle); // remember to close this!
     if(isgood == ERROR_SUCCESS)
     {
      tcout << _T("Old data is ") << oldValue << endl;
      tcout << _T("New data is ") << newValue << endl;
      if(newValue.compare(oldValue) != 0) // compare 2 strings, if
      {
       tcout << _T("String 1 and string 2 are different");

      }
      else
      {
       tcout << _T("String 1 and string 2 are the same");
      }
     }
     if(isgood == ERROR_FILE_NOT_FOUND)
     {
      tcout << _T("Name in registry not found!");
     }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    tstring val;
    function (val, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"), _T("CommonFilesDir"));
    return 0;
}
Justin Grant
Thank you Justin Grant for complete code, I know now what I do wrong :*
Jasmin25
But when I add to registry data "foo" and run this program with new data "foo" it shows:Old data is fooNew data is fooString 1 and string 2 are differentBut foo and foo are the same values.How change this code to working well?
Jasmin25
not sure. perhaps one of the strings includes the null-terminator character and one does not, causing the lengths to be different? In any case, look at the strings character-by-character and you'll figure out how they're different and how to fix the problem.
Justin Grant
Yes, in the end of string was '\0' character. After removing this, strings are equal. :)
Jasmin25
+1  A: 

ERROR_MORE_DATA means the buffer you supplied to hold the data is not big enough.

Your problems are multiple:

  1. When you say sizeof(string) you're getting the size of the string data type, not the length of the string. You should call string::size() to get the length of the string.
  2. You can't just cast a string to an LPBYTE. That is going to FAIL miserably. The Registry APIs are not designed to work with strings, they are designed to work with char* and WCHAR* types. You need to declare a local character array (e.g. char *foo = new char[256]) and then pass that. If you get ERROR_MORE_DATA, declare a bigger one.
jeffamaphone