Trying to find the path to excel by searching the registry - c++

I'm trying to find the path to Excel using the registry, and have tried to adapt some code I've found on the internet. I'm using 64-bit Win7 and have confirmed the key is there using regedit.
#include <windows.h>
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
HKEY hKey = 0;
char buf[255] = {0};
DWORD dwType = 0;
DWORD dwBufSize = sizeof(buf);
const char* subkey = "SOFTWARE\\Classes\\Excel.Application\\CLSID";
if( RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey) == ERROR_SUCCESS)
{
dwType = REG_SZ;
if( RegQueryValueEx(hKey,"default",0, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
{
cout << "key value is '" << buf << "'\n";
}
else
cout << "can not query for key value\n";
RegCloseKey(hKey);
}
else
cout << "Can not open key\n";
cin.ignore();
return 0;
}
Does anyone know why this isn't working?
Thanks
James

Try changing the
RegQueryValueEx(hKey,"default",0, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
with
RegQueryValueEx(hKey, NULL, 0, &dwType, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
If you want the "default" value, you should pass NULL or a empty string in the lpValueName field.
Also if your application is not 64-bit and you are running in a 64-bit OS, you should check the KEY_WOW64_64KEY flag on the RegOpenKeyEx function, to have access to the key you want.

Almost all Windows API functions, when the fail, set a more detailed error code that you can get by calling GetLastError() for more details. You should call that after a call to RegOpenKey() fails.
In your example, the RegOpenKey() is probably failing with an access denied error. RegOpenKey() open a registry key with full read/write/delete access. A standard user on Windows 7 doesn't have write or delete access on HKLM so RegOpenKey() will fail.
You should instead use RegOpenKeyEx() which will let you specify read-only access, as below.
RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &hKey)
PS. When asking a question like the one above you should be more descriptive on how the code is failing. In your example above you should include which line/function call is failing. For example "When I use this code, the call to RegOpenKey is failing.

Related

How to add a String Value/ Name Data pair in Windows Registry Editor key using C++ and Windows Registry API's

I want to add a string name and its value to the Windows Registry using C++ code, to stop browsers other than Firefox stop running. I plan to do the Windows Registry editing in a loop for all browsers, but for now I am implementing it for Chrome only.
My current code below is adding a value to the Default string, and it is not working, but I want to create a Debugger string and set it to "ntsd -c q" in the chrome.exe subkey, as shown in the picture below.
Here is my code, which is adding "ntsd -c q" for the Default string and not creating a new Debugger string. I am not able to clearly understand from Microsoft's documentation about how to achieve this using C/C++. I have seen some solutions that do it via the command line, but co-workers are very ethical and they don't prefer that way.
#include <Windows.h>
#include <iostream>
int main()
{
HKEY hkey;
LSTATUS ReturnValue = 0;
LPCTSTR Directory = TEXT("SOFTWARE\\Microsoft\\Windows\ NT\\CurrentVersion\\Image\ File\ Execution\ Options\\chrome.exe");
ReturnValue = RegOpenKeyEx(HKEY_LOCAL_MACHINE, Directory, 0, KEY_ALL_ACCESS, &hkey);
if (ERROR_SUCCESS != ReturnValue)
{
printf("RegOpenKeyEx failed\n");
printf("%d\n", GetLastError());
return -1;
}
//LPCSTR value = "Debugger";
//ReturnValue = RegQueryValueEx(HKEY_LOCAL_MACHINE, Directory, NULL, NULL, value, sizeof(value));
LPCSTR Value = "ntsd\ -c\ q\0";
ReturnValue = RegSetValueA(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\ NT\\CurrentVersion\\Image\ File\ Execution\ Options\\chrome.exe",REG_SZ, Value, sizeof(Value));
if (ERROR_SUCCESS != ReturnValue)
{
printf("RegStatusValueA failed\n");
printf("%d\n", GetLastError());
return -1;
}
ReturnValue = RegCloseKey(hkey);
if (ERROR_SUCCESS != ReturnValue)
{
printf("RegCloseKey failed\n");
printf("%d\n", GetLastError());
return -1;
}
return 0;
}
KEY_ALL_ACCESS requires admin rights. All you really need in this situation is KEY_SET_VALUE instead. Don't ask for more permissions than you actually need. But, you do still need admin rights to write to HKEY_LOCAL_MACHINE to begin with. So make sure you are running your code as an elevated user.
In any case, your string literals have a few \ that don't belong. But more importantly, your use of RegSetValueA() is completely wrong for this task. It is a deprecated API that can only write to the (Default) string and nothing else (and, you are not even calling it correctly anyway, you would need strlen(Value)+1 instead of sizeof(Value) - not that it matters because that parameter is ignored anyway).
In order to create your Debugger string value, you need to use RegSetValueEx() instead, eg:
#include <Windows.h>
#include <iostream>
int main()
{
HKEY hkey;
LPCTSTR Directory = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\chrome.exe");
LSTATUS ReturnValue = RegOpenKeyEx(HKEY_LOCAL_MACHINE, Directory, 0, KEY_SET_VALUE, &hkey);
if (ERROR_SUCCESS != ReturnValue)
{
printf("RegOpenKeyEx failed: %u\n", GetLastError());
return -1;
}
LPCTSTR Value = TEXT("ntsd -c q");
ReturnValue = RegSetValueEx(hkey, TEXT("Debugger"), 0, REG_SZ, (const BYTE*)Value, (lstrlen(Value)+1) * sizeof(TCHAR));
if (ERROR_SUCCESS != ReturnValue)
{
printf("RegSetValueExA failed: %u\n", GetLastError());
RegCloseKey(hkey);
return -1;
}
ReturnValue = RegCloseKey(hkey);
if (ERROR_SUCCESS != ReturnValue)
{
printf("RegCloseKey failed: %u\n", GetLastError());
return -1;
}
return 0;
}

How to write a 32 Bit D-Word to Windows registry in C++

I am trying to disable the Windows Defender using a C++ Win32API application.
To do that I need to write a D Word into the registry (DisableAntiSpyware = 1).
I always do that manually after installing a new Windows.
So here is my code, but its not working.
Maybe someone could tell me why or what is wrong with it. Thank you!
OK I've changed the code a bit, still not working...
case 1:
//::MessageBeep(MB_ICONERROR);
::MessageBox(hWnd, L"Button was Pressed",L"Button was clicked?",MB_OK);
LONG
SetRegValue
(
const wchar_t* path
, const wchar_t *name
, const BYTE *value
);
{
LONG status;
HKEY hKey;
DWORD value = 0x00000001;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"\\SOFTWARE\\Policies\\Microsoft\\Windows Defender", 0, KEY_ALL_ACCESS, &hKey);
if ((status == ERROR_SUCCESS) && (hKey != NULL))
{
status = RegSetValueEx(hKey, L"test", 0, REG_DWORD, (const BYTE*)&value,sizeof(value));
RegCloseKey(hKey);
}
return status;
::MessageBeep(MB_ICONERROR);
}
}
}
break;
When opening a Registry key, you should request only the rights you actually need. So replace KEY_ALL_ACCESS with KEY_SET_VALUE instead, since all you are doing is writing a value. But even then, you might still need to run your app with elevated permissions in order to write to HKEY_LOCAL_MAHCINE, unless you give your user account write access to the Windows Defender key beforehand.
Also, if your code is compiled as 32bit and runs on a 64bit system, and it needs to write to the 64bit Registry, then you have to include the KEY_WOW64_64KEY flag otherwise you may be subject to Registry Reflection/Registry Redirection.
Try something more like this instead:
case 1:
{
::MessageBox(hWnd, L"Button was Pressed", L"Button was clicked?", MB_OK);
DWORD value = 1;
DWORD flags = KEY_SET_VALUE;
#if !defined(_WIN64)
BOOL bIsWow64Process = FALSE;
if (IsWow64Process(GetCurrentProcess(), &bIsWow64Process) && bIsWow64Process)
flags |= KEY_WOW64_64KEY;
#endif
HKEY hKey;
LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"\\SOFTWARE\\Policies\\Microsoft\\Windows Defender", 0, flags, &hKey);
if ((status == ERROR_SUCCESS) && (hKey != NULL))
{
status = RegSetValueEx(hKey, L"DisableAntiSpyware", 0, REG_DWORD, (const BYTE*)&value, sizeof(value));
RegCloseKey(hKey);
}
::MessageBeep(MB_ICONERROR);
}
break;
You can't write to any key under HKEY_LOCAL_MACHINE unless the program is running with elevated privileges, i.e. administrator mode. The call to RegOpenKeyEx or RegSetValueEx will fail.

