Search code examples
c++visual-studio-201564-bitregistrywindows-10

C++ RegGetValue function output error


I am trying to search the registry's uninstall folder for a given program that I know is there by checking regedit. My function currently finds the program, but for some reason it doesn't update the output value from the RegGetValue function until the next iteration. So it prints the correct registry key and its predecessor. Any ideas?

I am on a Windows 10 64bit workstation with Intel processors using Visual Studio 2015 if that matters.

main.cpp

#include "Registry.h"
#include <Windows.h>
#include <tchar.h>

void main()
{
    Registry test(_T("Microsoft SQL Server 2012 Native Client "));
}

Registry.h

#pragma once

#include <Windows.h>
#include <string>

#define REG_PATH L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
#define X86REG_PATH L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"

class Registry
{
public:
    Registry(TCHAR* name);
    ~Registry();
    TCHAR* findGUID();
    TCHAR* getDisplayName();
    TCHAR* getGUID();
    TCHAR* getVersion();
    TCHAR* getPublisher();
    TCHAR* getInstallDate();
private:
    TCHAR* displayName;
    TCHAR* guid;
    TCHAR* version;
    TCHAR* publisher;
    TCHAR* installDate;
};

Registry.cpp

#pragma once

#include "Registry.h"
#include <Windows.h>
#include <iostream>
#include <tchar.h>
#include <fstream>

Registry::Registry(TCHAR* name)
{
    HKEY hKey;
    LPCTSTR lpSubKey;
    DWORD ulOptions;
    REGSAM samDesired;

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_PATH, NULL, KEY_READ, &hKey) == ERROR_SUCCESS)
    {
        std::wofstream file;
        file.open("test.txt");
        int index = 0;
        HKEY UninstallDir = hKey;
        TCHAR subKey[MAX_PATH];
        DWORD subKeySize = MAX_PATH;
        while (RegEnumKeyEx(hKey, index, subKey, &subKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
        {
            HKEY guid;
            TCHAR* guidPath = new TCHAR[MAX_PATH];
            _tcscpy_s(guidPath, MAX_PATH, REG_PATH);
            _tcscat_s(guidPath, MAX_PATH, subKey);
            TCHAR compareName[MAX_PATH];
            DWORD nameSize;
            //print all registry keys to file
            file << index << ": " << guidPath << std::endl;
            int test;
            RegGetValue(HKEY_LOCAL_MACHINE, guidPath, _T("DisplayName"), RRF_RT_ANY, NULL, &compareName, &nameSize);
            //compare all registry keys *temporary to debug
            if (_tcscmp(guidPath, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{49D665A2-4C2A-476E-9AB8-FCC425F526FC}")) == 0)
            {
                std::wcout << guidPath << " found" << std::endl;
            }
            if (_tcscmp(compareName, name) == 0)
            {
                _tprintf(_T("%d: %s\n"), index, guidPath);
            }
            //print if found

            index++;
            subKeySize = 260;
        }
        file.close();
    }
    else
    {
        std::cout << "Could not open registry key." << std::endl;
    }
    //temporary to see console
    std::cin.get();
}
//still need to be completed   
Registry::~Registry()
{
}

TCHAR* Registry::findGUID()
{
    return _T("");
}

TCHAR* Registry::getDisplayName()
{
    return _T("");
}

TCHAR* Registry::getGUID()
{
    return _T("");
}

TCHAR* Registry::getVersion()
{
    return _T("");
}

TCHAR* Registry::getPublisher()
{
    return _T("");
}

TCHAR* Registry::getInstallDate()
{
    return _T("");
}

Solution

  • I see a lot of problems with your code.

    You are mixing std::wcout and _tprintf(), which causes buffering conflicts.

    You are mixing char and wchar_t data incorrectly.

    You are leaking guidPath on every loop iteration.

    You are not initializing nameSize when calling RegGetValue().

    You are not setting up your code to access the 32bit Wow64Node key correctly.

    Try something more like this instead.

    main.cpp

    #include <Windows.h>
    #include "Registry.h"
    
    void main()
    {
        Registry test(L"Microsoft SQL Server 2012 Native Client");
    }
    

    Registry.h

    #pragma once
    
    #include <Windows.h>
    #include <string>
    
    class Registry
    {
    public:
        Registry(const std::wstring &name);
        ~Registry();
        std::wstring findGUID();
        std::wstring getDisplayName();
        std::wstring getGUID();
        std::wstring getVersion();
        std::wstring getPublisher();
        std::wstring getInstallDate();
    private:
        std::wstring displayName;
        std::wstring guid;
        std::wstring version;
        std::wstring publisher;
        std::wstring installDate;
    };
    

    Registry.cpp

    #pragma once
    
    #include <Windows.h>
    #include "Registry.h"
    #include <iostream>
    #include <fstream>
    
    #define REG_PATH L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
    
    Registry::Registry(const std::wstring &name)
    {
        HKEY hKey;
    
        // If you want to open the 32bit Wow64Node key,
        // DO NOT open the key directly! Open the 64bit
        // key and include the KEY_WOW64_32KEY flag
        // so it will redirect to the Wow64Node key...
        if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_PATH, NULL, KEY_READ, &hKey) == ERROR_SUCCESS)
        {
            std::wofstream file;
            file.open(L"test.txt");
    
            WCHAR subKey[MAX_PATH];
            DWORD subKeySize = MAX_PATH;
            WCHAR compareName[MAX_PATH];
            DWORD nameSize;
            int index = 0;
    
            while (RegEnumKeyEx(hKey, index, subKey, &subKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
            {
                // print all registry keys to file
                file << index << L": " << REG_PATH << subKey << std::endl;
                int test;
                nameSize = sizeof(compareName);
                RegGetValue(hKey, NULL, L"DisplayName", RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ | RRF_ZEROONFAILURE, NULL, compareName, &nameSize);
                //compare all registry keys *temporary to debug
                if (wcscmp(subKey, L"{49D665A2-4C2A-476E-9AB8-FCC425F526FC}") == 0)
                {
                    std::wcout << subKey << L" found" << std::endl;
                }
                if (name == compareName)
                {
                    std::wcout << name << L" found" << std::endl;
                }
                //print if found
    
                index++;
                subKeySize = MAX_PATH;
            }
            file.close();
        }
        else
        {
            std::wcout << L"Could not open registry key." << std::endl;
        }
    
        //temporary to see console
        std::wcin.get();
    }
    
    //still need to be completed   
    Registry::~Registry()
    {
    }
    
    std::wstring Registry::findGUID()
    {
        return L"";
    }
    
    std::wstring Registry::getDisplayName()
    {
        return L"";
    }
    
    std::wstring Registry::getGUID()
    {
        return L"";
    }
    
    std::wstring Registry::getVersion()
    {
        return L"";
    }
    
    std::wstring Registry::getPublisher()
    {
        return L"";
    }
    
    std::wstring Registry::getInstallDate()
    {
        return L"";
    }