Dealing with Keys

Here, we are going to learn how to deal with registry keys by using “ring_wincreg” extension capabilities through RCRegistry class library.

Create Key

We can create a new key by using the same functions for opening keys because these functions can create a key if it is not existed and then open it. (Open Key)

Key Existence

We can check whether a specific key existed before we open it by using KeyExists() function. This function accepts two parameters(HKEY ROOT, “SubKeyPath”). See the next example:

Load "wincreg.ring"

New RCRegistry {

        If KeyExists(HKEY_CURRENT_USER, "Software\MyApp") = True
                See "MyApp key is existed inside Software key"
        Else
                See "MyApp does not exist in Software key"
        Ok
}

Open Key

We can open a registry key using more than one function and option.

OpenKey() Function

This function is the primary open key function in the RCRegistry class that could be used to open keys.

This function accepts parameters as a list so we should pass one list parameter that contains other parameters. The number of parameters allowed are 2-4. These parameters are:

  1. The HKEY root indexes: of the windows registry which could either be:
    • HKEY_CLASSES_ROOT
    • HKEY_CURRENT_USER
    • HKEY_LOCAL_MACHINE
    • HKEY_USERS
    • HKEY_CURRENT_CONFIG

    Note

    ROOT HKEY indexes are numbers for each HKEY root, this index has been defined depending on the root organization in Windows Registry Editor but it starts with one. The complete list of HKEY roots indexes is:

    • HKEY_CLASSES_ROOT = 1
      • HKCR = 1
    • HKEY_CURRENT_USER = 2
      • HKCU = 2
    • HKEY_LOCAL_MACHINE = 3
      • HKLM = 3
    • HKEY_USERS = 4
      • HKU = 4
    • HKEY_CURRENT_CONFIG = 5
      • HKCC = 5

    Note that each HKEY root has been shorten for easier call.

  2. The sub key path: which is the key that we want to open under the specified root. It is a complete path to the required key under the specified root.

  3. Flags: which are numerical values represent specific behaviour that should extension assume. These flags allow more control over extension behaviour. They could be one or more of the follow:
    • CREG_CREATE = 1 : this flag will make the function to create the key if its not exist. (This flag used by default if no flags have been set)
    • CREG_READONLY = 0 : this flag opens the key if it is existed but will not create it if it is not. It cannot be used with CREG_CREATE flag at the same time.
    • CREG_AUTOOPEN = 2 : this flag activates the auto open mechanism of this extension, which helps faster performance by automatic close and then open the key whenever it is needed. This is useful in case of repeatedly calling key open and close functions.
    • CREG_NOCACHE = 4 : deactivate the caching mechanism of the CRegistry Class. ( Activated by default )

    Note

    Till now, the first three flags are only effective in the process of opening and closing the key, and the last one is effective in dealing with entries and values. To know how to use flags in more details go to (Set and Get Flags) section.

  4. The option to access Wow64 tree: which could be true for access or false for opposite. It has been set “False” by default.

Hint

Wow64 tree is an automatically created tree of keys inside windows registry for 32 bit programs that run on an 64 bit windows. So opening/creating “Software\MyApp” under the HKEY_LOCAL_MACHINE root will not open/create it as expected but it will be opened/created as “Software\Wow6432Node\MyApp”. (Registry Redirection)

Till now any windows application created by Ring Programming Language is considered to be 32 bit application because Ring is built as 32 bit program.

Now lets have some examples for how to use OpenKey() function.

Example 1

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software", CREG_READONLY])

If Reg.SubKeyExists("Microsoft")
        See "Microsoft key is already present in the Software key"
Ok

Reg.CloseKey()

This example opens “Software” key in the “HKEY_CURRENT_USER” HKEY root for reading only which means it will not auto create sub key if its not existed. Then it checks for “Microsoft” sub key whether it exists under “Software” key or not.

Example 2

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_LOCAL_MACHINE, "Software", CREG_READONLY, True])

If Reg.SubKeyExists("Microsoft")
        See "Microsoft key is already created in the Wow64 tree"
Ok

Reg.CloseKey()

This example does the same task that the previous example do. The main difference is that it opens the key in the Wow64 tree not the regular tree due to adding the forth parameter with “True” value.

Note

This example may show access denied error (if Registry Virtualization has been disabled by manifest file). You can get around it by running Ring as Administrator. You can use “Ring_WINAPI” extension to help elevating Ring.

Note

In case you want to reach Wow64 tree without changing flags you can open the key first by calling OpenKey() function with two parameters then use Access64Tree() function (Accessing Wow64 Tree (Registry Redirection)) to access Wow64 tree.

OpenKey2() Function

This function is an overriding copy of the previous OpenKey() . But it accepts just two non list parameters, these are:

  1. HKEY root.
  2. Sub key to be opened.

Example

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey2(HKCU, "Software\MyApp")

Reg["version"].SetValue("4.4")

See "MyApp version is : " + Reg["version"].GetValue()

Reg.CloseKey()

OpenKey3() Function

This function is an overriding copy of OpenKey() function. But it accepts just three non list parameters, these are:

  1. HKEY root.
  2. Sub key to be opened.
  3. Flags

Example

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey3(HKCU, "Software\MyApp", CREG_CREATE)

Reg["version"].SetValue("4.4")

See "MyApp version is : " + Reg["version"].GetValue()

Reg.CloseKey()

OpenKey4() Function

This function is another overriding copy of OpenKey() function. But it accepts all four non list parameters, which are:

  1. HKEY root.
  2. Sub key to be opened.
  3. Flags.
  4. Wow64 tree access.

Example

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey4(HKEY_LOCAL_MACHINE, "Software\MyApp", CREG_CREATE, True)

Reg["version"].SetValue("4.4")

See "MyApp version is : " + Reg["version"].GetValue()

Reg.CloseKey()

After opening the key it will be saved in an attribute as a pointer in RCRegistry object named (Key), So that it could be used by other functions easily.

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software,MyApp"])

See "This is the information of Key handle pointer of this RCRegistry Object" + NL

See Reg.Key

Reg.CloseKey()

Access HKEY Root

We can access/open any HKEY Root by passing empty string as sub key path as follow:

Load "wincreg.ring"

Reg = New RCRegistry { OpenKey([HKCU, ""]) }

See "The sub keys contained in HKEY_CURRENT_USER are : " + NL

See Reg.GetSubKeys()

Reg.CloseKey()

Close Key

We can close any opened key by using CloseKey() function. It is recommended to close any key you opened to prevent any conflicts when the key is needed to be opened again.

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software\MyApp"])

See "MyApp key is Opened" + NL

Reg.CloseKey()

See "MyApp key is closed"

Set and Get Flags

We can Set or Get flags any time in the code using special functions. This may be useful if we opened a key without specifying enough flags that we want.

This can be done using SetFlags() and GetFlags() functions as follow:

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software\MyApp"])

See "The flags that has been already set are : " + Reg.GetFlags() + NL
# Reg.GetFlags() will return 1 because CREG_CREATE flag has been set by default

Reg.SetFlags(Reg.GetFlags() | CREG_AUTOOPEN)

See "The flags after addition of CREG_AUTOOPEN are : " + Reg.GetFlags() + NL

Reg.SetFlags(Reg.GetFlags() & ~CREG_AUTOOPEN)

See "The flags after subtraction of CREG_AUTOOPEN are : " + Reg.GetFlags()

Reg.CloseKey()

It is a must to know that setting new flags will omit any previously set flags.

You can set multiple flags using bitwise operators as following (check previous example):
  • OR “|” operator : will sum any flags. You can use “+” operator to do the same task.
  • AND plus COMPLEMENT ” & ~ ” operators : will cause subtraction of any previously set flag. These operators reduce the possibility of creating unexpected flags than using “-” operator that may lead to unexpected behaviour if subtracted flags are not set initially.

The most important thing is that subtracting using bitwise operators should be segmented if you want to remove more than one flag as follow:

SetFlags( GetFlags() & ~CREG_AUTOOPEN )
SetFlags( GetFlags() & ~CREG_CREATE )

OR

SetFlags( (GetFlags() & ~CREG_AUTOOPEN) & ~CREG_CREATE )

Note

Setting multiple flags inappropriately may lead to unexpected behaviour.

CREG_CREATE and CREG_READONLY flags are not allowed to be used together in the same flag setting context to avoid unexpected behaviour. The accepted ways to use them are:

  • (CREG_CREATE) : This flag, alone or with other flags, will allow creating new keys.
  • (CREG_READONLY) : This flag, alone or with other flags, will not permit creating keys if they are not existed.
  • (GetFlags() & ~CREG_CREATE) : This expression will switch from CREG_CREATE situation into CREG_READONLY one in a key previously set to allow creating new keys. Providing that GetFlags() function returns multiple flags containing CREG_CREATE flag.
  • (GetFlags() | CREG_CREATE) : this expression will switch from CREG_READONLY situation into CREG_CREATE one in a key previously set to prevent creating new keys. Providing that GetFlags() function returns multiple flags containing CREG_READONLY flag.

The last two conditions help reset flags in case that there are already used multiple flags, but if you want to set flags completely from scratch use the previous two individual flags.

CREG_CREATE flag is used by default when calling OpenKey() function without setting flags. But if you set CREG_AUTOOPEN and\or CREG_NOCACHE flags alone without setting any one of the previous two flags (CREG_CREATE or CREG_READONLY), the extension will use CREG_READONLY by default.

As we highlighted before in (Open Key) section, using CREG_AUTOOPEN flag will help opening and closing the key automatically whenever it is needed, unless the key is manually closed or deleted. Now we will have a quick example showing the benefit of this:

Load "wincreg.ring"

Reg = New RCRegistry { OpenKey([HKCU, "Software\MyApp", CREG_CREATE | CREG_AUTOOPEN]) }
# After opening the key it will be closed automatically

Reg["version"].SetValue("5.5")
# Here the key will be opened, setting the value, and then closed automatically

