CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Aug 2006
    Posts
    515

    Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE?

    By default CWinApp::SetRegistryKey() set the application registry under HKEY_CURRENT_USER so each user (windows login account) has their private settings stored for them. However I would like my applications settings to be common for all windows users so I want to store them under HKEY_LOCAL_MACHINE.

    Can I do this use MFC registry functions? I hope I don't have to discard the MFC registry access functions in favor of independent registry calls to accomplish this!

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    SetRegistryKey was designed to store read/write user specific data, so that's why HKCU was chosen. You can step into the SetRegistryKey call and look at the appui3.cpp file in the mfc sources. You'll see it's hardcoded to use HKCU.

    If you want different behavior, you'll need to roll your own, but keep in mind that on the newer OS's, apps won't have access to HKLM by default, so your app will need to run under higher access privileges.

  3. #3
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by zspirit View Post
    By default CWinApp::SetRegistryKey() set the application registry under HKEY_CURRENT_USER so each user (windows login account) has their private settings stored for them. However I would like my applications settings to be common for all windows users so I want to store them under HKEY_LOCAL_MACHINE.
    HKEY_LOCAL_MACHINE was designed to be used as read-only for normal users. So you could write some initial data to it while installing your application; then all users would be able to read those data.
    To write to HKLM as Arjay pointed out the users have to run under higher access privileges, which nowaday almost impossible (except some cases like software installing.)

    So I'd recommend you to change your design.
    Victor Nijegorodov

  4. #4
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    If you need to store data that is common accross all users but is not installation specifc, then this data can be stored as a file under \documents and settings\All users\Application data\{app name}.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  5. #5
    Join Date
    Aug 2006
    Posts
    515

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by 2kaud View Post
    If you need to store data that is common accross all users but is not installation specifc, then this data can be stored as a file under \documents and settings\All users\Application data\{app name}.
    Are there any specific functions that I can create/access such file perhaps with the registry functions?

  6. #6
    Join Date
    Aug 2006
    Posts
    515

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by Arjay View Post
    SetRegistryKey was designed to store read/write user specific data, so that's why HKCU was chosen. You can step into the SetRegistryKey call and look at the appui3.cpp file in the mfc sources. You'll see it's hardcoded to use HKCU.

    If you want different behavior, you'll need to roll your own, but keep in mind that on the newer OS's, apps won't have access to HKLM by default, so your app will need to run under higher access privileges.
    That's a good idea but string thing is that it nevers allow me to step into SetRegistryKey() function so I can't get to its source otherwise I thought I could use function cloning here.

  7. #7
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by zspirit View Post
    That's a good idea but string thing is that it nevers allow me to step into SetRegistryKey() function so I can't get to its source otherwise I thought I could use function cloning here.
    Who (or what) never allows you to step in? Do you try it in Debug bulid? What VS are you using?

    Besides, as Arjay wrote you could just open appui3.cpp file to see its code. For SetRegistryKey ther is:
    Code:
    void CWinApp::SetRegistryKey(LPCTSTR lpszRegistryKey)
    {
    	ASSERT(m_pszRegistryKey == NULL);
    	ASSERT(lpszRegistryKey != NULL);
    	ASSERT(m_pszAppName != NULL);
    
    	BOOL bEnable = AfxEnableMemoryTracking(FALSE);
    	free((void*)m_pszRegistryKey);
    	m_pszRegistryKey = _tcsdup(lpszRegistryKey);
    	free((void*)m_pszProfileName);
    	m_pszProfileName = _tcsdup(m_pszAppName);
    	AfxEnableMemoryTracking(bEnable);
    }
    Victor Nijegorodov

  8. #8
    Join Date
    Aug 2006
    Posts
    515

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by VictorN View Post
    Who (or what) never allows you to step in? Do you try it in Debug bulid? What VS are you using?

    Besides, as Arjay wrote you could just open appui3.cpp file to see its code. For SetRegistryKey ther is:
    Code:
    void CWinApp::SetRegistryKey(LPCTSTR lpszRegistryKey)
    {
    	ASSERT(m_pszRegistryKey == NULL);
    	ASSERT(lpszRegistryKey != NULL);
    	ASSERT(m_pszAppName != NULL);
    
    	BOOL bEnable = AfxEnableMemoryTracking(FALSE);
    	free((void*)m_pszRegistryKey);
    	m_pszRegistryKey = _tcsdup(lpszRegistryKey);
    	free((void*)m_pszProfileName);
    	m_pszProfileName = _tcsdup(m_pszAppName);
    	AfxEnableMemoryTracking(bEnable);
    }
    I am using VS2010 and I 'step in' at this line with debugger it just do 'step over'. I was surprised too by this behavior. Thanks for the code but I don't really see the harcoded value for HKEY_CURRENT_USER. I see another thing though which I also wanted to fix. The default registry entry is the executable name which I wanted to be fixed so I see I could fix that too by cloning this function. However how I direct this to HKEY_LOCAL_MACHINE or anywhere else that I don't have to run into permission issues?

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by zspirit View Post
    I am using VS2010 and I 'step in' at this line with debugger it just do 'step over'. I was surprised too by this behavior. Thanks for the code but I don't really see the harcoded value for HKEY_CURRENT_USER. I see another thing though which I also wanted to fix. The default registry entry is the executable name which I wanted to be fixed so I see I could fix that too by cloning this function. However how I direct this to HKEY_LOCAL_MACHINE or anywhere else that I don't have to run into permission issues?
    You have to open the appui3.cpp file to see it. Order to do this, you needed to install the mfc sources when you installed VS. If you didn't, try searching the files in the VS install folder for CWinApp::SetRegistryKey.

    As far as directing it to HKLM - you don't (I thought we explained this already???). And if you attempt to access HKLM from your program without the proper permissions, it will fail.

    If you need read-only access to info for all users, then use 2kaud's suggestion from his earlier post.

  10. #10
    Join Date
    Aug 2006
    Posts
    515

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by Arjay View Post
    You have to open the appui3.cpp file to see it. Order to do this, you needed to install the mfc sources when you installed VS. If you didn't, try searching the files in the VS install folder for CWinApp::SetRegistryKey.

    As far as directing it to HKLM - you don't (I thought we explained this already???). And if you attempt to access HKLM from your program without the proper permissions, it will fail.

    If you need read-only access to info for all users, then use 2kaud's suggestion from his earlier post.
    Since you said its hardcoded to use HKCU, I just wanted to redirect it to HKLM and see what happens. I thought it would be interesting to try on XP (which are my users) but Windows 7 will definitely pose a problem with permission. I was just not able to see the hardcoded part but I will go with the other suggestion.

  11. #11
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by zspirit View Post
    Thanks for the code but I don't really see the harcoded value for HKEY_CURRENT_USER.
    Code:
    // returns key for HKEY_CURRENT_USER\"Software"\RegistryKey\ProfileName
    // creating it if it doesn't exist
    // responsibility of the caller to call RegCloseKey() on the returned HKEY
    HKEY CWinApp::GetAppRegistryKey(CAtlTransactionManager* pTM)
    {
    	ASSERT(m_pszRegistryKey != NULL);
    	ASSERT(m_pszProfileName != NULL);
    
    	HKEY hAppKey = NULL;
    	HKEY hSoftKey = NULL;
    	HKEY hCompanyKey = NULL;
    	
    	LSTATUS lStatus = pTM != NULL ? 
    		pTM->RegOpenKeyEx(HKEY_CURRENT_USER, _T("software"), 0, KEY_WRITE|KEY_READ, &hSoftKey) :
    		::RegOpenKeyEx(HKEY_CURRENT_USER, _T("software"), 0, KEY_WRITE|KEY_READ, &hSoftKey);
    
    	if (lStatus == ERROR_SUCCESS)
    	{
    		DWORD dw;
    
    		lStatus = pTM != NULL ? 
    			pTM->RegCreateKeyEx(hSoftKey, m_pszRegistryKey, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hCompanyKey, &dw) :
    			::RegCreateKeyEx(hSoftKey, m_pszRegistryKey, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hCompanyKey, &dw);
    
    		if (lStatus == ERROR_SUCCESS)
    		{
    			lStatus = pTM != NULL ? 
    				pTM->RegCreateKeyEx(hCompanyKey, m_pszProfileName, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hAppKey, &dw) :
    				::RegCreateKeyEx(hCompanyKey, m_pszProfileName, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hAppKey, &dw);
    		}
    	}
    	if (hSoftKey != NULL)
    		RegCloseKey(hSoftKey);
    	if (hCompanyKey != NULL)
    		RegCloseKey(hCompanyKey);
    
    	return hAppKey;
    }
    
    // returns key for:
    //      HKEY_CURRENT_USER\"Software"\RegistryKey\AppName\lpszSection
    // creating it if it doesn't exist.
    // responsibility of the caller to call RegCloseKey() on the returned HKEY
    HKEY CWinApp::GetSectionKey(LPCTSTR lpszSection, CAtlTransactionManager* pTM)
    {
    	ASSERT(lpszSection != NULL);
    
    	HKEY hSectionKey = NULL;
    	HKEY hAppKey = GetAppRegistryKey(pTM);
    	if (hAppKey == NULL)
    		return NULL;
    
    	DWORD dw;
    
    	if (pTM != NULL)
    	{
    		pTM->RegCreateKeyEx(hAppKey, lpszSection, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hSectionKey, &dw);
    	}
    	else
    	{
    		::RegCreateKeyEx(hAppKey, lpszSection, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hSectionKey, &dw);
    	}
    
    	RegCloseKey(hAppKey);
    	return hSectionKey;
    }
    . . . I see I could fix that too by cloning this function. However how I direct this to HKEY_LOCAL_MACHINE or anywhere else that I don't have to run into permission issues?
    Cloning Windows OS?

    Okay, getting serious. You were told several times: once you get to writing to local machine hive you inevitably run into permission issue. Once you get to writing under system Program Files folder, you're in trouble again. That was done by Windows architects on purpose, and you have no other way but live with that. If your design contradicts to very basic Windows security guidelines, you're on your own and free to go wherever you want until (or unless) Windows stops you.

    I don't know why would anybody need a multi-user app settings be kept in the same storage (.ini or registry or xml, whatever), but if you want to do that, just do that, but don't expect too much help from OS or MFC framework for unwelcomed things.
    Best regards,
    Igor

  12. #12
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Can CWinApp::SetRegistryKey() setup application registry under HKEY_LOCAL_MACHINE

    Quote Originally Posted by zspirit View Post
    Since you said its hardcoded to use HKCU, I just wanted to redirect it to HKLM and see what happens.
    If you change the file to point to HKLM and recompiled the MFC source files, the data would be redirected to HKLM. But then you would have to distribute the recompiled MFC dll with your app and that would violate MS's MFC redistributable agreement, not to mention break other apps that happened to use the modified DLL. On newer OS's you are also going to run into issues with the private copy and it may be flagged as spyware (because it's been modified). In short - you open up a big can of worms here just because you are attempting to do something that is non-standard and has been locked down by MS.

    Quote Originally Posted by zspirit View Post
    I thought it would be interesting to try on XP (which are my users) but Windows 7 will definitely pose a problem with permission. I was just not able to see the hardcoded part but I will go with the other suggestion.
    If it were me, I would just would store an xml file in the shared location that was mentioned and use IXMLDocument interface to manipulate the xml. I would write a wrapper class to make it simple to access it from my class.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured