Reading the windows registry

Registry Functions

The following are the registry functions.

Function Description
GetSystemRegistryQuota Retrieves the current size of the registry and the maximum size that the registry is allowed to attain on the system.
RegCloseKey Closes a handle to the specified registry key.
RegConnectRegistry Establishes a connection to a predefined registry handle on another computer.
RegCopyTree Copies the specified registry key, along with its values and subkeys, to the specified destination key.
RegCreateKeyEx Creates the specified registry key.
RegCreateKeyTransacted Creates the specified registry key and associates it with a transaction.
RegDeleteKey Deletes a subkey and its values.
RegDeleteKeyEx Deletes a subkey and its values from the specified platform-specific view of the registry.
RegDeleteKeyTransacted Deletes a subkey and its values from the specified platform-specific view of the registry as a transacted operation.
RegDeleteKeyValue Removes the specified value from the specified registry key and subkey.
RegDeleteTree Deletes the subkeys and values of the specified key recursively.
RegDeleteValue Removes a named value from the specified registry key.
RegDisablePredefinedCache Disables handle caching for the predefined registry handle for HKEY_CURRENT_USER for the current process.
RegDisablePredefinedCacheEx Disables handle caching for all predefined registry handles for the current process.
RegDisableReflectionKey Disables registry reflection for the specified key.
RegEnableReflectionKey Enables registry reflection for the specified disabled key.
RegEnumKeyEx Enumerates the subkeys of the specified open registry key.
RegEnumValue Enumerates the values for the specified open registry key.
RegFlushKey Writes all attributes of the specified open registry key into the registry.
RegGetKeySecurity Retrieves a copy of the security descriptor protecting the specified open registry key.
RegGetValue Retrieves the type and data for the specified registry value.
RegLoadKey Creates a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE and stores registration information from a specified file into that subkey.
RegLoadMUIString Loads the specified string from the specified key and subkey.
RegNotifyChangeKeyValue Notifies the caller about changes to the attributes or contents of a specified registry key.
RegOpenCurrentUser Retrieves a handle to the HKEY_CURRENT_USER key for the user the current thread is impersonating.
RegOpenKeyEx Opens the specified registry key.
RegOpenKeyTransacted Opens the specified registry key and associates it with a transaction.
RegOpenUserClassesRoot Retrieves a handle to the HKEY_CLASSES_ROOT key for the specified user.
RegOverridePredefKey Maps a predefined registry key to a specified registry key.
RegQueryInfoKey Retrieves information about the specified registry key.
RegQueryMultipleValues Retrieves the type and data for a list of value names associated with an open registry key.
RegQueryReflectionKey Determines whether reflection has been disabled or enabled for the specified key.
RegQueryValueEx Retrieves the type and data for a specified value name associated with an open registry key.
RegReplaceKey Replaces the file backing a registry key and all its subkeys with another file.
RegRestoreKey Reads the registry information in a specified file and copies it over the specified key.
RegSaveKey Saves the specified key and all of its subkeys and values to a new file.
RegSaveKeyEx Saves the specified key and all of its subkeys and values to a new file. You can specify the format for the saved key or hive.
RegSetKeyValue Sets the data for the specified value in the specified registry key and subkey.
RegSetKeySecurity Sets the security of an open registry key.
RegSetValueEx Sets the data and type of a specified value under a registry key.
RegUnLoadKey Unloads the specified registry key and its subkeys from the registry.

The following shell functions can be used with the registry:

The following are the initialization-file functions. They retrieve information from and copy information to a system- or application-defined initialization file. These functions are provided only for compatibility with 16-bit versions of Windows. New applications should use the registry.

Function Description
GetPrivateProfileInt Retrieves an integer associated with a key in the specified section of an initialization file.
GetPrivateProfileSection Retrieves all the keys and values for the specified section of an initialization file.
GetPrivateProfileSectionNames Retrieves the names of all sections in an initialization file.
GetPrivateProfileString Retrieves a string from the specified section in an initialization file.
GetPrivateProfileStruct Retrieves the data associated with a key in the specified section of an initialization file.
GetProfileInt Retrieves an integer from a key in the specified section of the Win.ini file.
GetProfileSection Retrieves all the keys and values for the specified section of the Win.ini file.
GetProfileString Retrieves the string associated with a key in the specified section of the Win.ini file.
WritePrivateProfileSection Replaces the keys and values for the specified section in an initialization file.
WritePrivateProfileString Copies a string into the specified section of an initialization file.
WritePrivateProfileStruct Copies data into a key in the specified section of an initialization file.
WriteProfileSection Replaces the contents of the specified section in the Win.ini file with specified keys and values.
WriteProfileString Copies a string into the specified section of the Win.ini file.