RegCreateKeyEX returns ERROR_INVALID_FUNCTION

I am writing a program that needs to create/delete a registry key. I am having a problem that the code to create the key returns ERROR_INVALID_FUNCTION.
If you look in the registry the key has been created so I'm not sure what the impact of this error is.
The value of key is "SOFTWARE\\Wow6432Node\\COMPANY\\APPLICATION"
The code is:
int RegistryViewer::CreateRegistryLocation(const char* key)
{
HKEY hkey = 0;
int retVal = RegistryViewer::OpenRegistryLocation(key);
if(retVal != ERROR_SUCCESS)
{
retVal = RegCreateKeyEx(HKEY_LOCAL_MACHINE, CString(key), 0, NULL,REG_OPTION_NON_VOLATILE, KEY_WOW64_32KEY | KEY_WRITE, NULL, &hkey, NULL);
RegCloseKey(hkey);
}
return retVal;
}
Is the problem that although the key is created, it's unable to set the permissions correctly?
Thanks.
Going to answer my own question in case it's helpful to others in future. I think I had two problems that were limiting access to the registry key, firstly I was opening it twice (once to see it existed and then when it was created), secondly I was assigning it KEY_WRITE permissions. Since RegCreateKeyEx opens a key if it already exists the first check was pointless and may have been holding the resource. I'm not sure the second thing was a problem but since it's changed in the code I thought I'd mention it.
Working code looks like this:
//Create a registry location
int RegistryViewer::CreateRegistryLocation(const char* key)
{
HKEY hkey = 0;
int retVal = RegCreateKeyEx(HKEY_LOCAL_MACHINE, CString(key), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkey, NULL);
if(retVal == ERROR_SUCCESS)
RegCloseKey(hkey);
return retVal;
}
The comment by eryksun was useful for another issue though as I was manually checking which part of the registry to use and he enabled me to remove that check.

