none
Registry access, worked on XP & Vista but not Windows 7

    Question

  • I have an application that stores the application database location in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\EasySoft. The VB6 application uses the registry API (RegOpenKey and RegQueryValue) to locate the database and works correctly on both XP and Vista. When run on Windows 7, the call to RegOpenKey fails returning an error code of 5 (access denied). The application install creates the registry entry with read access for all users. I have verified this happened on the windows 7 install using RegEdit. The entry is being created and the permission is being set to READ (same as in Vista and XP). To see if I could better understand the problem, I tried many unacceptable solutions including manually setting full control for all users, running the application as administrator and even turning off UAC. In every case, RegOpenKey returned error code 5 (getting access denied with user access control turned off seems impossible but this also failed). Any help, even suggestions about other things to check/test, would be greatly appreciated.

        Ken
    Monday, December 14, 2009 11:02 PM

Answers

  • Well, I finally figured out the problem. In the code example I downloaded (as with many others like http://www.codetoad.com/vb_modify_registry.asp) there was the constant ERROR_ACCESS_DENIED = 5 defined. While looking at potential issues with ADVAPI32.DLL, where the function I am call resides, I found another example with the constant ERROR_ACCESS_DENIED = 8 and another constant ERROR_CANTWRITE = 5 defined. When I changed my application to ignore ERROR_CANTWRITE, it now works correctly.

    I can understand adding a new return code since Windows 7 changed the access levels of this registry tree, but why change the meaning of an existing return value instead of adding a new one? And why not tell the development community what you did? One very simple note anywhere on the web and this would have been a 5 minute fix. Instead I spent many hours and wasted 2 weeks. Thanks for the great New Years present.

    And one final note, how come no one monitoring this Forum couldn't provide any useful help? My initial explanation of the problem gave the critical clue (...returning and error code of 5 - access denied...). Did any of you even bother to check the error code?

        Ken
    • Proposed as answer by Fisnik Hasani Sunday, January 03, 2010 6:53 PM
    • Marked as answer by Rong-Chun Zhang Monday, January 04, 2010 10:17 AM
    Friday, January 01, 2010 5:44 PM

All replies

  • Hello Ken,

    Did you try the application on a x64 Windows 7 machine? If your application is 32bit, then the registry entry will be redirected. 

    More information

    You can also use the Process monitor to get where your application is trying to access.

    Thanks,
    Rong-Chun Zhang

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by kagsw Tuesday, December 15, 2009 3:17 PM
    • Unmarked as answer by kagsw Tuesday, December 15, 2009 3:17 PM
    Tuesday, December 15, 2009 3:55 AM
  • My test system is an x64 system set up with dual boot of Windows 7 32 bit and Windows 7 64 bit. The behavior on both operating systems is the same. On the 64 bit operating system, the registry entry is redirected under Wow6432Node but the API call correctly finds it (the access denied error means it finds the entry). I will download the process monitor you reference and see if I can find anything further. Thanks for the response.

        Ken
    Tuesday, December 15, 2009 3:24 PM
  • The process monitor is great. I was able to isolate the application call and see it displayed by the monitor which shows the result as ACCESS DENIED.
    I then open RegEdit and checked the permissions for HKEY_LOCAL_MACHINE (Everyone - read), HKLM\SOFTWARE (Users - read), HKLM\SOFTWARE\SOFTWARE\EasySoft (Users - read) and the actual key being opened in the call HKLM\SOFTWARE\EasySoft\MSL51 (Users - read).

    Any other ideas?

        Ken

    PS - I used the 32-bit system for this most recent test.
    Tuesday, December 15, 2009 4:09 PM
  • Hi,

    RegOpenKey() Function:
    Note  This function is provided only for compatibility with 16-bit versions of Windows.

    You shall use RegOpenKeyEx() instead, many functions in Windows have been re-named now days.

    RegOpenKeyEx Function.
    http://msdn.microsoft.com/en-us/library/ms724897(VS.85).aspx

    Have a nice day...

    Best regards,
    Fisnik


    Coder24.com
    Tuesday, December 15, 2009 4:20 PM
  • Sorry, my bad. The API function being called is RegOpenKeyExA() which I believe is the ASCII (as opposed to Unicode) implementation of the call.

        Ken
    Tuesday, December 15, 2009 4:45 PM
  • RegOpenKeyExA() I think you shall remove the "A" - character?

    Because, RegOpenKeyEx() is the original name of that function.

    Does this work now?

    Have a nice day...

    Best regards,
    Fisnik
    Coder24.com
    Tuesday, December 15, 2009 4:48 PM
  • No, removing the A generates a run time error 453, "Can't Find DLL entry point RegOpenKeyEx in advapi32.dll".
    The function call as currently coded works correctly on XP and Vista. The only problem is on Windows 7.

        Ken
    Tuesday, December 15, 2009 5:30 PM
  • In What language do you do this?

    C#?

    Thanks...

    Have a nice day...

    Best regards,
    Fisnik
    Coder24.com
    Tuesday, December 15, 2009 5:33 PM
  • If you do this in C#, then you can actually specify the EntryPoint.

    [DllImport("advapi32.dll",EntryPoint=" RegOpenKeyEx")]
    public static extern int RegOpenKeyEx(
        UIntPtr hKey,
        string subKey,
        int ulOptions,
        int samDesired,
        out UIntPtr hkResult);


    You can specify the EntryPoint=.

    Got that code from P/Invoke:
    http://www.pinvoke.net/default.aspx/advapi32/RegOpenKeyEx.html

    Have a nice day...

    Best regards,
    Fisnik


    Coder24.com
    • Edited by Fisnik Hasani Tuesday, December 15, 2009 5:41 PM But modified and added EntryPoint
    Tuesday, December 15, 2009 5:40 PM
  • The application is written in VB6. The problem is not with the function call or the problem would exist on XP and Vista as well. The function call is correct unless Windows 7 has made a change that required the function call be changed. I have found nothing stating this function call that worked on XP and Vista should now not work on Windows 7.

    The problem is on Windows 7, the function returns error code 5 (ACCESS DENIED). The same function call on XP and Vista returns 0 (SUCCESS).

        Ken
    Tuesday, December 15, 2009 5:56 PM
  • hmm, why are you working with VB6, when we have Visual Basic 9.0 etc?
    Coder24.com
    Tuesday, December 15, 2009 6:06 PM
  • Not my choice but my responsibility. Any ideas about why Windows 7 behavior is different than the behavior on XP & Vista?
    Tuesday, December 15, 2009 8:39 PM
  • Hello Ken,

    Could you please some of your code with us? So that we can try to reproduce the issue locally.

    Thanks,
    Rong-Chun Zhang
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, December 16, 2009 8:28 AM
  • Yeah share some code!

    Have a nice day...

    Best regards,
    Fisnik
    Coder24.com
    Wednesday, December 16, 2009 10:48 AM
  • See code below.

    This code was not written by me. I'm just trying to help a friend get his application working on Windows 7.
    The original developer is not available (long story) but based on the variable naming of this function (not at all like the rest of the application code), I expect this was cut and pasted from an example found on the net. This code works correctly on XP and Vista. The calls to msgbox were added by me to help diagnose the problem.

    Any help would be greatly appreciated.

        Ken

    The application makes the following call:

      Path = RegGetValue(HKEY_LOCAL_MACHINE&, "Software\EasySoft\MSL51", "ShareFolder")



    The sources for the function call:

    Declare Function RegCloseKey& Lib "advapi32.dll" (ByVal hKey&)
    Declare Function RegOpenKeyExA& Lib "advapi32.dll" (ByVal hKey&, ByVal lpszSubKey$, dwOptions&, ByVal samDesired&, lpHKey&)
    Declare Function RegQueryValueExA& Lib "advapi32.dll" (ByVal hKey&, ByVal lpszValueName$, ByVal lpdwRes&, lpdwType&, ByVal lpDataBuff$, nSize&)
    Declare Function RegQueryValueEx& Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey&, ByVal lpszValueName$, ByVal lpdwRes&, lpdwType&, lpDataBuff&, nSize&)

    Global Const HH_DISPLAY_TOPIC As Long = 0
    Global Const HH_HELP_CONTEXT As Long = &HF
    Global Const HH_DISPLAY_TOC = &H1
    Global Const HKEY_CLASSES_ROOT = &H80000000
    Global Const HKEY_CURRENT_USER = &H80000001
    Global Const HKEY_LOCAL_MACHINE = &H80000002
    Global Const HKEY_USERS = &H80000003

    Const ERROR_SUCCESS = 0&
    Const REG_SZ = 1&                          ' Unicode nul terminated string
    Const REG_DWORD = 4&                       ' 32-bit number

    Const KEY_QUERY_VALUE = &H1&
    Const KEY_SET_VALUE = &H2&
    Const KEY_CREATE_SUB_KEY = &H4&
    Const KEY_ENUMERATE_SUB_KEYS = &H8&
    Const KEY_NOTIFY = &H10&
    Const KEY_CREATE_LINK = &H20&
    Const READ_CONTROL = &H20000
    Const WRITE_DAC = &H40000
    Const WRITE_OWNER = &H80000
    Const SYNCHRONIZE = &H100000
    Const STANDARD_RIGHTS_REQUIRED = &HF0000
    Const STANDARD_RIGHTS_READ = READ_CONTROL
    Const STANDARD_RIGHTS_WRITE = READ_CONTROL
    Const STANDARD_RIGHTS_EXECUTE = READ_CONTROL
    Const KEY_READ = STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY
    Const KEY_WRITE = STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY
    Const KEY_EXECUTE = KEY_READ

    Function RegGetValue$(MainKey&, SubKey$, TheValue$)
       ' MainKey must be one of the Publicly declared HKEY constants.
       Dim sKeyType&       'to return the key type.  This function expects REG_SZ or REG_DWORD
       Dim ret&            'returned by registry functions, should be 0&
       Dim lpHKey&         'return handle to opened key
       Dim lpcbData&       'length of data in returned string
       Dim ReturnedString$ 'returned string TheValue
       Dim ReturnedLong&   'returned long TheValue
      
       Call MsgBox(Str(MainKey) + " " + SubKey + "  " + TheValue, vbInformation)
       If MainKey >= &H80000000 And MainKey <= &H80000006 Then
          ' Open key
          ret = RegOpenKeyExA(MainKey, SubKey, 0&, KEY_READ, lpHKey)
          If ret <> ERROR_SUCCESS Then
             Call MsgBox("Open Return = " + Str(ret), vbInformation)
             RegGetValue = ""
             Exit Function     'No key open, so leave
          End If
         
          ' Set up buffer for data to be returned in.
          ' Adjust next value for larger buffers.
          lpcbData = 255
          ReturnedString = Space$(lpcbData)

          ' Read key
          ret& = RegQueryValueExA(lpHKey, TheValue, ByVal 0&, sKeyType, ReturnedString, lpcbData)
          If ret <> ERROR_SUCCESS Then
             'Call MsgBox("Query Return = " + Str(ret), vbInformation)
             RegGetValue = ""   'Value probably doesn't exist
          Else
            If sKeyType = REG_DWORD Then
                ret = RegQueryValueEx(lpHKey, TheValue, ByVal 0&, sKeyType, ReturnedLong, 4)
                If ret = ERROR_SUCCESS Then RegGetValue = CStr(ReturnedLong)
            Else
                RegGetValue = Left$(ReturnedString, lpcbData - 1)
            End If
        End If
          ' Always close opened keys.
          ret = RegCloseKey(lpHKey)
       End If
    End Function

    Wednesday, December 16, 2009 2:41 PM
  • Hello Ken:

    Is this the entire code?
    I see one problem, where is the

    Left$ function() ???

    Please post that part as well.

    Thanks for sharing your code.

    Have a nice day...

    Best regards,
    Fisnik


    Coder24.com
    Wednesday, December 16, 2009 6:51 PM
  • No, this is not the full application. This is the call made by the startup form during form load and the sources to the called function. This is sufficient to reproduce the error.

    Left$ is a VB6 primitive function (see definition from the documentation below).

        Ken

    Left Function @import url(MS-ITS:dsmsdn.chm::/html/msdn_ie4.css);

    Left Function

           

    Returns a Variant (String ) containing a specified number of characters from the left side of a string.

    Syntax

    Left (string , length )

    The Left function syntax has these named arguments :

    Part Description
    string Required. String expression from which the leftmost characters are returned. If string contains Null , Null is returned.
    length Required; Variant (Long ). Numeric expression indicating how many characters to return. If 0, a zero-length string ("") is returned. If greater than or equal to the number of characters in string , the entire string is returned.

    Remarks

    To determine the number of characters in string , use the Len function.

    Note    Use the LeftB function with byte data contained in a string. Instead of specifying the number of characters to return, length specifies the number of bytes.

    Wednesday, December 16, 2009 7:41 PM
  • Hello again:

    I have some small issues with this code,
    do you think you can share the VB file code
    instead, so we can download it and open it 
    directly with your live original code in your 
    file. 

    Using Windows Live SkyDrive

    That would be much easier...

    Have a nice day...

    Best regards,
    Fisnik  
    Coder24.com
    Wednesday, December 16, 2009 7:51 PM
  • For the last time, the problem isn't with the code. It works correctly on XP and Vista.
    The problem is the behavior is different on Windows 7. I need to understand why the behavior is different on Windows 7.

        Ken
    Wednesday, December 16, 2009 10:10 PM
  • For the last time, the problem isn't with the code. It works correctly on XP and Vista.
    The problem is the behavior is different on Windows 7. I need to understand why the behavior is different on Windows 7.

        Ken

    Yes, but I have Windows 7 on my PC with VS2008, and I am asking you to send me the
    original full source file, so I can compile it and test it under my Windows 7.

    If it works well here, then the mistake/problem is somewhere else...

    Have a nice day...

    Best regards,
    Fisnik
    Coder24.com
    Thursday, December 17, 2009 2:58 PM
  • The full application is quite large. To test I built a 1 form application to enter a registry key and entry and view the RegOpenKey results. The project has 3 files, test.vbp, form1.frm and esreg.bas which I've inserted into the code block below. Let me know if you need anything else.

    Also, thank you for your help. I apologize if I've seemed unreasonable but I'm under a lot of pressure to get this resolved and I've made very little progress.

        Ken

    ***text.vbp***
    
    Type=Exe
    Form=Form1.frm
    Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\Program Files\Pack 4.3\STDOLE2.TLB#OLE Automation
    Module=EsWin; EsReg.bas
    Startup="Form1"
    ExeName32="test.exe"
    Command32=""
    Name="Project1"
    HelpContextID="0"
    CompatibleMode="0"
    MajorVer=1
    MinorVer=0
    RevisionVer=0
    AutoIncrementVer=0
    ServerSupportFiles=0
    VersionCompanyName=" KAG Software, Inc."
    CompilationType=0
    OptimizationType=0
    FavorPentiumPro(tm)=0
    CodeViewDebugInfo=0
    NoAliasing=0
    BoundsCheck=0
    OverflowCheck=0
    FlPointCheck=0
    FDIVCheck=0
    UnroundedFP=0
    StartMode=0
    Unattended=0
    Retained=0
    ThreadPerObject=0
    MaxNumberOfThreads=1
    
    [MS Transaction Server]
    AutoRefresh=1
    
    
    ***form1.frm***
    
    VERSION 5.00
    Begin VB.Form Form1 
       Caption         =   "Form1"
       ClientHeight    =   3285
       ClientLeft      =   60
       ClientTop       =   450
       ClientWidth     =   4680
       LinkTopic       =   "Form1"
       ScaleHeight     =   3285
       ScaleWidth      =   4680
       StartUpPosition =   3  'Windows Default
       Begin VB.Frame FrameEntry 
          Caption         =   "Registry Entry"
          Height          =   735
          Left            =   120
          TabIndex        =   8
          Top             =   840
          Width           =   4455
          Begin VB.TextBox TextEntry 
             Height          =   375
             Left            =   120
             TabIndex        =   9
             Top             =   240
             Width           =   4215
          End
       End
       Begin VB.CommandButton CmdCall 
          Caption         =   "Call RegOpenKey"
          Height          =   375
          Left            =   840
          TabIndex        =   7
          Top             =   1800
          Width           =   2655
       End
       Begin VB.Frame FrameReturn 
          Caption         =   "RegOpenKey Results"
          Height          =   855
          Left            =   120
          TabIndex        =   2
          Top             =   2400
          Width           =   4455
          Begin VB.TextBox TextRet 
             Height          =   375
             Left            =   2160
             TabIndex        =   4
             Top             =   240
             Width           =   2175
          End
          Begin VB.TextBox TextErrCode 
             Height          =   375
             Left            =   720
             TabIndex        =   3
             Top             =   240
             Width           =   615
          End
          Begin VB.Label LabelRet 
             Caption         =   "Return Value"
             Height          =   375
             Left            =   1560
             TabIndex        =   6
             Top             =   240
             Width           =   495
          End
          Begin VB.Label LabelErrCode 
             Caption         =   "Error Code"
             Height          =   375
             Left            =   120
             TabIndex        =   5
             Top             =   240
             Width           =   495
          End
       End
       Begin VB.Frame RefKey 
          Caption         =   "Registry Key"
          Height          =   735
          Left            =   120
          TabIndex        =   0
          Top             =   120
          Width           =   4455
          Begin VB.TextBox TextRegKey 
             Height          =   375
             Left            =   120
             TabIndex        =   1
             Top             =   240
             Width           =   4215
          End
       End
    End
    Attribute VB_Name = "Form1"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = True
    Attribute VB_Exposed = False
    Private Sub CmdCall_Click()
      Dim TheRet As String
      
      If TextRegKey.Text = "" Or TextEntry.Text = "" Then
        Call MsgBox("Enter the registry key and entry you want to read", vbInformation)
        Exit Sub
      End If
      TheRet = RegGetValue(HKEY_LOCAL_MACHINE&, TextRegKey.Text, TextEntry.Text)
      
    End Sub
    
    ***esreg.bas***
    
    Attribute VB_Name = "EsWin"
    Declare Function RegCloseKey& Lib "advapi32.dll" (ByVal hKey&)
    Declare Function RegOpenKeyExA& Lib "advapi32.dll" (ByVal hKey&, ByVal lpszSubKey$, dwOptions&, ByVal samDesired&, lpHKey&)
    Declare Function RegQueryValueExA& Lib "advapi32.dll" (ByVal hKey&, ByVal lpszValueName$, ByVal lpdwRes&, lpdwType&, ByVal lpDataBuff$, nSize&)
    Declare Function RegQueryValueEx& Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey&, ByVal lpszValueName$, ByVal lpdwRes&, lpdwType&, lpDataBuff&, nSize&)
    
    Global Const HH_DISPLAY_TOPIC As Long = 0
    Global Const HH_HELP_CONTEXT As Long = &HF
    Global Const HH_DISPLAY_TOC = &H1
    Global Const HKEY_CLASSES_ROOT = &H80000000
    Global Const HKEY_CURRENT_USER = &H80000001
    Global Const HKEY_LOCAL_MACHINE = &H80000002
    Global Const HKEY_USERS = &H80000003
    
    Const ERROR_SUCCESS = 0&
    Const REG_SZ = 1&                          ' Unicode nul terminated string
    Const REG_DWORD = 4&                       ' 32-bit number
    
    Const KEY_QUERY_VALUE = &H1&
    Const KEY_SET_VALUE = &H2&
    Const KEY_CREATE_SUB_KEY = &H4&
    Const KEY_ENUMERATE_SUB_KEYS = &H8&
    Const KEY_NOTIFY = &H10&
    Const KEY_CREATE_LINK = &H20&
    Const READ_CONTROL = &H20000
    Const WRITE_DAC = &H40000
    Const WRITE_OWNER = &H80000
    Const SYNCHRONIZE = &H100000
    Const STANDARD_RIGHTS_REQUIRED = &HF0000
    Const STANDARD_RIGHTS_READ = READ_CONTROL
    Const STANDARD_RIGHTS_WRITE = READ_CONTROL
    Const STANDARD_RIGHTS_EXECUTE = READ_CONTROL
    Const KEY_READ = STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY
    Const KEY_WRITE = STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY
    Const KEY_EXECUTE = KEY_READ
    
    
    Function RegGetValue$(MainKey&, SubKey$, TheValue$)
       ' MainKey must be one of the Publicly declared HKEY constants.
       Dim sKeyType&       'to return the key type.  This function expects REG_SZ or REG_DWORD
       Dim ret&            'returned by registry functions, should be 0&
       Dim lpHKey&         'return handle to opened key
       Dim lpcbData&       'length of data in returned string
       Dim ReturnedString$ 'returned string TheValue
       Dim ReturnedLong&   'returned long TheValue
       
       If MainKey >= &H80000000 And MainKey <= &H80000006 Then
          ' Open key
          ret = RegOpenKeyExA(MainKey, SubKey, 0&, KEY_READ, lpHKey)
          Form1!TextErrCode.Text = Str(ret)
          Form1!TextRet.Text = ""
          If ret <> ERROR_SUCCESS Then
             RegGetValue = ""
             Exit Function     'No key open, so leave
          End If
          
          ' Set up buffer for data to be returned in.
          ' Adjust next value for larger buffers.
          lpcbData = 255
          ReturnedString = Space$(lpcbData)
    
          ' Read key
          ret& = RegQueryValueExA(lpHKey, TheValue, ByVal 0&, sKeyType, ReturnedString, lpcbData)
          If ret <> ERROR_SUCCESS Then
             'Call MsgBox("Query Return = " + Str(ret), vbInformation)
             RegGetValue = ""   'Value probably doesn't exist
          Else
            If sKeyType = REG_DWORD Then
                ret = RegQueryValueEx(lpHKey, TheValue, ByVal 0&, sKeyType, ReturnedLong, 4)
                If ret = ERROR_SUCCESS Then RegGetValue = CStr(ReturnedLong)
            Else
                RegGetValue = Left$(ReturnedString, lpcbData - 1)
                Form1!TextRet.Text = Left$(ReturnedString, lpcbData - 1)
            End If
        End If
          ' Always close opened keys.
          ret = RegCloseKey(lpHKey)
       End If
    End Function
    
    
    
    Thursday, December 17, 2009 5:26 PM
  • Hello Ken:

    I am pretty sorry to say this, but please provide me with the full *.vb file instead becuase there
    I'll have everything and they I'll understand more of your code and I will be able to help you.

    Nothing bad...

    Have a nice day...

    Best regards,
    Fisnik
    Coder24.com
    Saturday, December 19, 2009 2:23 PM
  • Thanks, butI'm not sure what else I can post. The last post was a full application that demonstrates the problem. I posted the project file, the form file and the function module. Together these can be used to build a complete application. I built this small application. When I run this application on an XP system, the call to RegOpenKey returns 0 (success). When I run this application on a Vista system, the call to RegOpenKey returns 0 (success). When I run this application on my new Windows 7 system, the call to RegOpenKey returns 5 (access denied).

    Is there something else I can post?

        Ken
    Saturday, December 19, 2009 10:31 PM
  • Well, I finally figured out the problem. In the code example I downloaded (as with many others like http://www.codetoad.com/vb_modify_registry.asp) there was the constant ERROR_ACCESS_DENIED = 5 defined. While looking at potential issues with ADVAPI32.DLL, where the function I am call resides, I found another example with the constant ERROR_ACCESS_DENIED = 8 and another constant ERROR_CANTWRITE = 5 defined. When I changed my application to ignore ERROR_CANTWRITE, it now works correctly.

    I can understand adding a new return code since Windows 7 changed the access levels of this registry tree, but why change the meaning of an existing return value instead of adding a new one? And why not tell the development community what you did? One very simple note anywhere on the web and this would have been a 5 minute fix. Instead I spent many hours and wasted 2 weeks. Thanks for the great New Years present.

    And one final note, how come no one monitoring this Forum couldn't provide any useful help? My initial explanation of the problem gave the critical clue (...returning and error code of 5 - access denied...). Did any of you even bother to check the error code?

        Ken
    • Proposed as answer by Fisnik Hasani Sunday, January 03, 2010 6:53 PM
    • Marked as answer by Rong-Chun Zhang Monday, January 04, 2010 10:17 AM
    Friday, January 01, 2010 5:44 PM
  • Hi Ken:

    Thank you, very much for informing us.
    I am glad that you'll problem finally is solved.

    Happy New Year to you...

    Sorry we have been very busy these weeks!

    Have a nice day....

    BTW, Thanks for sharing...

    Best regards,
    Fisnik
    Coder24.com
    Sunday, January 03, 2010 6:52 PM
  • Hi!
    I familiar to this problem, just replace RegOpenKeyEx function with RegCreateKeyEx (declaring 2 additional params). It opens existing key or creates new.
    It works fine!
    Wednesday, January 13, 2010 11:54 AM
  • Ken

    I too am having the same problem with this code, but I do not have the constant ERROR_ACCESS_DENIED = 5 defined.
    How did you modify the code to ignore ERROR_CANTWRITE ?

    Regards
    Chris

    Wednesday, January 13, 2010 12:05 PM
  • I have a similar difficulty. A VB6 program which works just fine in XP Pro and Vista, but fails in Vista 64-bit and Win7 64-bit. On Win7 64-bit, it works perfectly when run from the IDE, but not when I compile the program and run the .EXE. I have a Sub in a module, and I call the sub from two different locations in the same program, and one fails and the other works fine, compiled or from the IDE.

    The code is basically:

    ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\Testco\Installer", 0&, KEY_READ, lphKey)

    I have two form buttons, one called "Full Download", another called "Update" - one downloads an entire package, the other checks for updated portions of the package. The latter information is not relevant.

    The code for the start of the button handling functions is the same. It calls the same function in the module. However one works in IDE and compiled, and the other works only from the IDE.

    When it fails, I get a return code of 5 which is ERROR_ACCESS_DENIED or ERROR_CANT_WITE depending on where you look. I have changed the software to use HKEY_CURRENT_USER, but this does not help.

    I realise that VB6 is very old, but this is software we've written for another company under license, and they probably won't wear the cost of the time taken to rewrite this in a newer version of VB. Also then we have two apps to distribute, depending on which system the customer has, which complicates matters for the customer. And as the function works from one call but not from another, it doesn't make sense to me.

    Friday, March 19, 2010 3:17 PM
  • Declare Function RegOpenKeyExA& Lib "advapi32.dll" (ByVal hKey&, ByVal lpszSubKey$, dwOptions&, ByVal samDesired&, lpHKey&)

    I know this thread is getting old, but I ran into it today and I expect others will in the future.

    I'm sorry to say that I am probably the original source for that incorrect declare above, since the entire library matches mine word-for-word and has been up on my site for more than 10 years.

    The error never caused any problems until Windows 7, and has caused a lot of grief with my own programs. To fix it, add one ByVal:

    Declare Function RegOpenKeyExA& Lib "advapi32.dll" (ByVal hKey&, ByVal lpszSubKey$, ByVal dwOptions&, ByVal samDesired&, lpHKey&)

    • Proposed as answer by TrentNguyen Friday, October 22, 2010 9:11 PM
    Sunday, June 13, 2010 10:52 PM
  • Here's my code in C++, VS2008:  Works in XP fails in Windows 7

     DWORD dw;
     HKEY hSectionKey = NULL;
     RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\Windows\CurrentVersion\\Run", 0, KEY_WRITE|KEY_READ, &SectionKey);
     RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0,
                                   REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hSectionKey, &dw);
     RegCloseKey(HKEY_LOCAL_MACHINE);

    Both RegOpenKeyEx and RegCreateKeyEx fail with error code 5 (ERROR_ACCESS_DENIED).  If I change HKEY_LOCAL_MACHINE to HKEY_CURRENT_USER it works fine.

    [I'm not making both RegOpenKeyEx and RegCreateKeyEx calls, I just put both of them in to let you know it fails]

    What's the solution in C++?

     I am logged in a administrator.

    Tuesday, June 29, 2010 6:54 PM
  • My "solution", if it can be called that, is to have the user set the compatibility to Windows XP once they've installed the program. That seemed to do the trick. Note that I don't mean the optional add-on Windows XP mode, I mean right-click the shortcut, select 'compatibility', tick "Run this program in compatiblity mode for" and I think I went with Windows XP (service pack 3) from the drop-down.

    Not a great solution, but a quick one.

    Wednesday, June 30, 2010 9:14 AM
  • I had a similar problem with RegOpenKey(). My app which was created with VB6 under Win XP 32bit was throwing an ERROR_BADKEY (which is 2) when used under Win 7 64bit. The problem is with the differing registry "views" in 32bit and 64bit Win. See link..

    http://msdn.microsoft.com/en-us/library/aa384129%28VS.85%29.aspx

    It was easy to fix the issue. All I did was use RegOpenKeyEx() which has a parameter for a mask that specifies the desired access rights. Using the KEY_WOW64_64KEY flag solved the problem. BUT by using RegOpenKeyEx() and KEY_WOW64_64KEY a new error appeared.

    The new error was ERROR_CANTWRITE (which is 5). This was happening because I did not use a security descriptor in the RegOpenKeyEx() access rights parameter.

    Here is the proper fix for this issue. It works 100% using Win 7 64bit BUT I have not tested it on Win XP 32bit yet and am not sure if it is backwards compatible. Enjoy.

    Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long

    Private Const KEY_WOW64_64KEY = &H100 ''registry view flag

    Private Const KEY_ALL_ACCESS = &H3F ''security descriptor

    Private RSLT as long

    RSLT = RegOpenKeyEx(hKey, strPath, 0, KEY_ALL_ACCESS Or KEY_WOW64_64KEY, hCurKey)

    Bottom line is that Win 7 64bit handles the registry different than previous versions of Win. It stores values in different places and in different ways than in the past. It also has added security for the registry which isn't a bad thing, it's just not what we have all been used to.

    • Proposed as answer by kckstnd Thursday, August 12, 2010 9:11 PM
    Thursday, August 12, 2010 6:58 PM
  • I had a similar problem with RegOpenKey(). My app which was created with VB6 under Win XP 32bit was throwing an ERROR_BADKEY (which is 2) when used under Win 7 64bit. The problem is with the differing registry "views" in 32bit and 64bit Win. See link..

    http://msdn.microsoft.com/en-us/library/aa384129%28VS.85%29.aspx

    It was easy to fix the issue. 

    That was very interesting and helpful.

    Could you please give an example how to actualy read a string in VB6? RegQueryValueEx doesn't have the parameter "REGSAM samDesired", so I'm stuck e.g. getting the value of the string "MachineGuid" in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography under VB6.

    T.

    Monday, August 30, 2010 3:53 PM
  • The solution, one solution, is to modify the project manifes file, via:

    Project Properties/Linker/Manifest file: change UAC execution level to: requireAdministrator

    You may also want to change: Enable User Account Control (UAC) to: No.

    Monday, August 30, 2010 4:31 PM
  • I still find it amazing to see all of the odd ways that people go at this. The original poster's complete code sample works perfectly if, as I said before, you simply add the missing ByVal to the RegOpenKeyExA declare. I wrote that code, and I made the error - it just didn't matter with XP and Vista but now it does.
    Monday, September 13, 2010 3:36 AM
  • So what's the solution if you're using C++ instead of Basic and RegCreateKeyEx instead of RegOpenKeyEx?

    Tuesday, September 14, 2010 5:03 AM
  • Yes, it is amazing.  I had the exact same error code 5 "access denied" problem on Win7.  I went through half a day scouring for answer.  Nothing I read suggested this solution.  By chance I saw another declaration of RegOpenKeyExA that had the ByVal by the ulOptions (or dwOptions& in your declaration) and that works.

    Just to reiterate:

    Declare Function RegOpenKeyExA Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long

    Friday, October 22, 2010 9:24 PM
  • Thanks, Trent. Glad to see that someone gets it!

     

    Tuesday, October 26, 2010 2:09 AM
  • Yes, it is amazing.  I had the exact same error code 5 "access denied" problem on Win7.  I went through half a day scouring for answer.  Nothing I read suggested this solution.  By chance I saw another declaration of RegOpenKeyExA that had the ByVal by the ulOptions (or dwOptions& in your declaration) and that works.
    Just to reiterate:
    Declare Function RegOpenKeyExA Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long

    This is great for VB, could someone kindly post the proper solution for VC++ RegOpenKeyExW() ?
    I'm having the same problem, the only thing that works so far is to run Visual Studio as Administrator -- and I've tried just about everything in this long thread!  I'm getting error code 5, which does actually appear to mean ACCESS permission denied (not CANT WRITE as some have suggested) running VS2010, C/C++ this is my simplified code, Windows 7 64bit:
    #define KEY_ALL_ACCESS 0x3F	// Solve problem of access denied on Win 7 64bit? Nope
    	long dwErrorCode = ::RegOpenKeyEx(root, name.c_str(), 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hKey);
    	// Attempt to open the key and get the handle.
    	if (dwErrorCode != ERROR_SUCCESS) 
    	{			throw exception("Unable to open specified registry key");	 	}
    



    Wednesday, May 25, 2011 8:11 PM
  • In C++ you need to change the Manifest in the properties:

    1. Right click on the head of the project, below the solution
    2. You will get a popup menu, select: Properties
    3. Under: Configuration Properties/Linker/Manifest file, select:
    4. UAC Execution Level: change from asInvoker to requireAdministrator
    5. Rebuild
    6. This change will allow you to write to HKLM.

    You should be using parameters like:

    RegCreateKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, 
    REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, 
    NULL, &hSectionKey, &dw);
    
    
    • Proposed as answer by AlanMoo Saturday, July 09, 2011 6:32 PM
    Wednesday, May 25, 2011 10:40 PM
  • This does work, I can't say I'm totally happy with this solution but its the best one I've found so far. Thanks for that!
    Saturday, July 09, 2011 6:32 PM
  • Hi,

    I have same problem in my application. If will do same as by Anonymous-mouse at process(.exe application) project property level but in my application, I am using dll file in which we have code  "RegOpenKeyEx(HKEY_LOCAL_MACHINE, sKey, 0,  KEY_ALL_ACCESS, &hkKey);" like this and I have changed project settings also in .dll as suggested above but I am not able access registry.

    Can any one have solution for this !

    Thanks, 


    Thanks.


    • Edited by Mehul Donga Friday, July 12, 2013 10:31 AM small change
    Friday, July 12, 2013 10:28 AM
  • With User Account Control, Standard User applications have READ ONLY access to the HKEY_LOCAL_MACHINE_HIVE. "KEY_ALL_ACCESS" is only going to work if the application is running with administrator privileges.

    Ideally your application would use HKEY_CURRENT_USER instead for creating keys.

    http://msdn.microsoft.com/en-us/library/bb530410.aspx

    http://msdn.microsoft.com/en-us/library/aa905330.aspx

    http://technet.microsoft.com/en-us/library/cc709691.aspx

    Friday, July 12, 2013 6:11 PM