UNPKG

gpii-windows

Version:

Components of the GPII personalization infrastructure for use on Microsoft's "Windows" ™

562 lines (480 loc) 20.7 kB
/* * Windows Registry Settings Handler * * Licensed under the New BSD license. You may not use this file except in * compliance with this License. * * You may obtain a copy of the License at * https://github.com/GPII/universal/blob/master/LICENSE.txt */ "use strict"; var fluid = require("gpii-universal"), os = require("os"); var jqUnit = fluid.require("node-jqunit"); var gpii = fluid.registerNamespace("gpii"); require("../src/RegistrySettingsHandler.js"); fluid.registerNamespace("gpii.tests.windows.registrySettingsHandler"); jqUnit.module("RegistrySettingsHandler Module"); gpii.tests.windows.registrySettingsHandler.apiTest = { init: { "settings": { "FollowMouse": 1, "Invert": 0, "Magnification": 225 }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD" } } }, set: { payload: { "com.windows.magnifier": [{ "settings": { "FollowMouse": 0, "Invert": 1, "Magnification": 235 }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD" } } }] }, uwpPayload: { "com.windows.magnifier": [{ "settings": { "FollowMouse": 0, "Invert": 1, "Magnification": 235 }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD" }, "uwp": true } }] }, expectedResult: { "com.windows.magnifier": [{ "settings": { "FollowMouse": { "oldValue": 1, "statusCode": 200, "newValue": 0 }, "Invert": { "oldValue": 0, "statusCode": 200, "newValue": 1 }, "Magnification": { "oldValue": 225, "statusCode": 200, "newValue": 235 } } }] } }, get: { payload: { "com.windows.magnifier": [{ "settings": { "FollowMouse": { "dataType": "REG_DWORD" }, "Invert": { "dataType": "REG_DWORD" }, "Magnification": { "dataType": "REG_DWORD" } }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD" } } }] }, expectedResult: { "com.windows.magnifier": [{ "settings": { "FollowMouse": 1, "Invert": 0, "Magnification": 225 } }] } } }; gpii.tests.windows.registrySettingsHandler.handlerOneTest = { initPayload: { "settings": { "FollowMouse": 1, "Invert": 0, "Magnification": 255 }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD" } } }, setPayload: { "settings": { "FollowMouse": 0, "Invert": 1 }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD" } } }, expectedReturn: { "FollowMouse": { "oldValue": 1, "statusCode": 200, "newValue": 0 }, "Invert": { "oldValue": 0, "statusCode": 200, "newValue": 1 } } }; gpii.tests.windows.registrySettingsHandler.enumerationTest = { initPayload: { "settings": { "FollowMouse": 1, "Invert": 0, "Magnification": 255, "Description": "GPII Magnifier", "ZeroLength": "" }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD", "Description": "REG_SZ", "ZeroLength": "REG_SZ" } }, "count": 5 }, expectedReturn: { "FollowMouse": { "data": 1, "bytes": 4, "name": "FollowMouse", "type": "REG_DWORD" }, "Invert": { "data": 0, "bytes": 4, "name": "Invert", "type": "REG_DWORD" }, "Magnification": { "data": 255, "bytes": 4, "name": "Magnification", "type": "REG_DWORD" }, "Description": { "data": "GPII Magnifier", "bytes": 30, "name": "Description", "type": "REG_SZ" }, "ZeroLength": { "data": "", "bytes": 2, "name": "ZeroLength", "type": "REG_SZ" } } }; gpii.tests.windows.registrySettingsHandler.deleteKeyTest = { initPayload: { "settings": { "FollowMouse": 1, "Invert": 0, "Magnification": 255, "Description": "GPII Magnifier" }, "options": { "hKey": "HKEY_CURRENT_USER", "path": "Software\\GPIIMagnifier", "dataTypes": { "FollowMouse": "REG_DWORD", "Invert": "REG_DWORD", "Magnification": "REG_DWORD", "Description": "REG_SZ" } }, "count": 4 }, expectedReturn: { "statusCode": 404 } }; jqUnit.test("Testing registrySettingsHandler.setImpl incl undefined value.value", function () { jqUnit.expect(1); // set to initial values: gpii.windows.registrySettingsHandler.setImpl(gpii.tests.windows.registrySettingsHandler.handlerOneTest.initPayload); // now that we 'know' current values, set new ones: var actualReturn = gpii.windows.registrySettingsHandler.setImpl(gpii.tests.windows.registrySettingsHandler.handlerOneTest.setPayload); // check results jqUnit.assertDeepEq("Checking return payload", gpii.tests.windows.registrySettingsHandler.handlerOneTest.expectedReturn, gpii.resolveSync(actualReturn)); // cleanup gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier"); }); jqUnit.test("Reading and writing single registry keys", function () { jqUnit.expect(7); var dwordValue = 100; gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "Magnification", dwordValue, "REG_DWORD"); var value = gpii.windows.readRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "Magnification", "REG_DWORD"); jqUnit.assertEquals("Assert REG_DWORD", dwordValue, value.value); var unicodeString = "I am Agent Гюнтер"; gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationAnnotation", unicodeString, "REG_SZ"); var value2 = gpii.windows.readRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationAnnotation", "REG_SZ"); jqUnit.assertEquals("Assert REG_SZ", unicodeString, value2.value); gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationBinary", "0a, b0, cAfebAbe", "REG_BINARY"); var value3 = gpii.windows.readRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationBinary", "REG_BINARY"); jqUnit.assertEquals("Assert REG_BINARY", "0a b0 ca fe ba be", value3.value); var stringArray = [ "item 1", "item 2", "item 3" ]; gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationArray", stringArray, "REG_MULTI_SZ"); var value4 = gpii.windows.readRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationArray", "REG_MULTI_SZ"); jqUnit.assertDeepEq("Assert REG_MULTI_SZ", stringArray, value4.value); var stringNotArray = "item ABC"; gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationArray", stringNotArray, "REG_MULTI_SZ"); var value5 = gpii.windows.readRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "MagnificationArray", "REG_MULTI_SZ"); jqUnit.assertDeepEq("Assert REG_MULTI_SZ", [ stringNotArray ], value5.value); gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "Magnification", undefined, "REG_DWORD"); var value6 = gpii.windows.readRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "Magnification", "REG_DWORD"); jqUnit.assertDeepEq("Assert value not found after deleted", {statusCode: 404}, value6); // Test zero-length values return an empty string (GPII-2751). // The failure of this test also depends on the 2 bytes after the buffer being zero, so run it a few times to reduce // the element of luck. var tries = 500; jqUnit.expect(tries); for (var retry = 0; retry < tries; retry++) { var emptyString = ""; gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "ZeroTest", emptyString, "REG_SZ"); var result = gpii.windows.readRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "ZeroTest", "REG_SZ"); jqUnit.assertEquals("Assert empty REG_SZ", 0, result.value.length); if (result.value.length !== 0) { // One fail is enough. break; } } // clean up after ourselves gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier"); // test for GPII-1108 - deletion of subkey of nonexistent parent should be permitted gpii.windows.writeRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier", "Magnification", undefined, "REG_DWORD"); jqUnit.assert("Deletion of subkey of nonexistent parent should be valid noop"); }); jqUnit.test("Testing registrySettingsHandler API (get and set functions)", function () { jqUnit.expect(2); // set to initial values: gpii.windows.registrySettingsHandler.setImpl(gpii.tests.windows.registrySettingsHandler.apiTest.init); // First we test the get functionality var result = gpii.windows.registrySettingsHandler.get(gpii.tests.windows.registrySettingsHandler.apiTest.get.payload); // check results jqUnit.assertDeepEq("Checking return payload of get", gpii.tests.windows.registrySettingsHandler.apiTest.get.expectedResult, gpii.resolveSync(result)); // Test set functionality var result2 = gpii.windows.registrySettingsHandler.set(gpii.tests.windows.registrySettingsHandler.apiTest.set.payload); // check results jqUnit.assertDeepEq("Checking return payload of set", gpii.tests.windows.registrySettingsHandler.apiTest.set.expectedResult, gpii.resolveSync(result2)); // cleanup gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier"); }); jqUnit.test("Enumerating registry key values", function () { var testData = gpii.tests.windows.registrySettingsHandler.enumerationTest; var baseKey = testData.initPayload.options.hKey; var path = testData.initPayload.options.path; // Apply the data gpii.windows.registrySettingsHandler.setImpl(testData.initPayload); // Enumerate the key var result = gpii.windows.enumRegistryValues(baseKey, path); // Check the result jqUnit.assertDeepEq("Checking the return of enumRegistryValues", testData.expectedReturn, result); // Clean up gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier"); }); jqUnit.test("Enumerating registry key sub-keys", function () { var baseKey = "HKEY_CURRENT_USER"; var path = "Software\\GPIIMagnifier"; var subkeys = []; for (var n = 0; n < 10; n++) { var subkeyName = "subkey" + n; subkeys.push(subkeyName); gpii.windows.writeRegistryKey(baseKey, path + "\\" + subkeyName, "dummyvalue", "abc", "REG_SZ"); } // Enumerate the key var result = gpii.windows.enumRegistryKeys(baseKey, path); // Check the result jqUnit.assertDeepEq("Checking the return of enumRegistryKeys", subkeys.sort(), result.sort()); // Clean up fluid.each(subkeys, function (keyName) { gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier\\" + keyName); }); gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier"); }); jqUnit.test("Key deletion", function () { var testData = gpii.tests.windows.registrySettingsHandler.deleteKeyTest; var baseKey = testData.initPayload.options.hKey; var path = testData.initPayload.options.path; // Apply the data gpii.windows.registrySettingsHandler.setImpl(testData.initPayload); // Delete it gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier"); // Enumerate the key var result = gpii.windows.enumRegistryValues(baseKey, path); // Check the result jqUnit.assertDeepEq("Checking the return of enumRegistryValues", testData.expectedReturn, result); }); jqUnit.test("Non-existing key deletion", function () { jqUnit.expect(1); try { // Delete it gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\key-does-not-exist"); } catch (e) { jqUnit.fail("Should not fail."); throw e; } jqUnit.assert("Should succeed."); }); jqUnit.test("Testing 32/64 bit views", function () { // HKEY_LOCAL_MACHINE\Software has different values for 32/64-bit processes, however this one is write-able. // https://msdn.microsoft.com/library/aa384253 var baseKey = "HKEY_CURRENT_USER"; var path = "Software\\Classes\\CLSID\\GPII-Test"; var path32 = "32:" + path; var path64 = "64:" + path; var testValue = "test"; var bits = (os.arch() === "x64") ? "64" : "32"; // 32-bit read/write gpii.windows.writeRegistryKey(baseKey, path32, "test32", testValue, "REG_SZ"); var result1 = gpii.windows.readRegistryKey(baseKey, path32, "test32", "REG_SZ"); jqUnit.assertEquals("32-bit registry view should work", testValue, result1.value); // 64-bit read/write gpii.windows.writeRegistryKey(baseKey, path64, "test64", testValue, "REG_SZ"); var result2 = gpii.windows.readRegistryKey(baseKey, path64, "test64", "REG_SZ"); jqUnit.assertEquals("64-bit registry view should work", testValue, result2.value); if (gpii.windows.isWow64() || bits === "64") { // These tests aren't valid on a 32-bit OS because there is only 1 registry view; 32-bit and 64-bit views // point to the same thing, so both values will exist. // Try 32-bit value from 64-bit var result3 = gpii.windows.readRegistryKey(baseKey, path64, "test32", "REG_SZ"); jqUnit.assertUndefined("32-bit value should not exist in 64-bit registry view", result3.value); // Try 32-bit value from 64-bit var result4 = gpii.windows.readRegistryKey(baseKey, path32, "test64", "REG_SZ"); jqUnit.assertUndefined("64-bit value should not exist in 32-bit registry view", result4.value); // Get native value from native view var result5 = gpii.windows.readRegistryKey(baseKey, path, "test" + bits, "REG_SZ"); jqUnit.assertEquals("native-bit value should be in native-bit registry view", testValue, result5.value); // Try other value from native view var otherBits = (bits === "64") ? "32" : "64"; var result6 = gpii.windows.readRegistryKey(baseKey, path, "test" + otherBits, "REG_SZ"); jqUnit.assertUndefined("non-native-bit value should not be in in native-bit registry view", result6.value); } // Clean up gpii.windows.deleteRegistryKey(baseKey, path32); gpii.windows.deleteRegistryKey(baseKey, path64); }); var windows = fluid.registerNamespace("gpii.windows"); var ffi = require("ffi-napi"), ref = require("ref"); var advapi32 = new ffi.Library("advapi32", { GetExplicitEntriesFromAclW: [ "uint32", ["void*", "uint32*", "void*"] ], LookupAccountSidW: [ "bool", [ "pointer", "pointer", "char*", "uint32*", "char*", "uint32*", "uint32*"] ] }); jqUnit.test("Testing UWP key permissions", function () { jqUnit.expect(2); // set to initial values: gpii.windows.registrySettingsHandler.setImpl(gpii.tests.windows.registrySettingsHandler.apiTest.init); // Test set functionality var result2 = gpii.windows.registrySettingsHandler.set(gpii.tests.windows.registrySettingsHandler.apiTest.set.uwpPayload); // check results jqUnit.assertDeepEq("Checking return payload of set", gpii.tests.windows.registrySettingsHandler.apiTest.set.expectedResult, gpii.resolveSync(result2)); var keyHolder = Buffer.alloc(4); // Check key permissions try { var information = windows.securityInformation.DACL_SECURITY_INFORMATION; var baseKey = "HKEY_CURRENT_USER"; var path = "Software\\GPIIMagnifier"; windows.openRegistryKey(baseKey, path, keyHolder, windows.securityAccess); var secBuffer = windows.regGetKeySecurity(keyHolder, information); var isPresent = Buffer.alloc(4); var isDefaulted = Buffer.alloc(4); var oldACL = windows.getSecurityDescriptorDacl(secBuffer, isPresent, isDefaulted); var entriesBuff = Buffer.alloc(4); var eaRef = ref.alloc("int"); advapi32.GetExplicitEntriesFromAclW(oldACL.deref(), entriesBuff, eaRef); var entries = entriesBuff.readUInt32LE(); var foundCorrectPermission = false; var allACLs = eaRef.readPointer(0, windows.ExplicitAccess.size * entries); for (var i = 0; i < entries; i++) { var curACL = ref.get(allACLs, i * windows.ExplicitAccess.size, windows.ExplicitAccess); var nameBuff = Buffer.alloc(200); var bufferSize = Buffer.alloc(4); bufferSize.writeUInt32LE(100); var domainName = Buffer.alloc(200); var domainNameSize = Buffer.alloc(4); domainNameSize.writeUInt32LE(100); var nameUse = Buffer.alloc(4); var systemName = Buffer.alloc(10); advapi32.LookupAccountSidW(systemName, curACL.Trustee.ptstrName, nameBuff, bufferSize, domainName, domainNameSize, nameUse); var name = windows.fromWideChar(nameBuff); if (name === "ALL APPLICATION PACKAGES") { foundCorrectPermission = true; break; } } jqUnit.assertDeepEq("Correct permissions where found into modified key", true, foundCorrectPermission); windows.kernel32.LocalFree(eaRef.deref()); } finally { windows.closeRegistryKey(keyHolder); gpii.windows.deleteRegistryKey("HKEY_CURRENT_USER", "Software\\GPIIMagnifier"); } });