0

I'm using some Registry functions from the Windows API (RegOpenKeyEx, RegQueryInfoKey and RegEnumValue)Let's say this is the code I have so far:

const int MAX_VALUE_NAME= 16383;
const int MAX_DATA = 16383;

DWORD i;
    HKEY hKey = HKEY_CURRENT_USER;
    LPCTSTR lpSubKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU");
    DWORD ulOptions = 0;
    REGSAM samDesired = KEY_READ | KEY_WRITE | KEY_QUERY_VALUE;
    HKEY phkResult;
    DWORD dwIndex = 0;
    TCHAR lpValueName[MAX_VALUE_NAME];
    LPCTSTR ValueMRU;
    BYTE *DataMRU;
    DWORD lpcchValueName = MAX_VALUE_NAME;
    BYTE lpData[MAX_DATA+2];
    DWORD cbData = sizeof(lpData);
    DWORD type;

    TCHAR lpClass[MAX_PATH] = TEXT("");
    DWORD lpcClass = MAX_PATH;
    LPDWORD lpReserved = NULL;
    DWORD lpcSubKeys = 0;
    DWORD lpcMaxSubKeyLen;
    DWORD lpcMaxClassLen;
    DWORD lpcValues;
    DWORD lpcMaxValueNameLen;
    DWORD lpcMaxValueLen;
    DWORD lpcbSecurityDescriptor;
    FILETIME lpfLastWriteTime;
    char *pMsg = NULL;
    long R;

long OpenK = RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, &phkResult);

if (OpenK == ERROR_SUCCESS)
    {
        long Query = RegQueryInfoKey(phkResult, lpClass, &lpcClass, lpReserved, &lpcSubKeys, &lpcMaxSubKeyLen,
            &lpcMaxClassLen, &lpcValues, &lpcMaxValueLen, &lpcMaxValueLen, &lpcbSecurityDescriptor, &lpfLastWriteTime);

        if (Query == ERROR_SUCCESS)
        {
            if (lpcValues)
            {

                cout << "Number of values in the subkey: " << lpcValues << endl;
                cout << "\nThe values are:: \n" << endl;

                //Show RunMRU values and content.

                for (i = 0; i < lpcValues; i++)
                {

                    lpcchValueName = MAX_VALUE_NAME;
                    //lpValueName[0] = '\0';    
                    lpValueName[MAX_VALUE_NAME];
                    //lpData[MAX_DATA + 2];
                    cbData = MAX_DATA;


                    R = RegEnumValue(phkResult, i, lpValueName, &lpcchValueName, NULL,
                        &type, lpData, &cbData);

                    int Quantity = strlen((const char *)lpData);




                    if (R != ERROR_NO_MORE_ITEMS)
                    {

                            cout << "\0" << lpValueName << ": " << lpData << endl;
                            cout << "Number of characters: " << Quantity << endl;
                            cout << "\n";



                    }
                    else
                    {
                        cout << "Error enumerating values. Code: " << R << endl;
                    }



                }


            } //EOIF.

And this is what I got:

enter image description here

The questions are:

  1. How do I remove the "\1" at the end of the string from lpData? [Solved: See below]

PD. lpData gets the value's content, not the value.

  1. How do I avoid showing the RunMRU value without affecting the "for" and the other values and content?

EDIT 1: I could solve the "\1" question by adding this into the FOR:

int Quantity = strlen(lpData);
std::string original = lpData;
std::string result = original.substr(0, original.size() - 2);
std::string result = original.substr(0, Quantity - 2);

if (R != ERROR_NO_MORE_ITEMS)
{
cout << "\0" << lpValueName << ": " << (TCHAR*)result.c_str() << endl; 
cout << "Numbers of characters: " << Quantity-2 << endl;
cout << "\n";

}
else 
{
cout << "Error enumerating the values. Code: " << R << endl;
}

Now I just need to know how to avoid showing the MRUList value within the FOR.

Sergio Calderon
  • 837
  • 1
  • 13
  • 32
  • Copy the string, search it backwards for the last instance of "\", replace that char with 0x0 or '\0'. strrchr would be what I'd use in C. – enhzflep Oct 13 '13 at 15:07
  • 1
    You do realize that your program is accessing undocumented registry keys, right? Make sure your customers understand that it may stop working at any time. – Raymond Chen Oct 13 '13 at 20:24

2 Answers2

0
char* dest = new char[strlen(lpData) - 2];
memcpy(dest, lpData, strlen(lpData) - 2)

//do stuff with dest..
delete[] dest;

Another way is to std::string it..

std::string dest = std::string(lpData);
dest.erase(std::find_last_of("\\1"), 2);
Brandon
  • 22,723
  • 11
  • 93
  • 186
0

I think you may have not only \1. It is possible to have \2 or even \100, so my answer shows how to cut all that stuff from the end.

You need to substring you value. Try this:

size_t len = strlen(lpData);
for (int i = len - i; i <= 0; --i)
{
    if (lpData == '\\')
    {
        lpData[i] = '\0';
        break;
    }
}

You may need some other procedure instead of strlen depending on setting, you can choose it from here. Probably wcslen.


How do I avoid showing the RunMRU value without affecting the "for" and the other values and content?

It is more C solution then C++ but this way performance is better. Pure C++ solution would be connected with std::string and would take more clocks to get wanted result.


Also you may found this helpful.

Community
  • 1
  • 1
ST3
  • 8,826
  • 3
  • 68
  • 92
  • Thanks! But not working, because I need to initialize the len like that: size_t len = strlen((const char *)lpData); The cycle does not allow to operand BYTE with a char. Any idea? – Sergio Calderon Oct 13 '13 at 15:22
  • Do you have UNICODE defined in your project? – ST3 Oct 13 '13 at 15:23
  • I set it like "Not Set" in the Properties. – Sergio Calderon Oct 13 '13 at 15:27
  • ST3's for loop is wrong.. It should be: `for (int I = len; I > 0; --I)` then the if statement should be: `if (lpData[I] == '\\')` Then it should work. In other words: http://pastebin.com/FMFFH7B9 – Brandon Oct 13 '13 at 15:37
  • However I get the same error when I am writing the "if" sentence: "Error:operand types are incompatible ("TCHAR *" and "char")" No matter if I set the lpData as BYTE or TCHAR. – Sergio Calderon Oct 13 '13 at 15:48
  • Solved. See the post. I just need now how to avoid the MRUList value while printing the results. Any ideas? – Sergio Calderon Oct 13 '13 at 16:32