gpii-windows
Version:
Components of the GPII personalization infrastructure for use on Microsoft's "Windows" ™
718 lines (638 loc) • 27.2 kB
JavaScript
/*
* Windows Registry Settings Handler
*
* Copyright 2012, 2014 Raising the Floor - International
* Copyright 2012 Antranig Basman
* Copyright 2012 Astea Solutions AD
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* The research leading to these results has received funding from the European Union's
* Seventh Framework Programme (FP7/2007-2013)
* under grant agreement no. 289016.
*
* You may obtain a copy of the License at
* https://github.com/GPII/universal/blob/master/LICENSE.txt
*/
"use strict";
var ffi = require("ffi-napi"),
ref = require("ref"),
Struct = require("ref-struct"),
fluid = require("gpii-universal");
require("../../WindowsUtilities/WindowsUtilities.js");
var gpii = fluid.registerNamespace("gpii");
var windows = fluid.registerNamespace("gpii.windows");
fluid.registerNamespace("gpii.windows.registrySettingsHandler");
var NULL = ref.NULL;
/**
* Pointer to ACL struct.
*
* This type is just for making more human readable working with pointers to ACL
* structs.
*/
var ACLRef = ref.refType("void");
// Guide to node_ffi types and conversions:
// https://github.com/rbranson/node-ffi/wiki/Node-FFI-Tutorial
var advapi32 = new ffi.Library("advapi32", {
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724897(v=vs.85).aspx
// HKEY, LPCWSTR, DWORD, REGSAM, PHKEY
// Note abuse of type of argument 1 - node_ffi doesn't allow us to forge pointers from integers directly,
// as required by base keys
RegOpenKeyExW: [
"int32", ["uint32", "pointer", "uint32", "uint32", "pointer"]
],
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724837(v=vs.85).aspx
// HKEY
RegCloseKey: [
"long", ["uint32"]
],
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724911(v=vs.85).aspx
// HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD
RegQueryValueExW: [
"int32", ["uint32", "pointer", "pointer", "pointer", "pointer", "pointer"]
],
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724844(v=vs.85).aspx
// HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD
// Similar abuse to RegOpenKeyExW
RegCreateKeyExW: [
"long", ["uint32", "pointer", "uint32", "pointer", "uint32", "uint32", "pointer", "pointer", "pointer"]
],
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724923(v=vs.85).aspx
// HKEY, LPCWSTR, DWORD, DWORD, const BYTE*, DWORD
RegSetValueExW: [
"long", ["uint32", "pointer", "uint32", "uint32", "pointer", "uint32"]
],
// https://msdn.microsoft.com/library/ms724847
// HKEY, LPCWSTR
// Similar abuse to RegOpenKeyExW - for convenience, only accepts base keys
RegDeleteKeyExW: [
"long", ["uint32", "pointer", "uint32", "ulong"]
],
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724851(v=vs.85).aspx
// HKEY, LPCWSTR
RegDeleteValueW: [
"long", ["uint32", "pointer"]
],
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724865(v=vs.85).aspx
// HKEY, DWORD, LPTSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE, LPDWORD
// Similar abuse to RegOpenKeyExW - for convenience, only accepts base keys
RegEnumValueW: [
"int32", ["uint32", "uint32", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer"]
],
// https://docs.microsoft.com/es-es/windows/desktop/api/winreg/nf-winreg-reggetkeysecurity
// HKEY, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, LPDWORD
RegGetKeySecurity : [
"long", ["uint32", "uint32", "pointer", "uint32*"]
],
// https://docs.microsoft.com/es-es/windows/desktop/api/winreg/nf-winreg-regsetkeysecurity
// HKEY, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR
RegSetKeySecurity: [
"long", ["uint32", "uint32", "pointer"]
],
// https://docs.microsoft.com/en-us/windows/desktop/api/aclapi/nf-aclapi-setentriesinaclw
// ULONG, PEXPLICIT_ACCESS_W, PACL, PACL
SetEntriesInAclW: [
"uint32", ["ulong", "pointer", "pointer", "pointer"]
],
// https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-initializesecuritydescriptor
// PSECURITY_DESCRIPTOR, DWORD
InitializeSecurityDescriptor: [
"bool", ["pointer", "uint32"]
],
// https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getsecuritydescriptordacl
// PSECURITY_DESCRIPTOR, LPBOOL, PACL, LPBOOL
GetSecurityDescriptorDacl: [
"bool", ["pointer", "bool*", "pointer", "bool*"]
],
// https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptordacl
// PSECURITY_DESCRIPTOR, LPBOOL, PACL, LPBOOL
SetSecurityDescriptorDacl: [
"bool", ["pointer", "bool", "pointer", "bool"]
],
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724865(v=vs.85).aspx
// HKEY, DWORD, LPWSTR, LPDWORD, LPDWORD, LPWSTR, LPDWORD, PFILETIME
// Similar abuse to RegOpenKeyExW - for convenience, only accepts base keys
RegEnumKeyExW: [
"int32", ["uint32", "uint32", "pointer", "pointer", "int", "int", "int", "int"]
]
});
var t = windows.types;
/**
* Structure that holds information to identify to which entities the permissions specified in the
* ExplicitAccess should be applied to.
*
* Doc: https://docs.microsoft.com/en-us/windows/desktop/api/accctrl/ns-accctrl-_trustee_a
*/
windows.Trustee = new Struct([
["pointer", "pMultipleTrustee"],
[t.DWORD, "MultipleTrusteeOperation"],
[t.DWORD, "TrusteeForm"],
[t.DWORD, "TrusteeType"],
["pointer", "ptstrName"]
]);
/**
* Structure that holds the access control information for a security descriptor.
*
* Doc: https://docs.microsoft.com/en-us/windows/desktop/api/accctrl/ns-accctrl-_explicit_access_a
*/
windows.ExplicitAccess = new Struct([
[t.DWORD, "grfAccessPermissions"],
[t.DWORD, "grfAccessMode"],
[t.DWORD, "grfInheritance"],
[windows.Trustee, "Trustee"]
]);
// SECURITY_DESCRIPTOR Constants
windows.securityDescriptorRevision = 1;
// sizeof(SECURITY_DESCRIPTOR)
windows.securityDescriptorSize = 48;
// Minimal permissions required for accessing and modifying keys security information.
windows.securityAccess = windows.accessTypes.READ_CONTROL | windows.accessTypes.WRITE_DAC;
var cr = windows.checkReturnCode;
windows.registryTypes = {};
windows.registryTypes.REG_SZ = {
code: 1,
readConvert: function (pointer) {
return windows.fromWideChar(pointer);
},
writeConvert: function (value) {
return windows.toWideChar(value);
}
};
windows.registryTypes.REG_MULTI_SZ = {
code: 7,
readConvert: function (pointer) {
return windows.stringFromWideCharArray(pointer);
},
writeConvert: function (value) {
var buffer = windows.stringToWideCharArray(value);
return {
pointer: buffer,
length: buffer.length
};
}
};
windows.registryTypes.REG_DWORD = {
code: 4,
readConvert: function (pointer) {
return pointer.readUInt32LE(0);
},
writeConvert: function (value) {
var pointer = new Buffer(4);
pointer.writeUInt32LE(Number(value), 0);
return {
pointer: pointer,
length: 4
};
}
};
windows.registryTypes.REG_BINARY = {
code: 3,
readConvert: function (pointer, count) {
return gpii.pointerToHex(pointer, count);
},
writeConvert: function (value) {
return gpii.hexToPointer(value);
}
};
var c = windows.API_constants;
windows.getBaseKey = function (baseKey) {
var key = c[baseKey];
if (key === undefined) {
fluid.fail("Unknown registry base key " + baseKey);
}
return key;
};
/**
* Parses a registry key path, allowing to specify if the 32 or 64-bit view should be used instead of the one correct
* for the processes. The view is specified by prefixing the real path with "32:" or "64:" (eg, "64:Software\GPII").
* Currently, this is only used when retrieving the MachineGuid.
*
* The return object contains the real path, and a value (KEY_WOW64_64KEY, KEY_WOW64_32KEY, or 0) to bitwise "or" with
* the samDesired parameter of RegCreateKeyEx,
* RegOpenKeyEx, or RegDeleteKeyEx.
*
* @param {String} path The path
* @return {Object} Object containing the real path, and access mask.
*/
windows.parseRegistryPath = function (path) {
var togo = {
desiredAccess: 0,
realPath: path
};
// To explicitly use either the 32 or 64bit view, prepend the path with "32:" or "64:".
if (path[2] === ":") {
var bits = path.substr(0, 2);
if (bits === "64") {
togo.desiredAccess |= c.KEY_WOW64_64KEY;
} else if (bits === "32") {
togo.desiredAccess |= c.KEY_WOW64_32KEY;
}
togo.realPath = path.substr(3);
}
return togo;
};
/**
* Opens the given registy key.
* @param {String} baseKey The name of the base key. One of HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS,
* or HKEY_CURRENT_CONFIG
* @param {String} path Path to the key.
* @param {Buffer} keyHolder Buffer in which the key handle is received.
* @param {Number} extraRights [optional] Any additional access rights required (see https://docs.microsoft.com/windows/desktop/SysInfo/registry-key-security-and-access-rights)
* @return {Object} undefined on success, or { statusCode: 404 }
*/
windows.openRegistryKey = function (baseKey, path, keyHolder, extraRights) {
var regPath = windows.parseRegistryPath(path);
var pathW = windows.ensureAlignment(windows.toWideChar(regPath.realPath).pointer);
var base = windows.getBaseKey(baseKey);
var desiredAccess = regPath.desiredAccess | c.KEY_QUERY_VALUE;
if (extraRights) {
desiredAccess |= extraRights;
}
var code = advapi32.RegOpenKeyExW(base, pathW, 0, desiredAccess, keyHolder);
if (code === windows.API_constants.returnCodes.FILE_NOT_FOUND) {
return {
statusCode: 404
};
}
cr(code);
};
windows.closeRegistryKey = function (keyHolder) {
var code4 = advapi32.RegCloseKey(keyHolder.readUInt32LE(0));
cr(code4);
};
windows.readRegistryKey = function (baseKey, path, subKey, type) {
var converter = windows.registryTypes[type];
if (!converter) {
fluid.fail("Unsupported registry type " + type);
}
var togo = {
statusCode: 200
};
var keyHolder = new Buffer(4);
var openError = windows.openRegistryKey(baseKey, path, keyHolder);
if (openError) {
return openError;
}
try {
var subKeyW = windows.ensureAlignment(windows.toWideChar(subKey).pointer);
var dataLength = new Buffer(4);
var code2 = advapi32.RegQueryValueExW(keyHolder.readUInt32LE(0), subKeyW, NULL, NULL, NULL, dataLength);
if (code2 === windows.API_constants.returnCodes.FILE_NOT_FOUND) {
togo.statusCode = 404;
return togo;
}
cr(code2);
togo.bytes = dataLength.readInt32LE(0);
// Add an extra 2 bytes to ensure the return is always null terminated (numeric values will ignore it).
var valueHolder = new Buffer(togo.bytes + 2);
valueHolder.fill(0);
var code3 = advapi32.RegQueryValueExW(keyHolder.readUInt32LE(0), subKeyW, NULL, NULL, valueHolder, dataLength);
cr(code3);
togo.value = converter.readConvert(valueHolder, togo.bytes);
} finally {
windows.closeRegistryKey(keyHolder);
}
return togo;
};
/**
* Initializes a new empty security descriptor.
*
* @return {Object} A Buffer holding a new empty security descriptor.
*/
windows.initializeSecurityDescriptor = function () {
var newSecDes = Buffer.alloc(windows.securityDescriptorSize);
var resCode = advapi32.InitializeSecurityDescriptor(newSecDes, windows.securityDescriptorRevision);
if (resCode === 0) {
fluid.fail("Error: Failed to initialize security descriptor.");
} else {
return newSecDes;
}
};
/**
* Retrieves a buffer holding a pointer to a security descriptor DACL.
*
* @param {Buffer} secBuffer The containing the security descriptor.
* @param {Buffer} isPresent The buffer for holding a flag that determines if the DACL is especified in the
* security descriptor.
* @param {Buffer} isDefaulted A buffer for holding a flag to get the source of the DACL.
* @return {Buffer} A buffer holding a reference to the current DACL that the security descriptor owns.
*/
windows.getSecurityDescriptorDacl = function (secBuffer, isPresent, isDefaulted) {
var oldACL = ref.alloc(ACLRef);
var desDACLCode = advapi32.GetSecurityDescriptorDacl(secBuffer, isPresent, oldACL, isDefaulted);
if (desDACLCode === 0) {
fluid.fail(windows.win32errorText("Getting security descriptor DACL ", 0, 0));
} else {
return oldACL;
}
};
/**
* Sets a new ACL to the supplied security descriptor.
*
* @param {Buffer} secBuffer The buffer containing the security descriptor.
* @param {Number} daclPresent Flag to indicate the presence of a DACL in the security descriptor.
* @param {Buffer} aclRef Reference to a ACL structrue that specifies the DACL for the security descriptor.
* @param {Number} daclDefaulted Flag that indicates the source of the DACL.
*/
windows.setSecurityDescriptorDacl = function (secBuffer, daclPresent, aclRef, daclDefaulted) {
var resCode = advapi32.SetSecurityDescriptorDacl(secBuffer, daclPresent, aclRef.deref(), daclDefaulted);
if (resCode === 0) {
fluid.fail(windows.win32errorText("Setting security descriptor DACL ", 0, 0));
}
};
/**
* Receives the number of entries in the EXPLICIT_ACCESS struct, and solve the
*
* @param {Number} nEntries Number of entries of the list of EXPLICIT_ACCESS structs passed as second
* parameter.
* @param {Object} eaSt EXPLICIT_ACCESS structure specifying the access control information.
* @param {Object} aclRef Pointer to the existing ACL structure which want to be updated.
* @return {Object} A pointer to a new ACL structure combining the information of the parameters
* 'aclRef' and 'eaSt'.
*/
windows.setEntriesInAclW = function (nEntries, eaSt, aclRef) {
var newACL = ref.alloc(ACLRef);
var newEntriesCode = advapi32.SetEntriesInAclW(nEntries, eaSt.ref(), aclRef.deref(), newACL);
cr(newEntriesCode);
return newACL;
};
/**
* Gets a registry key security descriptor.
*
* @param {Buffer} keyHolder A uint32 size buffer with the pointer to the registry key.
* @param {Number} information A uint32 with the information to be retrieved from the registryKey. Supported values
* can be found in the windows.securityInformation object.
* @return {Buffer} A buffer holding the security descriptor that wanted to be retrieved.
*/
windows.regGetKeySecurity = function (keyHolder, information) {
var secSize = Buffer.alloc(4);
var secBuffer = Buffer.alloc(4);
advapi32.RegGetKeySecurity(keyHolder.readUInt32LE(0), information, secBuffer, secSize);
var secSizeVal = secSize.readUInt32LE(0);
secBuffer = Buffer.alloc(secSizeVal);
var keySecCode = advapi32.RegGetKeySecurity(keyHolder.readUInt32LE(0), information, secBuffer, secSize);
cr(keySecCode);
return secBuffer;
};
/**
* Sets a registry key security descriptor.
*
* @param {Buffer} keyHolder A uint32 size buffer with the pointer to the registry key.
* @param {Number} information A uint32 with the information to be retrieved from the registryKey. Supported values
* can be found in the windows.securityInformation object.
* @param {Buffer} secBuffer A buffer holding the security descriptor that is going to be set in the registry key.
*/
windows.regSetKeySecurity = function (keyHolder, information, secBuffer) {
var resCode = advapi32.RegSetKeySecurity(keyHolder.readUInt32LE(0), information, secBuffer);
cr(resCode);
};
/**
* Writes the necessary permissions to a registry key, so it can be accessed by UWP applications.
*
* @param {Buffer} keyHolder A uint32 size buffer with the pointer to the registry key.
*/
windows.writeUwpSecurity = function (keyHolder) {
var information = windows.securityInformation.DACL_SECURITY_INFORMATION;
var secBuffer = windows.regGetKeySecurity(keyHolder, information);
var isPresent = Buffer.alloc(4);
var isDefaulted = Buffer.alloc(4);
var oldACL = windows.getSecurityDescriptorDacl(secBuffer, isPresent, isDefaulted);
var appAppPackages = "ALL APPLICATION PACKAGES";
var ea = new windows.ExplicitAccess();
ea.grfAccessPermissions = windows.accessTypes.GENERIC_READ;
ea.grfAccessMode = windows.accessMode.SET_ACCESS;
ea.grfInheritance = windows.inheritanceFlags.SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ea.Trustee.TrusteeForm = windows.trusteeForm.TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = windows.trusteeType.TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = windows.toWideChar(appAppPackages).pointer;
var newACL = windows.setEntriesInAclW(1, ea, oldACL);
var isPresentVal = isPresent.readInt8();
var isDefaultedVal = isDefaulted.readInt8();
var newSecDes = windows.initializeSecurityDescriptor();
windows.setSecurityDescriptorDacl(newSecDes, isPresentVal, newACL, isDefaultedVal);
windows.regSetKeySecurity(keyHolder, information, newSecDes);
windows.kernel32.LocalFree(newACL.deref());
};
/**
* Writes a registry key.
*
* @param {String} baseKey The base registry key of the full key path.
* @param {String} path The registry key path without the base key.
* @param {String} subKey The name of the subkey that is going to be written.
* @param {Object} value The value to be set in the subKey.
* @param {String} type The type of the value that is going to be set.
* @param {Boolean} uwpKey A flag indicating if the registry key should be created with special read permissions, so
* UWP application can access them.
* @return {Object} An object holding a field 'statusCode' with the error code
* resulting from the operation.
*/
windows.writeRegistryKey = function (baseKey, path, subKey, value, type, uwpKey) {
var converter = windows.registryTypes[type];
if (!converter) {
fluid.fail("Unsupported registry type " + type);
}
var togo = {
statusCode: 200
};
var regPath = windows.parseRegistryPath(path);
var pathW = windows.ensureAlignment(windows.toWideChar(regPath.realPath).pointer);
var keyHolder = new Buffer(4);
var base = windows.getBaseKey(baseKey);
var code = 0;
if (uwpKey) {
code = advapi32.RegCreateKeyExW(
base, pathW, 0, NULL, 0,
regPath.desiredAccess | c.KEY_SET_VALUE | windows.securityAccess, NULL, keyHolder, NULL
);
} else {
code = advapi32.RegCreateKeyExW(
base, pathW, 0, NULL, 0,
regPath.desiredAccess | c.KEY_SET_VALUE, NULL, keyHolder, NULL
);
}
cr(code);
try {
var subKeyW = windows.ensureAlignment(windows.toWideChar(subKey).pointer);
var code2;
if (value === undefined) {
code2 = advapi32.RegDeleteValueW(keyHolder.readUInt32LE(0), subKeyW);
} else {
var converted = converter.writeConvert(value);
code2 = advapi32.RegSetValueExW(keyHolder.readUInt32LE(0), subKeyW, 0, converter.code, converted.pointer, converted.length);
}
if (value === undefined && code2 === windows.API_constants.returnCodes.FILE_NOT_FOUND) { // Do not fail if delete was requested for nonexistent key
return togo;
}
// TODO: consider plausible errors which might result from this process
cr(code2);
if (uwpKey) {
windows.writeUwpSecurity(keyHolder);
}
} finally {
advapi32.RegCloseKey(keyHolder.readUInt32LE(0));
}
return togo;
};
// Note that this function cannot delete keys recursively. RegDeleteKeyExW is not available
// as a result of requirement for Windows XP level API support. This functionality can be
// implemented manually on top of this existing API if required.
// NB: This utility is currently used only to clean up state from within test cases
windows.deleteRegistryKey = function (baseKey, path) {
var regPath = windows.parseRegistryPath(path);
var pathW = windows.ensureAlignment(windows.toWideChar(regPath.realPath).pointer);
var base = windows.getBaseKey(baseKey);
var code = advapi32.RegDeleteKeyExW(base, pathW, regPath.desiredAccess, 0);
// Do not fail if delete was requested for nonexistent key
if (code !== windows.API_constants.returnCodes.FILE_NOT_FOUND) {
cr(code);
}
};
/**
* Enumerates the values in a key.
*
* @param {String} baseKey The registry base key.
* @param {String} path The key path.
* @return {*} An object containing the name, data, type, and size of each value.
*/
windows.enumRegistryValues = function (baseKey, path) {
var togo = {};
var keyHolder = new Buffer(4);
var openError = windows.openRegistryKey(baseKey, path, keyHolder);
if (openError) {
return openError;
}
try {
var maxLength = 0xffff;
var nameLength = new Buffer(4);
var typeHolder = new Buffer(4);
var nameHolder = new Buffer(maxLength);
var dataSizeHolder = new Buffer(maxLength);
for (var index = 0; ; index++) {
// Get the name, type, and data length of the next value.
nameLength.writeUInt32LE(Number(maxLength), 0);
var code2 = advapi32.RegEnumValueW(keyHolder.readUInt32LE(0), index, nameHolder, nameLength, NULL, typeHolder, NULL, dataSizeHolder);
if (code2 === windows.API_constants.returnCodes.FILE_NOT_FOUND) {
return togo;
} else if (code2 === windows.API_constants.returnCodes.ERROR_NO_MORE_ITEMS) {
break;
} else {
cr(code2);
}
var value = {
name: windows.fromWideChar(nameHolder),
bytes: dataSizeHolder.readInt32LE(0),
type: null,
data: null
};
togo[value.name] = value;
// Add an extra 2 bytes to ensure the return is always null terminated (numeric values will ignore it).
var dataHolder = new Buffer(value.bytes + 2);
dataHolder.fill(0);
var code3 = advapi32.RegQueryValueExW(keyHolder.readUInt32LE(0), nameHolder, NULL, typeHolder, dataHolder, dataSizeHolder);
cr(code3);
// Get the type converter
var typeCode = typeHolder.readUInt32LE(0);
if (typeCode === 2) {
// Cater for REG_EXPAND_SZ (RegGetValue should really have been used if expansion is required)
typeCode = windows.registryTypes.REG_SZ.code;
}
var converter = null;
for (var regType in windows.registryTypes) {
if (windows.registryTypes.hasOwnProperty(regType) && windows.registryTypes[regType].code === typeCode) {
converter = windows.registryTypes[regType];
value.type = regType;
break;
}
}
if (converter) {
value.data = converter.readConvert(dataHolder, dataSizeHolder.readUInt32LE(0));
}
}
} finally {
windows.closeRegistryKey(keyHolder);
}
return togo;
};
/**
* Enumerates the sub-keys in a key.
*
* @param {String} baseKey The registry base key.
* @param {String} path The key path.
* @return {Array<String>} An array of the names of keys contained in the given key.
*/
windows.enumRegistryKeys = function (baseKey, path) {
var togo = [];
var keyHolder = new Buffer(4);
var openError = windows.openRegistryKey(baseKey, path, keyHolder, c.KEY_ENUMERATE_SUB_KEYS);
if (openError) {
return openError;
}
try {
// Max key name is 255 characters (+1 for null terminator, x2 for wide chars)
var maxLength = 0x200;
var nameHolder = new Buffer(maxLength);
var nameLength = ref.alloc(gpii.windows.types.DWORD);
var index = 0;
var code;
do {
nameLength.writeUInt32LE(Number(maxLength), 0);
code = advapi32.RegEnumKeyExW(keyHolder.readUInt32LE(0), index, nameHolder, nameLength, 0, 0, 0, 0);
if (code === 0) {
togo.push(gpii.windows.fromWideChar(nameHolder));
index++;
} else if (code !== windows.API_constants.returnCodes.ERROR_NO_MORE_ITEMS) {
cr(code);
}
} while (code === 0);
} finally {
windows.closeRegistryKey(keyHolder);
}
return togo;
};
windows.registrySettingsHandler.setImpl = function (payload) {
var baseKey = payload.options.hKey;
var path = payload.options.path;
var dataTypes = payload.options.dataTypes;
var uwpKey = payload.options.uwp;
var results = fluid.transform(payload.settings, function (value, key) {
if (dataTypes[key] === undefined) {
fluid.fail("No registry dataType defined in options block for the setting " + key);
}
var dataType = dataTypes[key];
var oldValue = windows.readRegistryKey(baseKey, path, key, dataType);
var writeStatus = windows.writeRegistryKey(baseKey, path, key, value, dataType, uwpKey);
var newValue = windows.readRegistryKey(baseKey, path, key, dataType);
return {
oldValue: oldValue.value,
statusCode: writeStatus.statusCode,
newValue: newValue.value
};
});
fluid.log("Registry settings handler SET returning results ", results);
return results;
};
windows.registrySettingsHandler.getImpl = function (payload) {
var baseKey = payload.options.hKey;
var path = payload.options.path;
var dataTypes = payload.options.dataTypes;
if (dataTypes === undefined) {
fluid.fail("No registry dataTypes block defined in options. Full payload: " +
JSON.stringify(payload, null, 4));
}
var results = fluid.transform(payload.settings, function (value, key) {
if (dataTypes[key] === undefined) {
fluid.fail("No registry dataType defined in options block for the setting " + key);
}
var currentValue = windows.readRegistryKey(baseKey, path, key, dataTypes[key]);
return currentValue.value;
});
fluid.log("Registry settings handler GET returning results ", results);
return results;
};
windows.registrySettingsHandler.get = function (payload) {
return gpii.settingsHandlers.invokeSettingsHandler(windows.registrySettingsHandler.getImpl, payload);
};
windows.registrySettingsHandler.set = function (payload) {
return gpii.settingsHandlers.invokeSettingsHandler(windows.registrySettingsHandler.setImpl, payload);
};