Add Application to Startup (Registry) - c++

I'm trying to add my software to registry, I have found some pieces of the codes I can use but not full working code C/C++ is new to me and can't create it on my own. But here is the basic idea: Check if reg key set if not create it.
I was able to get my program location using this code:
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL,szPath,MAX_PATH);
And was able to create the key with: (Not sure if it's the right way)
HKEY newValue;
RegOpenKey(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&newValue);
RegSetValueEx(newValue,"myprogram",0,REG_SZ,(LPBYTE)szPath,sizeof(szPath));
RegCloseKey(newValue);
return 0;
What is missing, A small check if the key isn't already there...
Thank you!

Here's some code that likely does what you want. Call RegisterProgram for your EXE to self-register itself for automatically being started when the user logs in. This function calls GetModuleFileName and then invokes another helper function called RegisterMyProgramForStartup that does the writing to the registry.
Call IsMyProgramRegisteredForStartup(L"My_Program") to detect if the registration actually exists and appears valid.
One quick note. The performance impact of checking to see if the key exists before actually writing it out again is negligible. You could just call RegisterProgram blindly and it will overwrite the key if it already exists. Detecting if the registration exists is useful for initializing your UI checkbox that enables or disables auto-start. (You are giving your users a choice, right? Because I hate apps that automatically install themselves to run automatically without giving me a choice.)
BOOL IsMyProgramRegisteredForStartup(PCWSTR pszAppName)
{
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwRegType = REG_SZ;
wchar_t szPathToExe[MAX_PATH] = {};
DWORD dwSize = sizeof(szPathToExe);
lResult = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, &hKey);
fSuccess = (lResult == 0);
if (fSuccess)
{
lResult = RegGetValueW(hKey, NULL, pszAppName, RRF_RT_REG_SZ, &dwRegType, szPathToExe, &dwSize);
fSuccess = (lResult == 0);
}
if (fSuccess)
{
fSuccess = (wcslen(szPathToExe) > 0) ? TRUE : FALSE;
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
return fSuccess;
}
BOOL RegisterMyProgramForStartup(PCWSTR pszAppName, PCWSTR pathToExe, PCWSTR args)
{
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwSize;
const size_t count = MAX_PATH*2;
wchar_t szValue[count] = {};
wcscpy_s(szValue, count, L"\"");
wcscat_s(szValue, count, pathToExe);
wcscat_s(szValue, count, L"\" ");
if (args != NULL)
{
// caller should make sure "args" is quoted if any single argument has a space
// e.g. (L"-name \"Mark Voidale\"");
wcscat_s(szValue, count, args);
}
lResult = RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, (KEY_WRITE | KEY_READ), NULL, &hKey, NULL);
fSuccess = (lResult == 0);
if (fSuccess)
{
dwSize = (wcslen(szValue)+1)*2;
lResult = RegSetValueExW(hKey, pszAppName, 0, REG_SZ, (BYTE*)szValue, dwSize);
fSuccess = (lResult == 0);
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
return fSuccess;
}
void RegisterProgram()
{
wchar_t szPathToExe[MAX_PATH];
GetModuleFileNameW(NULL, szPathToExe, MAX_PATH);
RegisterMyProgramForStartup(L"My_Program", szPathToExe, L"-foobar");
}
int _tmain(int argc, _TCHAR* argv[])
{
RegisterProgram();
IsMyProgramRegisteredForStartup(L"My_Program");
return 0;
}

To check whether or not the value exists, call RegQueryValueEx.
LONG retval = RegQueryValueEx(hKey, "myprogram", NULL, NULL, NULL, NULL);
Note that what you called newValue is actually a key rather than a value. To avoid confusion you should name it such. I used the name hKey.
Then to check whether or not the value exists, compare retval against ERROR_SUCCESS as described in the documentation.
The other problem with your code is that there is absolutely no error checking. I'll leave that to you to address.

You forget to write an argument about security access

Related

In c++, how to disable windows UAC control by program?

In program C++, how to change the windows UAC to always notify or never notify.
Manually, I should change like this:
I found C# code from Internet:
const string UACkey = #"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System";
const string Subkey = "EnableLUA";
RegistryUtilities.SetValue(UACkey, Subkey, **1**, Microsoft.Win32.RegistryValueKind.DWord, RegistryUtilities.WOW64Key.Key64);
Does somebody know how to change into c++ code?
I tried to change the Registry with c++, but it does not work.
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwSize;
const size_t count = MAX_PATH*2;
wchar_t szValue[count] = {};
lResult = RegOpenKeyExW(HKEY_CURRENT_USER, L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, (KEY_WRITE | KEY_READ), &hKey);
fSuccess = (lResult == 0);
if (fSuccess)
{
dwSize = (wcslen(szValue)+1)*2;
lResult = RegSetValueExW(hKey, L"EnableLUA", 0, REG_SZ, (BYTE*)szValue, dwSize);
fSuccess = (lResult == 0);
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
To answer your stated question, you can set registry keys with RegSetKeyValue, however you have to get past UAC in order to change the registry. To answer your implicit question, yes you could probably disable UAC programatically for malicious purposes, however you have to get past UAC in the first place to do so. Once you're on the other side of the airtight hatchway, you can do whatever you want of course. However you still have to get past the UAC hurdle.
Furthermore, I highly recommend you do a cursory google search before posting a question like this. The Windows C API is documented very well on MSDN.
Your code is actually very close;
DWORD val = 0;
HKEY uaKey;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_WRITE , &uaKey);
if(uaKey == NULL)
{
//Handle error message here
}
else
{
if (RegSetValueEx (uaKey, "EnableLUA", 0, REG_DWORD, (const BYTE *)&val, sizeof(val)) != ERROR_SUCCESS)
{
//Error
}
else
{
//Success
}
RegCloseKey(uaKey);
}

HKEY handle is NULL, during debug it writes unused <unable to read memory>

I have defined HKEY in anonymous namespace to use it in more cpp. I create register key and it normally returns HKEY, then I want to use that handle in another cpp, and it is NULL. When I debug, it writes unused .
this is one .h file (structAndHandle.h)
namespace
{
StCommand command;
HANDLE dataInEvent;
HANDLE dataOutEvent;
HANDLE threadHandle;
HANDLE mutexHandle;
HKEY hKey;
TCHAR repositoryPath[MAX_PATH];
}
here I create it... (repositoryStore.cpp)
if (RegCreateKeyEx(HKEY_CURRENT_USER, STR_KEY_NAME, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)
!= ERROR_SUCCESS)
{
_tprintf_s(_T("Could not create or open register key: %s\n"), STR_KEY_NAME);
}
TCHAR pathValueName[MAX_PATH] = _T("repositoryPath");
TCHAR indexValueName[MAX_PATH] = _T("repositoryIndex");
TCHAR repPath[MAX_PATH] = _T("C:\\repository\0");
if (RegSetValueEx(hKey, pathValueName, 0L, REG_SZ, (LPBYTE)repPath, _tcslen(repPath) * sizeof(TCHAR))
!= ERROR_SUCCESS)
{
_tprintf_s(_T("Could not create or set register value: %s\n"), repPath);
}
DWORD repositoryIndex = 0;
if (RegSetValueEx(hKey, indexValueName, 0L, REG_DWORD, (LPBYTE)&repositoryIndex, sizeof(DWORD))
!= ERROR_SUCCESS)
{
_tprintf_s(_T("Could not create or set register value: repositoryIndex\n"));
}
and when I want to use it here, in another cpp, it is NULL (settings.cpp)
DWORD GetDwordSetting(TCHAR* valueName, DWORD defaultValueData)
{
DWORD receivedData;
DWORD type = REG_DWORD;
DWORD size = sizeof(DWORD);
if (RegQueryValueEx(hKey, valueName, 0L, &type, (LPBYTE)&receivedData, &size)
!= ERROR_SUCCESS)
{
_tprintf_s(_T("Could not get register value: repositoryIndex\n"));
return defaultValueData;
}
return receivedData;
}
DWORD SetDwordSetting(TCHAR* valueName, DWORD valueData)
{
if (RegSetValueEx(hKey, valueName, 0L, REG_DWORD, (LPBYTE)&valueData, sizeof(DWORD))
!= ERROR_SUCCESS)
{
_tprintf_s(_T("Could not set register value: repositoryIndex\n"));
return GetLastError();
}
return 0;
}
DWORD GetSzSetting(TCHAR* valueName, TCHAR* defaultValueData)
{
DWORD type = REG_SZ;
DWORD size = sizeof(TCHAR) * sizeof(MAX_PATH);
if (RegQueryValueEx(hKey, valueName, 0L, &type, (LPBYTE)&repositoryPath, &size)
!= ERROR_SUCCESS)
{
_tcscpy_s(repositoryPath, defaultValueData);
_tprintf_s(_T("Could not get register value: repositoryPath\n"));
return GetLastError();
}
return 0;
}
Instead of placing your handles in an unnamed namespace put them in a singleton class, that multiple .cpp files can access the same instance:
class AllMyHandles {
public:
static AllMyHandles& instance() {
static AllMyHandles theInstance;
return theInstance;
}
// provide getter setter methods for these handles
private:
StCommand command;
HANDLE dataInEvent;
HANDLE dataOutEvent;
HANDLE threadHandle;
HANDLE mutexHandle;
HKEY hKey;
TCHAR repositoryPath[MAX_PATH];
AllMyHandles() {}
};
Another way, is to have a simple class/struct (without the instance() function), and to pass instances of these around as reference parameters.

Save Me Simple Add to Startup via Registry [duplicate]

I'm trying to add my software to registry, I have found some pieces of the codes I can use but not full working code C/C++ is new to me and can't create it on my own. But here is the basic idea: Check if reg key set if not create it.
I was able to get my program location using this code:
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL,szPath,MAX_PATH);
And was able to create the key with: (Not sure if it's the right way)
HKEY newValue;
RegOpenKey(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&newValue);
RegSetValueEx(newValue,"myprogram",0,REG_SZ,(LPBYTE)szPath,sizeof(szPath));
RegCloseKey(newValue);
return 0;
What is missing, A small check if the key isn't already there...
Thank you!
Here's some code that likely does what you want. Call RegisterProgram for your EXE to self-register itself for automatically being started when the user logs in. This function calls GetModuleFileName and then invokes another helper function called RegisterMyProgramForStartup that does the writing to the registry.
Call IsMyProgramRegisteredForStartup(L"My_Program") to detect if the registration actually exists and appears valid.
One quick note. The performance impact of checking to see if the key exists before actually writing it out again is negligible. You could just call RegisterProgram blindly and it will overwrite the key if it already exists. Detecting if the registration exists is useful for initializing your UI checkbox that enables or disables auto-start. (You are giving your users a choice, right? Because I hate apps that automatically install themselves to run automatically without giving me a choice.)
BOOL IsMyProgramRegisteredForStartup(PCWSTR pszAppName)
{
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwRegType = REG_SZ;
wchar_t szPathToExe[MAX_PATH] = {};
DWORD dwSize = sizeof(szPathToExe);
lResult = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, &hKey);
fSuccess = (lResult == 0);
if (fSuccess)
{
lResult = RegGetValueW(hKey, NULL, pszAppName, RRF_RT_REG_SZ, &dwRegType, szPathToExe, &dwSize);
fSuccess = (lResult == 0);
}
if (fSuccess)
{
fSuccess = (wcslen(szPathToExe) > 0) ? TRUE : FALSE;
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
return fSuccess;
}
BOOL RegisterMyProgramForStartup(PCWSTR pszAppName, PCWSTR pathToExe, PCWSTR args)
{
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwSize;
const size_t count = MAX_PATH*2;
wchar_t szValue[count] = {};
wcscpy_s(szValue, count, L"\"");
wcscat_s(szValue, count, pathToExe);
wcscat_s(szValue, count, L"\" ");
if (args != NULL)
{
// caller should make sure "args" is quoted if any single argument has a space
// e.g. (L"-name \"Mark Voidale\"");
wcscat_s(szValue, count, args);
}
lResult = RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, (KEY_WRITE | KEY_READ), NULL, &hKey, NULL);
fSuccess = (lResult == 0);
if (fSuccess)
{
dwSize = (wcslen(szValue)+1)*2;
lResult = RegSetValueExW(hKey, pszAppName, 0, REG_SZ, (BYTE*)szValue, dwSize);
fSuccess = (lResult == 0);
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
return fSuccess;
}
void RegisterProgram()
{
wchar_t szPathToExe[MAX_PATH];
GetModuleFileNameW(NULL, szPathToExe, MAX_PATH);
RegisterMyProgramForStartup(L"My_Program", szPathToExe, L"-foobar");
}
int _tmain(int argc, _TCHAR* argv[])
{
RegisterProgram();
IsMyProgramRegisteredForStartup(L"My_Program");
return 0;
}
To check whether or not the value exists, call RegQueryValueEx.
LONG retval = RegQueryValueEx(hKey, "myprogram", NULL, NULL, NULL, NULL);
Note that what you called newValue is actually a key rather than a value. To avoid confusion you should name it such. I used the name hKey.
Then to check whether or not the value exists, compare retval against ERROR_SUCCESS as described in the documentation.
The other problem with your code is that there is absolutely no error checking. I'll leave that to you to address.
You forget to write an argument about security access

Create new data in registry key?

I just create new registry key called MyTestApp, and want to add new data in it, but don't know how. So I have following code.
bool CreateSectionDataRegistry(CString sectionData, CString sectionValue)
{
HKEY hKey; //registry key handle
LONG lResult; //result of registry operations
DWORD dwType, dwSize=0;
//try to open the key that we are currently pointing at with rootPath
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, rootPath + "\\" + "MyTestApp", NULL, KEY_ALL_ACCESS, &hKey);
if (lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA)
{
//we have successfully opened the registry key. Now try to access the data
lResult = RegQueryValueEx(HKEY_LOCAL_MACHINE, sectionData, 0, &dwType, NULL, &dwSize);
if(lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA)
{
//data already exists, so just return
RegCloseKey(hKey);
return true;
}
else//section data does not exist, so create new data
{
DWORD dwDisposition;
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, sectionData, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition);
RegCloseKey(hKey);
return true;
}
}
return false;
}
But when I trace down to the RegCreateKeyEx() call, it returns success but data is not created under the MyTestApp registry key or anywhere in the registry. Am I using the correct function to create new data under MyTestApp. Also from the argument above, I have CString sectionValue, so how do I check if I need to create data for REG_SZ or REG_DWORD?
Thanks!
It seems I just need to call RegSetValueEx() to create registry value under MyTestApp. Probably just me but when I look at the RegSetValueEx() definition in Microsoft website, it says set the value, but it does not say if value does not exist, it will create the value.
LPTSTR lpszData = new TCHAR[sectionValue.GetLength() + 1];
_tcscpy(lpszData, sectionValue);
lResult = RegSetValueEx(hKey, sectionData, 0, REG_SZ, (LPBYTE)lpszData, sectionValue.GetLength());
So now it creates the registry value, however I cannot still tell if sectionValue is REG_SZ or REG_DWORD.