Obsolete Functions

These functions are provided only for compatibility with 16-bit versions of Windows:

Reading and Writing to the Windows Registry in-process from Node.js

November 9th, 2015

A single npm module that enables Node developers to update the Windows Registry, create file associations, and much more!

As cross-platform application developers, we often need the ability to update the Windows Registry when installing our applications on Windows. Common features requested by app developers include reading and writing keys to Windows registry, creating file associations to make Windows assign default programs to a file extension, elevating processes to run as an administrator, and last but not least doing all this within the same process as our application. This code story describes the development of a single npm module that enables Node developers to perform these commonly-requested operations when installing Node.js applications on Windows.

The Problem

Electron is a framework that enables developers to build cross platform desktop apps with web technologies. Electron is behind Microsoft’s Visual Studio Code, Slack’s Apps, GitHub’s Atom, Facebook’s Nucleide, Docker’s Kinematic, and a few others. Prior to our hackathon with GitHub and Visual Studio Code, developers had limited number of resources to work with in order to interact with the Windows Registry. More importantly, there was no library that allowed developers to update the Windows Registry without running a separate shell script. In order to provide a great app install experience for users on Windows, it was obvious that we needed to create an NPM module that can address all these issues. Since this is an NPM module, all Node.js applications can take advantage of this library.

Overview of the Solution

We partnered with GitHub, the maintainer of Electron, and Visual Studio Code, to enable registry operations and file associations for Node application on Windows. As a result of our hackathon, there is now a NPM module for Windows Registry you can include in your application to do just that.

Interact with Windows APIs

This library interacts with native Windows APIs. We leveraged the following node modules to enable Node.js application to communicate with Windows interfaces:

  • node-ffi – A Node.js addon for loading and calling dynamic libraries using pure Javascript. It can be used to create bindings to native libraries without writing any C++ code. We used this module to load a list of Windows DLLs to call native Windows APIs.
  • ref – A NPM module that turns buffer instances into pointers. We used this module to define our own data types to map to the Windows data types. It also conveniently allowed us to reference and dereference buffers.
  • ref-struct – This module allows us to define and implement structures. In order to communicate with Windows APIs, we needed to implement structs that mirror the inputs and outputs of Windows interfaces.

We leveraged the following Windows DLLs to communicate with Windows APIs.

  • Advapi32.dll – A Windows library that supports numerous APIs including many security and registry calls. We used this library to perform CRUD operations in Windows Registry.
  • Shell32.dll – A Windows library that contains Windows Shell APIs, which are used to open processes on Windows. We used this library to elevate privilege of a process, similar to the experience of running an application as an administrator.

Let’s dive into the code!

Creating Node Wrappers for Windows APIs

We created a Node wrapper adv_api.js for Advapi32.dll to support basic registry manipulation. Using the ffi node module, we can load Advapi32.dll . Then for each Windows API we wanted to call, we created a Javascript API with the expected inputs and outputs.

In C++, the follow example illustrates the use of RegOpenCurrentUser , which is used to retrieve a handle to the HKEY_CURRENT_USER key for the user that the current thread is impersonating.

In our Node.js wrapper, we used the ffi node module to load Advapi32.dll . Then we defined the RegOpenCurrentUser API and other Registry related APIs with their expected inputs and outputs.

Similarly, we created a Node wrapper shell32.js for Shell32.dll , which is used to launch a process on Windows.

In C++, the following example illustrates the use of ShellExecuteEx to launch an application:

In our Node.js wrapper, we used the ffi node module to load Shell32.dll , then we defined the ShellExecuteExA API with its expected input and output.

Create Windows Data Types in JavaScript

As you can see, in order to replicate the exact Windows API call in JavaScript, we needed to create the same function with the exact inputs and outputs of the same data type as the Windows native data types.

For example, let’s look at how we defined the data types for the ShellExecuteExA function.

In C++, here is the definition of the ShellExecuteEx function:

