Announcement

Collapse
No announcement yet.

Registry Access Problems help needed

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Registry Access Problems help needed

    I am having a problem with Registry access.

    Using the same code (an include file), I can create and recall keys Just fine in one program, but I cannot read those keys in another program


    Here are the functions I am using to read and write. (All debug code is left in)

    Code:
      ' READ FUNCTION
    
    FUNCTION  GetUserSetting (BYVAL hWnd AS LONG, BYVAL Keyno AS LONG, szValue AS ASCIIZ, OPTIONAL szSubKey AS ASCIIZ) AS LONG
    
        LOCAL HomeKey AS LONG, szAppKey AS ASCIIZ * %MAX_PATH, sam AS LONG, hKey AS LONG, iret AS LONG
    
        LOCAL szValueName AS ASCIIZ * %MAX_PATH, iValueType AS LONG, cbValue AS LONG
        LOCAL pL    AS LONG PTR, iGv AS LONG
        LOCAL fv    AS LONG
        LOCAL E AS LONG
    
    
        fv      = %TRUE   ' default to failure
        szValue = ""      ' default to no data
    
        HomeKey =  %REG_HOMEKEY
        szAppkey = $REG_APPKEY
        sam      = %KEY_ALL_ACCESS
    
        sam      = %KEY_READ
        hKey     = %NULL
    
        ' -----------------------------------------------------
        ' if a subkey was specified, append that to the appkey
        '------------------------------------------------------
    
        IF ISTRUE VARPTR(szSubKey) THEN
             szAppkey = szAppKey & "\" & szSubKey
        END IF
    
        ' get a handle to the key of interest
    
        iRet  =   RegOpenKeyEx (HomeKey, szAppkey, BYVAL %NULL, sam, hKey)
        E =        iRet  ' returns error code directly here
    
        MSGBOX USING$("RegOpenKeyEx FOR Key (Home #)  # appkey '&' returns # with hKey # ", Homekey, KeyNo, szAppKey,iRet, hKey)
    
        IF iRet = %ERROR_SUCCESS THEN
            'hresult key is valid and we can proceed to get the value
    
               szValueName =  AppGetValueName (KeyNo)
               cbvalue     =  %MAX_PATH -1        'because they all are
               ' I could call this function with CBValue and szValue = NULL and that will
               ' return ERROR_SUCCESS f key is found along with the actual size and type.
               ' I like that and once this is working I will change this to do that.
    
               igv =  RegQueryValueEx (hkey, szValueName, BYVAL %NULL, iValueType, BYVAL VARPTR(szValue), cbvalue)
               E    = igv  ' regqueryvalueEx returns the error value!  don't use GetLastError() here!
    
    
    
               IF igv = %ERROR_SUCCESS THEN   ' the value was found, an we may have to convert a integer to a string
    
                    MSGBOX USING$("RegQUeryValueEx for '&' succeeded, returns iValueType #", szValueName, iValueType),, "KEY NO " & FORMAT$(Keyno)
    
    
    
                    SELECT CASE AS LONG iValueType
                        CASE %REG_DWORD
                            pL = VARPTR (szValue)
                            szValue = FORMAT$(@pl)
                    END SELECT
                    ' if the only other type we support (REG_SZ), szValue already contains the string data
                    fv  = 0&    ' key successfully obtained
               ELSE
                    szValue = ""
                    ' if key not found returns igv=2 the sstem cannot find the file specified..
                    ' which is what it should do when the key is not found. Maybe I should
                    ' return an explicit value for "Not found" here?
                    ' I think I will have to, since it's possible to have key with no value
                      MSGBOX USING$("ReqQueryValueEx Failed with igv # LE # ", igv,E)  & SystemErrorMessageText(E)
               END IF
               RegCloseKey hKey    ' regardless what happened  if we got here the key was opened and must be closed
        ELSE  'Fails if not found, correctly.
            MSGBOX "RegOpenKeyEx failed " & SystemErrorMessageText (E)
        END IF
    
        FUNCTION = fv
    
    
    END FUNCTION
    
    '  WRITE FUNCTION
    
    FUNCTION SaveUserSetting (BYVAL hWnd AS LONG, BYVAL KeyNo AS LONG, szValue AS ASCIIZ, OPTIONAL szSubKey AS ASCIIZ) AS LONG
    
      LOCAL HomeKey AS LONG, szAppKey AS ASCIIZ * %MAX_PATH, sam AS LONG, hKey AS LONG, iret AS LONG
    
        LOCAL szValueName AS ASCIIZ * %MAX_PATH, iValueType AS LONG, cbData AS LONG
        LOCAL pL    AS LONG PTR, iGv AS LONG
        LOCAL fv    AS LONG
        LOCAL dwDisp AS DWORD  ' will tell us if key was created new or opened old
        LOCAL dwOptions AS DWORD
        LOCAL dwData    AS DWORD   ' address of data
        LOCAL L         AS LONG
    
        LOCAL w AS STRING  ' for debugging only.
    
    
        fv      = %TRUE   ' default to failure
    
    
        HomeKey =  %REG_HOMEKEY
        szAppkey = $REG_APPKEY
        sam      = %KEY_ALL_ACCESS
        hKey     = %NULL
    
        ' -----------------------------------------------------
        ' if a subkey was specified, append that to the appkey
        '------------------------------------------------------
    
        IF ISTRUE VARPTR(szSubKEy) THEN
             szAppkey = szAppKey & "\" & szSubKey
        END IF
    
        ' get a handle to the key of interest, so we can set it.
        ' here we are going to use RegCreateKey so if the key does not (yet) exist, it will be created
        dwOptions = %REG_OPTION_NON_VOLATILE
    
    
    
        iRet  =   RegCreateKeyEx (HomeKey, szAppkey, BYVAL %NULL, _
                   BYVAL %NULL, dwOptions, sam, _
                   BYVAL %NULL, hKey, dwDisp)
    
        IF iRet = %ERROR_SUCCESS THEN ' was created or opened
    
            IF dwDisp = %REG_CREATED_NEW_KEY THEN
                w = USING$("Created New Key '&'", szAppKey)
            ELSEIF dwDisp = %REG_OPENED_EXISTING_KEY THEN
                w = USING$("Opened Existing Key '&'", szAppkey)
            END IF
           ' MSGBOX W,,"SaveUserSetting Debugging"
    
            ' get the value name for this key
            szValueName =  AppGetValueName (KeyNo)
    
    
            ' get the value type for this key
            iValueType  = AppGetValueType (Keyno)
            IF iValueType = %REG_DWORD THEN
                L         = VAL(szValue)
                dwData    = VARPTR(L)
                cbdata    = SIZEOF(L)
            ELSE   ' must be REG_SZ
                dwData    = VARPTR (szValue)
                cbData    = LstrLen(szValue) + 1&   'include terminating null in size
            END IF
            igv = RegSetValueEx (hKey, szValueName, BYVAL %NULL, iValueType, BYVAL dwData, cbData)
            IF igv = %ERROR_SUCCESS THEN
                fv = 0&    ' success!
            END IF
            RegCloseKey    hKey
    
        END IF
    
    
    ' DECLARE FUNCTION RegSetValueEx LIB "ADVAPI32.DLL" ALIAS "RegSetValueExA"
    ' (BYVAL hKey AS DWORD, lpValueName AS ASCIIZ, BYVAL dwReserved AS DWORD,
     ' BYVAL dwType AS DWORD, lpData AS ANY, BYVAL cbData AS DWORD) AS LONG
    
        FUNCTION =  FV
    
    
    
    END FUNCTION

    Both programs are run using the PB IDE "Compiler and Execute" in the same editing session.

    The first program is a pure test program... it can add keys and read them back, or report errors doing so.

    The second program...a "real" appplication is (so far) only trying to read the keys I created in the first program, so I can put the defaults on the screen for editing. However, in this second program, 'RegOpenKeyEx' in the GetUserSetting function always returns 2 (ERR_FILE_NOT_FOUND)

    Regedit can find and modify the keys, values, etc. just fine, and the first program can read them back immeditately after they have been changed by refedit.

    I have tried KEY_ALL_ACCESS instead of KEY_READ in the "Get" function, but the same results.

    I also used RegEdit to delete the whole set of keys, then recompile both programs and start over.

    When reading, both programs do the same thing: they call the GetUserSetting function with a key number.

    Can anyone spot what I am doing wrong here? Need more info?

    (I'm on Win/XP SP2)

    Thanks,
    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

  • #2
    MCM,
    Just to bust a lil bit but am I to assume the following?
    1. OS with the problem is XP? (If Vista then could be a different problem)....EDITED...sorry I missed you posted that part until after I posted.
    2. PB Version? 8.03 or 8.04 I would assume...(In this case I do not see why 1 version vs another should matter but thought I would ask)
    3. Registry is on the "C:\" drive right? and not on another "Physical Drive" or "Drive Partition"?


    If the above is what I think it is, you may (Just MAY) have fallen into a problem that I (only THINK) I have seen in the last few days. So I have to ask for the reason of "Reaching for Straws"

    "When you purposely delete the keys to get a fresh start on things, Is PB itself still open?"... I have seen something similar with *.ini files or *.txt files that I have not had time to investigate yet, but registry may be in the same lines for something to test.

    If you get time, could you throw together a PbForms example of the problem? (at first look I do not see anything that jumps out at me unless I compile a full sample)
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

    Comment


    • #3
      Using the same code (an include file), I can create and recall keys Just fine in one program, but I cannot read those keys in another program
      I can't tell from your sample where your writing these, but it could be a permissions issue. If you write to hKeyCurrentUser, make sure both programs are using the same account. hKeyLocalMachine is usually a safe place when using different accounts.

      Just a thought.
      Software makes Hardware Happen

      Comment


      • #4
        Permissions was my first thought, too, but everything was identical. I ran both programs with the source code up in the IDE with "Compile and Execute." Then I ran from Explorer by double-clicking the EXE... same results.


        I'll strip out enough to create compilable demos and post. But fwiw the equates used above are...
        Code:
        ' ----------------------------------------------
        '   ptmnedi_userINC
        '   INI (registry) Constants and #include of common
        '   Registry access code for use in ptmnedi suite
        '   Created 01.18.08
        ' ----------------------------------------------------
        
        ' ----------------------------------------------------
        ' EQUATES TO BE SET FOR EACH APPLICATION
        ' ---------------------------------------------
        
        %REG_HOMEKEY  = %HKLM                                       ' predefined key used for registry access
        $REG_APPKEY   = "Software\Tal Systems\ptmnedi\ptmncom\1.0"  ' all keys are under this
        
        
        '----------------------------------------
        ' DEFINE KEYS FOR THE APPLICATION
        ' ---------------------------------------
        ' MAIN APPLICATION SETTINGS
        
        %INI_KEY_PTMNCOM_LIBNAME         =  1&       ' full path to the ptmncom.dll file
        
        %INI_KEY_DEFAULT_DBNAME          =  2&
        %INI_KEY_DEFAULT_TIMEOUT         =  3&       ' in seconds
        %INI_KEY_DEFAULT_FREQUENCY       =  4&       ' ditto seconds
        %INI_KEY_DEFAULT_SHOW            =  5&       ' "Y" or "N"
        
        ' Keys which vary within 'soft' subkeys
        ' I want each of these keys to be under a subkey of dbname/username with value name connect
        %INI_KEY_DBROOT          =  10&       ' has no value but has subkeys.
                                              ' I suppose I could use REG_MULTI_SZ here and store a list
                                              ' of the subkeys but that would be silly since I can enum
        %INI_KEY_DBCONNECT       =  11&       ' connection string
        
        %INI_KEY_DBDESCRIPTION   =  12&       ' user database description
        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          You need to make sure your subkeys don't have a \ at beginning or end (Trim$(SubKeys, "\"))...may not be needed in your case, but if params are passed it would be a good idea.

          Other than that, I have never had issues with registry values, some things to consider that cause issues:

          1. Making sure RegCloseKey is called in all cases...perhaps even in errors if it has a value, etc.

          2. It appears you already have it non-volatile, so we can skip that one.

          3. Watching out for Nulls. I don't think I've ever included the null in the size of the string like you do. And, in ansi functions you have to watch out for nulls in names and such too...Sysinternals, back before the Borg took them over, had an interesting article on hiding reg keys because of null issues, etc.

          4. AV and Firewall programs may be blocking your 2nd app's access.

          5. I know you said XP SP2, but another gotcha is in 64bit Registry Hives 32bit apps store to a different value and while you may specify a certain key it is redirected to another section of the registry...right now PB is missing 2 equates to specify and force writing to specific sides:

          KEY_WOW64_32KEY (0x0200)
          KEY_WOW64_64KEY (0x0100)

          6. Permissions as noted. If both are ran one after the other right from Explorer or a Command Prompt I see no issue, but if spawned in some other way or even with one including some type of copy protection, etc all bets are off.
          Last edited by Roger Garstang; 21 Jan 2008, 12:34 AM.
          sigpic
          Mobile Solutions
          Sys Analyst and Development

          Comment


          • #6
            Originally posted by Joe Byrne View Post
            hKeyLocalMachine is usually a safe place when using different accounts.
            It's not. At least not for writing, as users without administrative privileges by default don't have write permission in HKLM.

            Comment


            • #7
              Found the problem.

              I was making up a 'smallest compilable program which demos the problem' and ran that... and it worked OK. (!!!).

              Enabled TRACE and inspected.

              Difference: LONG v DWORD casting. I handled the passing of the parameters slightly differently in the two using programs. In one case the compiler handled it such that it was immaterial, in the other case it didn't handle it the same way, resulting in the wrong "Home Key" (%HOME_KEY).


              Darned, this would have worked OK out of the box if I had been using PB/DLL 5 or 6 intead of 8.

              Sorry to have troubled anyone.

              MCM
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment

              Working...
              X