Solved

Unable to write to registry

Posted on 2002-05-31
16
244 Views
Last Modified: 2010-05-02
Helo, I have a program that successfully writes to the HKEY_CURRENT_USER hive, especifically to the /SOFTWARE/ODBC/ODBC.INI key, however this works well in Windows98, when we migrate to Windows 2000 the program begins to raise errors. I realized that in Windows 2000 this values were under another hive HKEY_LOCAL_MACHINE, the key remains the same.
However when I try to overwrite any value I get an error and it is not a trappable error is and unhandled error for vb too because the whole IDE hangs.

Let me know how I can over come this.
0
Comment
Question by:GustavoValdes
  • 5
  • 4
  • 3
  • +2
16 Comments
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
To write to the HKLM hive on Win2k or WinNT I believe the logged in user will need Admin rights.
0
 
LVL 1

Author Comment

by:GustavoValdes
Comment Utility
I've already belong to the Admins group, so, I must supose that I have this kind of rights.
0
 
LVL 1

Expert Comment

by:jdc0724
Comment Utility
Not necessarily.  I am always logged into my Win2K machine as administrator and there were certain registry entries that I could not edit.  Under Win2K there are two registry's.  Regedit, is used primarily for indexed searching.  Regedt32 is the registry in which you want to write to.  Also, when running the Regedt32.exe you can go to the specific key you are having problems with and then select permissions from the menu bar.  You will see that you only have read access.  Being the administrator, you can then grant yourself permission to edit the registry key.  Hope this helps.

JDC0724
0
 
LVL 1

Expert Comment

by:RHuebner
Comment Utility
Not sure if you know this but i'll share anyways, since your most likly using API commands to access the registry I found a problem when moving my code from 9x to NT.

In 9x you report to the API function the size of the buffer plus the null char, however in NT the size must be exact (do not include the null char).

I did right a module containing all my registry access code the determines if your on 9x or NT then adjusts the buffer size value accordingly.

Maybe this is your problem maybe not. Good Luck,
RH.
0
 
LVL 3

Expert Comment

by:MCummings111400
Comment Utility
JDC0724

    There is only one registry on any windows 32-bit OS. However under the Windows NT Family, two registry editors have been shipped, regedit.exe and regedt32.exe, the only supported editor for editing the NT registry is regedt32.exe. the only reason regedit.exe is included is to support editing Windows 95/98 registries from a NT machine
0
 
LVL 1

Author Comment

by:GustavoValdes
Comment Utility
This is a part of the code, the offending line is the last one:

    'Find out windows' version
    If InStr(1, FindOutOS, "2000") Then
        'Look for a different registry fields
         lRetVal = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\ODBC\ODBC.INI\ActDatabase", hKey)
    Else
         lRetVal = RegOpenKey(HKEY_CURRENT_USER, "Software\ODBC\ODBC.INI\ActDatabase", hKey)
    End If

    'Tratar de abrir la llave de los ODBCs
    If lRetVal = ERROR_SUCCESS Then
        'key could be open/created
        sBuffer = LCase(sValorNuevo)
       
        lRetVal = RegSetValueEx(hKey, "ServerName", 0&, REG_SZ, ByVal sBuffer, Len(sBuffer))

When the program tries to execute this last line, VB crashes.

0
 
LVL 1

Expert Comment

by:RHuebner
Comment Utility
Like i said before you must report the correct buffer size
when writing to the registry.

'try this
If Win9x Then            'If 95/98/ME
'Len should return size of buffer plus null char
  lRetVal = RegSetValueEx(hKey, "ServerName", 0&, REG_SZ, ByVal sBuffer, Len(sBuffer))
ElseIf WinNT Then        'If NT/2K/XP
'Len should return size of buffer minus null char
  lRetVal = RegSetValueEx(hKey, "ServerName", 0&, REG_SZ, ByVal sBuffer, Len(sBuffer) - 1)
End If

Good Luck,
RH.
0
 
LVL 1

Expert Comment

by:jdc0724
Comment Utility
MCummings, thanks that is interesting to know.  I wasn't all that familiar with the NT registry setup and that is where I read that NT and 2000pro primarily used regedit.reg for quick searching purposes.  I originally tried to remove virus files from my 2000 computer assuming to use regedit.exe.  However, it wouldn't let me remove any of the virus keys.  That is where I did the reading on 2000pro registry and how they have shipped with both.  Once I went into regedi32.exe I was still denied access to delete the virus files but it allowed me the option of giving myself write access since I was the administrator.  Once I changed my privledges I was able to delete all the virus keys from regedt32.reg without a problem.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Expert Comment

by:jdc0724
Comment Utility
GustavoValdez, RHuebner, now that I have seen the code, I think your first and foremost problem is in your RegOpenKey calls.  These are the old and deprecated calls.  When you use RegOpenKey is uses the default security mask.  Then you try to write to the registry using the "correct" version of "regSetValueEx" which you need to specify a security mask.  

You need to change your "RegOpenKey" to "RegOpenKeyEx" and I think you will be all set.  Let me know if this works.

Thanks,
JDC
0
 
LVL 1

Author Comment

by:GustavoValdes
Comment Utility
Ok, I've changed the code to use know the RegOpenKeyEx function, however all VB crashed when trying to set the registry value.

Thanks in advace for any clue.

Public Function SetCurrentServer(sValorAnterior As String, sValorNuevo As String) As Boolean
    Dim hKey            As Long
    Dim iLong           As Long
    Dim sBuffer         As String
    Dim lRetVal         As Long
   
    sBuffer = GetCurrentServer
   
    If sValorAnterior <> sBuffer Then
        'Los datos de configuración han sido cambiados manualmente
        MsgBox "The ODBC parameters have been changed manually after the last update performed by this program." & vbCrLf & "The active server is " & sBuffer, vbOKOnly + vbInformation, "Warning!"
        'MsgBox "Los datos de configuración han sido modificados maualmente posteriormente al último cambio hecho por este programa." & vbCrLf & "El servidor actual es " & sBuffer, vbOKOnly + vbInformation, "Advertencia"
        SetCurrentServer = False
        Exit Function
    End If
   
   
    'Determinar la version de windows
    If InStr(1, FindOutOS, "2000") Then
        'Look for a different registry fields
         lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\ODBC\ODBC.INI\ActDatabase", 0&, KEY_ALL_ACCESS, hKey)
    Else
         lRetVal = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\ODBC\ODBC.INI\ActDatabase", 0&, KEY_ALL_ACCESS, hKey)
    End If

    'Tratar de abrir la llave de los ODBCs
    If lRetVal = ERROR_SUCCESS Then
        'La llave fue abierta exitosamente
       
        'Fijar los distintos valores del server
       
        'Cambiando el servidor
        sBuffer = LCase(sValorNuevo)
       
        lRetVal = RegSetValueEx(hKey, "ServerName", 0&, REG_SZ, ByVal sBuffer, Len(sBuffer) - 1)
       
        If lRetVal <> ERROR_SUCCESS Then
            MsgBox "The new server parameter could not be updated."
            'MsgBox "El valor de Servidor no pudo ser actualizado"
        End If
       
        'Cambiar el servicio
        sBuffer = LCase(sValorNuevo) & "tcp"
       
        lRetVal = RegSetValueEx(hKey, "Service", 0&, REG_SZ, ByVal sBuffer, Len(sBuffer))
       
        If lRetVal <> ERROR_SUCCESS Then
            MsgBox "The service parameter could not be updated."
            'MsgBox "El valor de Service no pudo ser actualizado"
        End If
       
        'Cambiar el Host Name
        sBuffer = LCase(sValorNuevo)
       
        lRetVal = RegSetValueEx(hKey, "HostName", 0&, REG_SZ, ByVal sBuffer, Len(sBuffer))
       
        If lRetVal <> ERROR_SUCCESS Then
            MsgBox "The hostname parameter could not be updated."
            MsgBox "El valor de HostName no pudo ser actualizado"
        End If
       
    Else
        'La llave no pudo hacer abierta exitosamente
        MsgBox "The ActDatabase DSN has not been defined."
        'MsgBox "No se ha definido el DSN ActDatabase."
        Exit Function
    End If

End Function
0
 
LVL 1

Expert Comment

by:RHuebner
Comment Utility
once again on setting the value of the registry key you must specify the size depending on the OS.

Add this or something like it..

'GET VERSION OF OPERATING SYSTEM
  Private Declare Function GetVersion& Lib "Kernel32" Alias "GetVersionExA" _
    (ByRef lpVersionInfo As OSVERSIONINFO)

  Private Type OSVERSIONINFO      'typedef struct _OSVERSIONINFO{
    dwOSVersionInfoSize As Long   '  DWORD dwOSVersionInfoSize &
    dwMajorVersion As Long        '  DWORD dwMajorVersion &
    dwMinorVersion As Long        '  DWORD dwMinorVersion &
    dwBuildNumber As Long         '  DWORD dwBuildNumber &
    dwPlatformId As Long          '  DWORD dwPlatformId &   is VER_PLATFORM
    szCSDVersion As String * 128  '  TCHAR szCSDVersion[ 128 ] &
  End Type                        '} OSVERSIONINFO &
Const VER_PLATFORM_WIN32s& = 0              'Windows 3.1 w/32 bit
Const VER_PLATFORM_WIN32_WINDOWS& = 1       'Windows 95,98,ME
Const VER_PLATFORM_WIN32_NT& = 2            'Windows NT,2K, XP?

'CONVERT AND RETURN ANSI LENGTH OF VB STRING
Private Function AnsiSize&(Expression As String)
  If WinVersion = "NT" Then 'SIZES ARE EXACT
    AnsiSize = LenB(StrConv(Expression, vbFromUnicode)) '+ 1
  Else                      'SIZE INCLUDES NULL CHAR
    AnsiSize = LenB(StrConv(Expression, vbFromUnicode)) + 1
  End If
End Function

Private Function WinVersion$()
Dim OS_INFO As OSVERSIONINFO, lRet&
  OS_INFO.dwOSVersionInfoSize = Len(OS_INFO) 'SET SIZE OF STRUCT
  lRet = GetVersion(OS_INFO)                          'GET OS VERSION INFO
  Select Case OS_INFO.dwPlatformId
   Case VER_PLATFORM_WIN32_NT: WinVersion = "NT"
   Case VER_PLATFORM_WIN32_WINDOWS:  WinVersion = "9x"
   Case VER_PLATFORM_WIN32_WINDOWS: WinVersion = "3x"
   'Else: Err.Raise "", "API", "UnRecognized Operating System"
  End Select
End Function

Then modify your calls from this...
lRetVal = RegSetValueEx(hKey, "HostName", 0&, REG_SZ, ByVal sBuffer, Len(sBuffer))

to this..
lRetVal = RegSetValueEx(hKey, "HostName", 0&, REG_SZ, ByVal sBuffer, AnsiSize(sBuffer))

weather you use the "Ex"  versioning of the call or not you still must specify the correct size.

RH.
0
 
LVL 1

Expert Comment

by:jdc0724
Comment Utility
Yes, that is correct.  The Buffer size still needs to correctly specified.  It seems there were a couple of issues here.
0
 
LVL 1

Author Comment

by:GustavoValdes
Comment Utility
I have just added your function to determine the correct size of the string to be written in the registry and the error is the same.
This is the error.

The instruction at "0x77db9504" referenced memory at "0x00301d1f". The memory could not be "read".
0
 
LVL 28

Accepted Solution

by:
AzraSound earned 100 total points
Comment Utility
See if you can run vbaccelerator's Registry class to edit that key correctly.  If it does work, maybe you can look through the source to see what he has implemented differently, or just use his class instead.  If it fails as well, there is some other issue involved, perhaps still a security one.

http://www.vbaccelerator.com/codelib/inireg/registry.htm
0
 
LVL 1

Author Comment

by:GustavoValdes
Comment Utility
Thanks to everyone for your help.
In this case, AzraSound answer leads me to a sample project that shows me that there are more Registry Related API functions, especifically they are:
RegSetValueExStr
RegSetValueExLong
RegSetValueExByte

one for every type of registry key value, and I have test using this functions with the length modifications that some of you suggested me before depending on the OS, ant they work.

Thanks a lot.
0
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
FYI:
For future grading, see the grading guidelines at the following link:

http://www.experts-exchange.com/jsp/cmtyQuestAnswer.jsp#3


Glad you found a working solution.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now