See "The version of my app is : " + Reg["version"].GetValue()
# Here the key will be opened again, retrieving the value, and then closed automatically

CREG_NOCACHE flag may rarely be used if you want to relieve some load from RAM if the application is suspected to run on old computers, because this extension load all entries of the opened key by default for better responsiveness and performance.

Accessing Wow64 Tree (Registry Redirection)

We can change the setting that let us access the 64 bit applications registry tree any time if we miss to set it during key opening.

This could be done by using Access64Tree() function as follow:

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_LOCAL_MACHINE, "Software\MyApp"])

Reg.Access64Tree(False)

Reg["new value"].SetValue("1")

Reg.Access64Tree(False)

IF Reg["new value"].Exists()
        See "new value does exist" + NL
Else
        See "new value does not exist" + NL
Ok

Reg.Access64Tree(True)

IF Reg["new value"].Exists()
        See "new value does exist" + NL
Else
        See "new value does not exist" + NL
Ok

Reg.CloseKey()

Note

This example may show access denied error. You can get around it by running Ring as Administrator. You can use “Ring_WINAPI” extension to help elevating Ring.

Registry Virtualization Check

We can attempt to check whether the opened key is under virtualization effect or not using IsVirtualized() and IsVirtualized2() functions.

Registry Virtualization is an internal mechanism of Windows that helps keeping the sensitive registry keys and windows files away from being touched by the applications that have been developed to reach them in the previous copies of windows. So that to reach such sensitive keys and files you have to disable virtualization either by running your application/program as an administrator or use manifest files.

Now check whether the currently opened key has been virtualized or not we can use these two functions.

IsVirtualized() Function

This function checks virtualization of the opened key and return True/False.

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_LOCAL_MACHINE, "Software\MyApp"])

If Reg.IsVirtualized()
        See "This key is virtualized"
Else
        See "This key is not virtualized"
Ok

Reg.CloseKey()

IsVirtualized2() Function

This function checks virtualization of the opened key and return:

  1. Number ( 1 ) if it is virtualized.
  2. Number ( 0 ) if it is not virtualized.
  3. Number ( -1 ) if the function is not certain about virtualization of the specified key.
Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_LOCAL_MACHINE, "Software\MyApp"])

Switch Reg.IsVirtualized2()
On 1
        See "This key is virtualized"
On 0
        See "This key is not virtualized"
On -1
        See "The function is not able to check virtualization of this key"
Off

Reg.CloseKey()

Refresh Caching

If we found that some unknown or unexpected behaviours of “ring_wincreg” extension regarding retrieving entries or some values we can refresh the internal catching mechanism by using Refresh() function.

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software\MyApp"])

See "Refreshing wincreg" + NL

Reg.Refresh()

See "Ring_WinCReg extension has been refreshed"

Reg.CloseKey()

Note

This function may not be used during all of your work as there is a good internal management mechanism in “ring_wincreg” extension.

Sub Keys Existence

We can check for any sub key that we may think it could be existed within the opened key by SubKeyExists() function.

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software\MyApp"])

If Reg.SubKeyExists("Options")
        See "Options sub key already existed"
Else
        See "Options sub key does not exist"
Ok

Reg.CloseKey()

Sub Keys Count

We can get the total number of sub keys that are contained within any opened key by using SubKeysCount() function as follow:

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software\MyApp"])

See "The total number of sub keys contained in this key are : " + Reg.SubKeysCount()

Reg.CloseKey()

Sub Key by Index

We can get any sub key present in the opened key by its index using GetSubKeyAt() function.

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software\MyApp"])

See "The first sub key in this key is : " + Reg.GetSubKeyAt(1)

Reg.CloseKey()

Get All Sub Keys

We can get the list of all sub keys in the opened key as a list by using GetSubKeys() function as follow:

Load "wincreg.ring"

New RCRegistry {

        OpenKey([HKEY_CURRENT_USER, "Software\MyApp"])

        See "The list of Keys in MyApp key are : " + NL

        aList = GetSubKeys()

        See aList

        CloseKey()

}

Delete Key

We can delete any key by using DeleteKey() and DeleteKey2() functions.

DeleteKey() Function

This function can delete any opened key as follow:

Load "wincreg.ring"

Reg = New RCRegistry

Reg.OpenKey([HKEY_CURRENT_USER, "Software\MyTempApp"])

See "MyTempApp key is Created and Opened" + NL

Reg.DeleteKey()

See "MyTempApp key is deleted now"

DeleteKey2() Function

This function can delete any key that is not already opened. This function accepts two parameters (HKEY ROOT, “SubKeyPath”) as follow:

Load "wincreg.ring"

New RCRegistry {

        OpenKey([HKEY_CURRENT_USER, "Software\MyTempApp"])

        See "MyTempApp has been created" + NL

        CloseKey()
}

New RCRegistry {

        DeleteKey2(HKEY_CURRENT_USER, "Software\MyTempApp")

        See "MyTempApp key is deleted without opening"

}