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("");
}
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"";
}