diff --git a/gpii/node_modules/WindowsUtilities/WindowsUtilities.js b/gpii/node_modules/WindowsUtilities/WindowsUtilities.js index f6cb9ef5f..d040cdefe 100644 --- a/gpii/node_modules/WindowsUtilities/WindowsUtilities.js +++ b/gpii/node_modules/WindowsUtilities/WindowsUtilities.js @@ -329,6 +329,12 @@ windows.API_constants = { disableAT: 2, enableAT: 3, + // https://msdn.microsoft.com/library/ms724947 + SpiFlags: { + SPIF_UPDATEINIFILE: 0x1, + SPIF_SENDCHANGE: 0x2 + }, + MONITOR_DEFAULTTOPRIMARY: 1, CCHDEVICENAME: 32, QDC_ONLY_ACTIVE_PATHS: 2, @@ -767,21 +773,62 @@ windows.createEmptyStructure = function (structName) { * Takes an array of flag names, applies binary OR among them and returns the result. * Used to supply the "dwFlags" argument of some structures. * - * @param {Array} flagNamesArray An array of flag names. - * These should be predefined in windows.flagConstants. + * @param {Array} flagNamesArray An array of flag names, which must be in allFlags. + * @param {Array} allFlags [optional] An array of all possible flags and their value. Defaults to windows.flagConstants. + * @param {String} op [optional] The operation, either "or" (default) or "and". */ -windows.combineFlags = function (flagNamesArray) { +windows.combineFlags = function (flagNamesArray, allFlags, op) { + allFlags = allFlags || windows.flagConstants; + var or = op !== "and" && op !== "&"; + + var combine = or + ? function (left, right) { return left | right; } + : function (left, right) { return left & right; }; + var combinedFlags = 0; if (!fluid.isArrayable(flagNamesArray)) { - console.log("GPII Windows SpiSettingsHandler combineFlags: array expected!"); + fluid.log("GPII Windows SpiSettingsHandler combineFlags: array expected!"); return 0; } for (var index in flagNamesArray) { - combinedFlags = combinedFlags | windows.flagConstants[flagNamesArray[index]]; + combinedFlags = combine(combinedFlags, allFlags[flagNamesArray[index]]); } return combinedFlags; }; +/** + * Resolves a list of flags into the numeric value. Flags can either be a string, with the delimiter of either + * "|" or "&" specifying the operation, or an array of flag strings (in which case the operation is binary OR). + * + * The value of each possible flag is specified in allFlags. + * + * @param {String|Array} flags The list of flags to resolve. + * @param {Array} allFlags An associative array of every flag. + * @return {number} The numeric value of flags. + */ +windows.resolveFlags = function (flags, allFlags) { + var togo = 0; + if (!isNaN(Number(flags))) { + // Use the hard-coded number as-is + togo = Number(flags); + } else if (flags) { + var op = "or"; + // Split a string into an array. + if (typeof(flags) === "string") { + var or = flags.indexOf("&") < 0; + op = or ? "or" : "and"; + flags = flags.split(/ *[&|]+ */); + } + if (fluid.isArrayable(flags)) { + togo = gpii.windows.combineFlags(flags, allFlags, op); + } else { + fluid.fail("windows.resolveFlags was passed an unknown type of flags"); + } + } + + return togo; +}; + /** * Gets the value of a given flag name. * diff --git a/gpii/node_modules/spiSettingsHandler/src/SpiChildProcess.js b/gpii/node_modules/spiSettingsHandler/src/SpiChildProcess.js index 5bf31da66..8bda36c11 100644 --- a/gpii/node_modules/spiSettingsHandler/src/SpiChildProcess.js +++ b/gpii/node_modules/spiSettingsHandler/src/SpiChildProcess.js @@ -24,6 +24,7 @@ var ffi = require("ffi"); var pvParamPrimitive = process.env.GPII_SPI_PVPARAM_PRIMITIVE === "1"; var action = process.env.GPII_SPI_ACTION; var uiParam = process.env.GPII_SPI_UIPARAM; +var fWinIni = process.env.GPII_SPI_FWININI; var pvParam, type; if (pvParamPrimitive) { @@ -40,4 +41,4 @@ var user32 = ffi.Library("user32", { ] }); -return user32.SystemParametersInfoW(action, uiParam, pvParam, 0); +return user32.SystemParametersInfoW(action, uiParam, pvParam, fWinIni); diff --git a/gpii/node_modules/spiSettingsHandler/src/SpiSettingsHandler.js b/gpii/node_modules/spiSettingsHandler/src/SpiSettingsHandler.js index 47ecb7df4..d92d89ca7 100644 --- a/gpii/node_modules/spiSettingsHandler/src/SpiSettingsHandler.js +++ b/gpii/node_modules/spiSettingsHandler/src/SpiSettingsHandler.js @@ -83,13 +83,13 @@ gpii.windows.spi.getCurrentSettings = function (payload) { return currentSettings; }; -gpii.windows.spi.systemParametersInfo = function (pvParamType, action, uiParam, pvParam) { +gpii.windows.spi.systemParametersInfo = function (pvParamType, action, uiParam, pvParam, fWinIni) { var callSuccessful = 0; if (pvParamType === "BOOL" || pvParamType === "UINT") { - callSuccessful = gpii.windows.spi.systemParametersInfoWUint.SystemParametersInfoW(action, uiParam, pvParam, 0); + callSuccessful = gpii.windows.spi.systemParametersInfoWUint.SystemParametersInfoW(action, uiParam, pvParam, fWinIni); } else { - callSuccessful = gpii.windows.spi.systemParametersInfoWPtr.SystemParametersInfoW(action, uiParam, pvParam, 0); + callSuccessful = gpii.windows.spi.systemParametersInfoWPtr.SystemParametersInfoW(action, uiParam, pvParam, fWinIni); } return callSuccessful; @@ -123,7 +123,7 @@ gpii.windows.spi.waitForSpi = function (action) { /** * Performs the SPI call in a child-process. This is used on certain SPI_SET* calls to SPI that are known to be - * troublesome and have the potential to hang. + * troublesome and have the potential to hang, or when calling with fWinIni=SPIF_SENDCHANGE. * * See GPII-2001 for an example, where a system process causes this phenomenon. While it may be possible to fix that * particular issue, it raises the question: what prevents other processes from doing the same? To work around this, @@ -136,9 +136,10 @@ gpii.windows.spi.waitForSpi = function (action) { * @param action The uiAction SPI parameter. * @param uiParam The uiParam SPI parameter. * @param pvParam The pvParam SPI parameter. + * @param fWinIni The fWinIni SPI parameter. * @return {promise} Rejects if the SPI call hangs. */ -gpii.windows.spi.callProblematicSpi = function (pvParamType, action, uiParam, pvParam) { +gpii.windows.spi.callProblematicSpi = function (pvParamType, action, uiParam, pvParam, fWinIni) { var cp = require("child_process"); var primitiveType = pvParamType in gpii.windows.types; @@ -148,7 +149,8 @@ gpii.windows.spi.callProblematicSpi = function (pvParamType, action, uiParam, pv GPII_SPI_ACTION: action, GPII_SPI_UIPARAM: uiParam, GPII_SPI_PVPARAM_PRIMITIVE: primitiveType ? 1 : 0, - GPII_SPI_PVPARAM: primitiveType ? pvParam : pvParam.toString("hex") + GPII_SPI_PVPARAM: primitiveType ? pvParam : pvParam.toString("hex"), + GPII_SPI_FWININI: fWinIni }, execArgv: [] }; @@ -190,6 +192,7 @@ gpii.windows.spi.applySettings = function (payload) { var action = gpii.windows.actionConstants[payload.options.setAction]; var uiParam = gpii.windows.spi.getUiParam(payload); var pvParam = gpii.windows.spi.getPvParam(payload); + var fWinIni = gpii.windows.resolveFlags(payload.options.fWinIni, gpii.windows.API_constants.SpiFlags); uiParam = pvParam.uiParam; // this will be updated because it looks bad pvParam = pvParam.pvParam; @@ -206,12 +209,15 @@ gpii.windows.spi.applySettings = function (payload) { // Wait for sethc.exe to end before making the SPI call gpii.windows.spi.waitForSpi() .then(function () { + // SPIF_SENDCHANGE broadcasts several messages and has the potential to block, so call it in a child + // process. + var sendChange = fWinIni & gpii.windows.API_constants.SpiFlags.SPIF_SENDCHANGE; - if (problematicSpiCalls.indexOf(action) >= 0) { - var p = gpii.windows.spi.callProblematicSpi(pvParamType, action, uiParam, pvParam); + if (sendChange || (problematicSpiCalls.indexOf(action) >= 0)) { + var p = gpii.windows.spi.callProblematicSpi(pvParamType, action, uiParam, pvParam, fWinIni); fluid.promise.follow(p, promiseTogo); } else { - var callSuccessful = gpii.windows.spi.systemParametersInfo(pvParamType, action, uiParam, pvParam); + var callSuccessful = gpii.windows.spi.systemParametersInfo(pvParamType, action, uiParam, pvParam, fWinIni); if (callSuccessful) { fluid.promise.follow(gpii.windows.spi.waitForSpi(action), promiseTogo); diff --git a/gpii/node_modules/windowMessages/src/windowMessages.js b/gpii/node_modules/windowMessages/src/windowMessages.js index 4d65801db..1ca0d1d0d 100644 --- a/gpii/node_modules/windowMessages/src/windowMessages.js +++ b/gpii/node_modules/windowMessages/src/windowMessages.js @@ -159,7 +159,7 @@ gpii.windows.messages.messagePump = function (that) { } if (that.messageWindow) { - setTimeout(loop, 2000); + setTimeout(loop, 300); } }; loop(); diff --git a/package.json b/package.json index 98e440c8d..ef0dd041b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "edge": "6.5.1", "edge-js": "8.8.1", "ffi": "2.0.0", - "gpii-universal": "0.3.0-dev.20180608T130946Z.7218a34", + "gpii-universal": "stegru/universal#GPII-1716", "@pokusew/pcsclite": "0.4.18", "ref": "1.3.4", "ref-struct": "1.1.0",