Answered by:
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.
KenMonday, 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 3, 2010 6:53 PM
- Marked as answer by Rong-Chun Zhang Monday, January 4, 2010 10:17 AM
Friday, January 1, 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 informationYou 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.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.
KenTuesday, 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.comTuesday, 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.
KenTuesday, 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.comTuesday, 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.
KenTuesday, December 15, 2009 5:30 PM -
In What language do you do this?
C#?
Thanks...
Have a nice day...
Best regards,
Fisnik
Coder24.comTuesday, 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).
KenTuesday, December 15, 2009 5:56 PM -
hmm, why are you working with VB6, when we have Visual Basic 9.0 etc?
Coder24.comTuesday, 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.comWednesday, 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 theLeft$ function() ???
Please post that part as well.
Thanks for sharing your code.
Have a nice day...
Best regards,
Fisnik
Coder24.comWednesday, 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.comWednesday, 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.
KenWednesday, 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.comThursday, 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.comSaturday, 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?
KenSaturday, 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 3, 2010 6:53 PM
- Marked as answer by Rong-Chun Zhang Monday, January 4, 2010 10:17 AM
Friday, January 1, 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.comSunday, January 3, 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
ChrisWednesday, 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"); }
- Proposed as answer by Anonymous-mouse Wednesday, May 25, 2011 10:33 PM
- Unproposed as answer by Anonymous-mouse Wednesday, May 25, 2011 10:34 PM
Wednesday, May 25, 2011 8:11 PM -
In C++ you need to change the Manifest in the properties:
- Right click on the head of the project, below the solution
- You will get a popup menu, select: Properties
- Under: Configuration Properties/Linker/Manifest file, select:
- UAC Execution Level: change from asInvoker to requireAdministrator
- Rebuild
- 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 9, 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 9, 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
- Proposed as answer by Chuck Walbourn - MSFTMicrosoft employee Friday, July 12, 2013 6:11 PM
Friday, July 12, 2013 6:11 PM -
'Hi, this is my solution! :), and really it is works!
lRetVal = RegOpenKeyEx(lPredefinedKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
If lRetVal <> 0 Then ' Force RegOpenKeyEx! It may be has problem accessing 64bit registry from 32bit apps, so this is a dirty solution!
Dim K As Long
For K = 0 To 99999
lRetVal = RegOpenKeyEx(lPredefinedKey, sKeyName, 0, K, hKey)
If lRetVal = 0 Then Exit For
Next K
End If
Tuesday, April 25, 2017 3:30 PM -
even after making above changes, I am not able to write in HKLM.Wednesday, December 4, 2019 10:02 AM
-
even after making above changes, I am not able to write in HKLM.
Your comment was added to a 10 year old question that has been marked as answered.
You should post your question in a new thread and provide all relevant details including your version of Windows, the programming language being used and the specific error codes/messages that are encountered. It is often helpful to include a code snippet that demonstrates what you are trying to do.
Friday, December 6, 2019 11:28 AM