Delete a registry key recursively

I need to remove a subtree in the Windows registry under Windows Mobile 6. The RegDeleteTree function is not available, and SHDeleteKey is (apparently) not available in any static library under the WM6 SDK, though the declaration is available in shlwapi.h.
I tried to get it from shlwapi.dll, like
typedef DWORD (__stdcall *SHDeleteKey_Proc) (HKEY, LPCWSTR);
SHDeleteKey_Proc procSHDeleteKey;
HINSTANCE shlwapidll = ::LoadLibrary(_T("shlwapi.dll"));
if(shlwapidll) {
procSHDeleteKey =
(SHDeleteKey_Proc)GetProcAddress(shlwapidll,_T("SHDeleteKeyW"));
ASSERT(procSHDeleteKey);
}
But I hit the assert.
Is there a nice way to delete, recursively, a Registry key (empty or not) under Windows Mobile?
I guess I found the answer myself in MSDN. It puzzles me that the functionality is not available through the SDK, though...
I put the code from MSDN here as well, just for the record:
//*************************************************************
//
// RegDelnodeRecurse()
//
// Purpose: Deletes a registry key and all it's subkeys / values.
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful.
// FALSE if an error occurs.
//
//*************************************************************
BOOL RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey)
{
LPTSTR lpEnd;
LONG lResult;
DWORD dwSize;
TCHAR szName[MAX_PATH];
HKEY hKey;
FILETIME ftWrite;
// First, see if we can delete the key without having
// to recurse.
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
if (lResult == ERROR_SUCCESS)
return TRUE;
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
printf("Key not found.\n");
return TRUE;
}
else {
printf("Error opening key.\n");
return FALSE;
}
}
// Check for an ending slash and add one if it is missing.
lpEnd = lpSubKey + lstrlen(lpSubKey);
if (*(lpEnd - 1) != TEXT('\\'))
{
*lpEnd = TEXT('\\');
lpEnd++;
*lpEnd = TEXT('\0');
}
// Enumerate the keys
dwSize = MAX_PATH;
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
NULL, NULL, &ftWrite);
if (lResult == ERROR_SUCCESS)
{
do {
StringCchCopy (lpEnd, MAX_PATH*2, szName);
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
break;
}
dwSize = MAX_PATH;
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
NULL, NULL, &ftWrite);
} while (lResult == ERROR_SUCCESS);
}
lpEnd--;
*lpEnd = TEXT('\0');
RegCloseKey (hKey);
// Try again to delete the key.
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
if (lResult == ERROR_SUCCESS)
return TRUE;
return FALSE;
}
//*************************************************************
//
// RegDelnode()
//
// Purpose: Deletes a registry key and all it's subkeys / values.
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful.
// FALSE if an error occurs.
//
//*************************************************************
BOOL RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey)
{
TCHAR szDelKey[MAX_PATH*2];
StringCchCopy (szDelKey, MAX_PATH*2, lpSubKey);
return RegDelnodeRecurse(hKeyRoot, szDelKey);
}
The second argument of GetProcAddress is a LPCSTR (that is, it is not a LPCTSTR). So remove the _T() and try this:
GetProcAddress(shlwapidll, "SHDeleteKeyW");
Does that help solve the problem?
You're looking for the RegDeleteTree() function. Just replace RegDeleteKey with it.
Apparently, it took them a while to figure it out, so if you want to support XP or older, you need to have your own implementation of it.