Get machine name from registry using RegQueryValueEx

I am trying to do an application which shows machine name of the PC fetch from registry. It has to run in 64 bit window 7 machine.
But I can only manage to output the system error message.
In below code,
I always get value of value1str (using RegOpenKeyEx method) => as 0 (which is ERROR_SUCCESS)
and value2str (using RegQueryValueEx method) => as 2 (which is ERROR_FILE_NOT_FOUND)
Anyone knows how to display the real machine name?
Please help!
#define KEY_WOW64_64KEY (0x0100)
#include <iostream>
#include <string>
BEGIN_MESSAGE_MAP(CPOConLogApp, CWinApp)
END_MESSAGE_MAP()
CPOConLogApp::CPOConLogApp()
{
int value1;
int value2;
HKEY root = NULL;
CString value1Str,value2Str;
value1=RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"), NULL, KEY_READ|KEY_WOW64_64KEY, &root);
value1Str.Format("%d",value1);
MessageBoxA ( NULL, value1Str, "Test", MB_OK );
LPBYTE data = NULL;
DWORD dwType;
DWORD dwSize;
data = new BYTE[dwType];
value2=RegQueryValueEx(HKEY_LOCAL_MACHINE,TEXT("Computer Name"), NULL, &dwType, data, &dwSize);
value2Str.Format("%d",value2);
MessageBoxA (NULL, value2Str , "Test", MB_OK );
}
Alternative solution:
Instead of trying to find where is the key in the Registry and how to read it, you can just rely on the API Microsoft provide.
To get the Computer NetBIOS name (initialized from registry at system startup) use GetComputerName like below.
#include <windows.h>
int main()
{
char buf[1024];
DWORD dwCompNameLen = 1024;
if (0 != GetComputerName(buf, &dwCompNameLen)) {
printf("name %s\n", buf);
}
return 0;
}
You can read the computer name from the below mentioned registry key,
System\CurrentControlSet\Control\ComputerName\ComputerName
I found out why always ERROR_FILE_NOT_FOUND value. I suppose to put last parameter of RegOpenKeyEx to the first parameter in RegQueryValueEx. It should be like this.
value2=RegQueryValueEx(root,TEXT("Computer Name"), NULL, &dwType, data, &dwSize);
If you want prompts the value of the registry, computer name in this case, use the below code.
value.Format("%s",pszBuffer);
MessageBoxA (NULL, value , "Test", MB_OK );

Enumerating registry subkeys in HKEY_LOCAL_MACHINE\SOFTWARE in c++

I have trouble enumerating subkeys of HKEY_LOCAL_MACHINE\SOFTWARE, all I can get is subkeys on HKEY_LOCAL_MACHINE.
WCHAR Temp[255];
DWORD TMP = 255;
HKEY hKey;
int count = 0;
long regError;
...
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\", NULL, KEY_ENUMERATE_SUB_KEYS, &hKey);
if (regError == ERROR_SUCCESS){
file<<"Key opened!\nSubkeys of HKEY_LOCAL_MACHINE\\SOFTWARE:\n\n";
while ((regError = RegEnumKeyEx(HKEY_LOCAL_MACHINE, count, Temp, &TMP, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS){
TMP = sizeof (Temp);
count++;
file<<count<<". "<<Temp<<std::endl;
}
if (regError == ERROR_NO_MORE_ITEMS) file<<"Done.";
else file << std::endl <<"RegEnumKeyEx error!";
}
else file << std::endl <<"RegOpenKeyEx error!";
RegCloseKey(hKey);
Here is my file:
Key opened!
Subkeys of HKEY_LOCAL_MACHINE\SOFTWARE:
1. BCD00000000
2. DRIVERS
3. HARDWARE
4. SAM
5. SECURITY
6. SOFTWARE
7. SYSTEM
Done.
How can I output keys inside of HKEY_LOCAL_MACHINE\SOFTWARE and not just HKLM? Thanks.
You are passing the wrong HKEY to RegEnumKeyEx(). You are passing the HKLM root, but you need to pass the HKEY that RegOpenKeyEx() returns. In other words, change this:
RegEnumKeyEx(HKEY_LOCAL_MACHINE, ...)
To this:
RegEnumKeyEx(hKey, ...)