With the above definition, ShellExecuteEx expects a parameter of the type SHELLEXECUTEINFO* , which is a pointer to a SHELLEXECUTEINFO structure that contains and receives information about the application being executed. It also has a return value of type BOOL , which represents the result of executing this call.

In C++, this is the definition of the SHELLEXECUTEINFO structure.

In our Node.js wrapper windef.js, we needed to create the same SHELLEXECUTEINFO struct. Luckily, we had ref , ref struct , and ref union node modules to help us create the same struct in Javascript.

For each struct member, we looked up its data type and its size from the Windows Data Types reference, then created the same data type with the same properties in types.js. We leveraged the ref node module to create types.

Now that we have the SHELLEXECUTEINFO struct in Javascript, we can create an instance of it in utils.js with the runas ShellExecuteEx verb for the lpVerb member and a file path to the process we want to launch for the lpFile member. Let’s call it shellexecuteinfoval . This instance can then be used as a parameter of ShellExecuteExA so that we can launch a process with elevated privilege.

Let’s call ShellExecuteExA with a reference of our new parameter. We implemented this as an asynchronous call so that when the UAC (User Account Control) prompt is launched, the current process can continue to run without waiting on the user to respond.

To wrap everything together, we created an API elevate in our module that takes in a filepath of the process you want to launch, its parameters if any, and a callback to get the user’s response to the UAC prompt.

The process you want to launch with admin access will only be launched after the callback is called and only if the user clicks Yes in the UAC prompt. Otherwise, the process will not be launched. If the user is already running as an admin, the UAC prompt will not be triggered and the process you provided will be launched as an administrator automatically.

Here is an example of this running:

Enable Your Application

To add the NPM module for Windows Registry to your Node application, install the package:

Installation

To install node modules that require compilation on Windows, make sure you have installed the necessary build tools. Specifically, you need npm install -g node-gyp , a cross-platform cli written in Node.js for native addon modules for Node.js.

To install node-gyp , you need to have the following prerequisites installed and configured in your development environment.

  • Install python v2.7.3, and add it to your PATH , npm config set python python2.7
  • Install VC++ Build Tools Technical Preview. You do not need to install the full Visual Studio, only the build tools are required.
    • [Windows 7 only] requires .NET Framework 4.5.1
  • Launch cmd, npm config set msvs_version 2015 —global (this is instead of npm install [package name] —msvs_version=2015 every time.)

Once the prerequisites are installed, you should be able to do npm install -g node-gyp .

Reading and Writing to the Windows Registry

This library implements only a few of the basic registry commands, which allow you to do basic CRUD operations for keys in the registry.

Opening a Registry Key

Registry keys can be opened by either opening a predefined registry key defined in the windef module:

Or you can open a sub key from an already opened key:

And don’t forget to close your key when you’re done. Otherwise, you will leak native resources:

Creating a Key

Creating a key just requires that you have a Key object by either using the predefined keys within the windef.HKEY or opening a subkey from an existing key.

Deleting a Key

To delete a key just call the Key.deleteKey() function.

Writing a Value to a Key

To write a value, you will again need a Key object and just need to call the Key.setValue function:

Getting a Value From a Key

To get a value from a key, just call Key.getValue :

The return value depends on the type of the key (REG_SZ for example will give you a string).

Creating File Associations

To create a file association, you can call the fileAssociation.associateExeForFile api, which will make windows assign a default program for an arbitrary file extension:

After running the code above, you will see files with the extension of .zzz will be automatically associated with the Node program and their file icon will be changed to the Node file icon.

Launching Process as an Admin

To launch a process as an Administrator, you can call the utils.elevate api, which will launch a process as an Administrator causing the UAC (User Account Control) elevation prompt to appear if required. This is similar to the Windows Explorer command “Run as administrator”. Pass in FILEPATH to the process you want to elevate. Pass in any PARAMETERS to run with the process. Since this is an asynchronous call, pass in a callback to handle user’s selection.

Opportunities for Reuse

With NPM module for Windows Registry, developers can now read and write keys to Windows registry, create file associations to make Windows assign default programs to a file extension, and elevate processes to run as an administrator for any Node application running on Windows. With the source code of this NPM module in GitHub, our solution also serves as an example for how to interact with native Windows APIs in Node.js.

Anthony Turner

Sr. Software Security Engineer, Security Solutions Area

Читайте также:  При загрузке windows просит активацию
Оцените статью