2Copyright 2022 Intel Corporation
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
19// win-deskutils is a utility module that exposes various desktop related features for Windows
20// such as MouseTrails Accessability and Windows Desktop Background
24// MSDN documention for the system call this module relies on can be found at:
25// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfoa
28var SPI_GETDESKWALLPAPER = 0x0073;
29var SPI_SETDESKWALLPAPER = 0x0014;
30var SPI_GETMOUSETRAILS = 0x005E;
31var SPI_SETMOUSETRAILS = 0x005D;
33var GM = require('_GenericMarshal');
34var user32 = GM.CreateNativeProxy('user32.dll');
35user32.CreateMethod('SystemParametersInfoA');
38// This function is a helper method to dispatch method calls to different user sessions
40function sessionDispatch(tsid, parent, method, args)
43 // Check to see if the process owner of the current processor is root
46 var stype = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : 0;
48 The following is the list of possible values for stype.
49 If the current process owner is root, we set the stype to user,
50 because we cannot set/get any properties from this user, we
51 must switch to a user session.. Default behavior for stype(1)
52 is that it will context switch to the logged in user. If
53 this is not intended, then an actual user TSID must be specified, using
54 ILibProcessPipe_SpawnTypes_SPECIFIED_USER and the actual TSID
55 ------------------------------------------------------------------------
56 ILibProcessPipe_SpawnTypes_DEFAULT = 0,
57 ILibProcessPipe_SpawnTypes_USER = 1,
58 ILibProcessPipe_SpawnTypes_WINLOGON = 2,
59 ILibProcessPipe_SpawnTypes_TERM = 3,
60 ILibProcessPipe_SpawnTypes_DETACHED = 4,
61 ILibProcessPipe_SpawnTypes_SPECIFIED_USER = 5,
62 ILibProcessPipe_SpawnTypes_POSIX_DETACHED = 0x8000
63 ------------------------------------------------------------------------
65 console.log('stype: ' + stype);
68 if (tsid == null && require('MeshAgent')._tsid != null)
70 stype = 5; // ILibProcessPipe_SpawnTypes_SPECIFIED_USER
71 sid = require('MeshAgent')._tsid; // If this is set, it was set via user selection UI
75 sid = tsid; // Set the SID to be whatever was passed in
79 // Spawn a child process in the appropriate user session, and relay the response back via stdout
80 var mod = Buffer.from(getJSModule('win-deskutils')).toString('base64');
81 var prog = "try { addModule('win-deskutils', process.env['win_deskutils']);} catch (x) { } var x;try{x=require('win-deskutils').dispatch('" + parent + "', '" + method + "', " + JSON.stringify(args) + ");console.log(x);}catch(z){console.log(z);process.exit(1);}process.exit(0);";
82 var child = require('child_process').execFile(process.execPath, [process.execPath.split('\\').pop(), '-b64exec', Buffer.from(prog).toString('base64')], { type: stype, uid: sid, env: { win_deskutils: getJSModule('win-deskutils') } });
84 child.stdout.str = '';
85 child.stdout.on('data', function (c) { this.str += c.toString(); });
86 child.stderr.on('data', function (c) { });
87 child.on('exit', function (c) { this.exitCode = c; });
89 if (child.exitCode == 0)
91 return (child.stdout.str.trim()); // If the return code was 0, then relay the response from stdout
95 throw (child.stdout.str.trim()); // If the return code was nonzero, then the stdout response is the exception that should be bubbled
100// This function gets the path of the windows desktop background of the specified user desktop session
102function background_get(tsid)
104 if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
106 // Need to disatch to different session first
107 return (sessionDispatch(tsid, 'background', 'get', []));
109 var v = GM.CreateVariable(1024);
110 var ret = user32.SystemParametersInfoA(SPI_GETDESKWALLPAPER, v._size, v, 0);
113 throw ('Error occured trying to fetch wallpaper');
119// This function sets the path for the windows desktop background of the specified user desktop session
121function background_set(path, tsid)
123 if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
125 // Need to disatch to different session first
126 return (sessionDispatch(tsid, 'background', 'set', [path]));
128 var nb = GM.CreateVariable(path);
129 var ret = user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, nb._size, nb, 0);
132 throw ('Error occured trying to set wallpaper');
138// This is a helper function that is called by the child process from sessionDispatch()
140function dispatch(parent, method, args)
144 return (this[parent][method].apply(this, args));
148 console.log('ERROR: ' + e);
149 throw ('Error occured trying to dispatch: ' + method);
154// This function sets the mousetrail accessibility feature, for the specified user desktop session.
155// Setting value 0 or one disables this feature
156// Otherwise, value is the number of cursors to render for this feature
158function mousetrails_set(value, tsid)
160 if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
162 // Need to disatch to different session first
163 return (sessionDispatch(tsid, 'mouse', 'setTrails', [value]));
165 var ret = user32.SystemParametersInfoA(SPI_SETMOUSETRAILS, value, 0, 0);
168 throw ('Error occured trying to fetch wallpaper');
173// This function returns the number of cursors the mousetrail accessibility feature will render
174// A value of 0 or 1 means the feature is disabled, otherwise it is the number of cursors that will be rendered
176function mousetrails_get(tsid)
178 if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
180 // Need to disatch to different session first
181 return (sessionDispatch(tsid, 'mouse', 'getTrails', []));
183 var v = GM.CreateVariable(4);
184 var ret = user32.SystemParametersInfoA(SPI_GETMOUSETRAILS, v._size, v, 0);
187 throw ('Error occured trying to fetch wallpaper');
189 return (v.toBuffer().readUInt32LE());
192module.exports = { background: { get: background_get, set: background_set } };
193module.exports.mouse = { getTrails: mousetrails_get, setTrails: mousetrails_set };
194module.exports.dispatch = dispatch;