Added console command 'mousetrails' and 'deskbackground' to be able to get/set mouse accessibility and desktop background image path, on Windows.
Bryan Roe committed
Nov 1, 2022 at 20:01 UTC
2a6e08f663a0ae5036e1f7cebbec789a65aa9df3
2 files changed
+232
agents/meshcore.js
+38
@@ -3679,6 +3679,44 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
3679
response = "Available commands: \r\n" + fin + ".";
3680
break;
3681
}
3682
+ case 'mousetrails':
3683
+ try { require('win-deskutils'); } catch (ex) { response = 'Unknown command "mousetrails", type "help" for list of avaialble commands.'; break; }
3684
+ var id = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : null;
3685
+ switch (args['_'].length)
3686
+ {
3687
+ case 0:
3688
+ var trails = require('win-deskutils').mouse.getTrails(id);
3689
+ response = trails == 0 ? 'MouseTrails Disabled' : ('MouseTrails enabled (' + trails + ')');
3690
+ response += '\nTo change setting, specify a positive integer, where 0 is disable: mousetrails [n]';
3691
+ break;
3692
+ case 1:
3693
+ var trails = parseInt(args['_'][0]);
3694
+ require('win-deskutils').mouse.setTrails(trails, id);
3695
+ trails = require('win-deskutils').mouse.getTrails(id);
3696
+ response = trails == 0 ? 'MouseTrails Disabled' : ('MouseTrails enabled (' + trails + ')');
3697
+ break;
3698
+ default:
3699
+ response = 'Proper usage: mousetrails [n]';
3700
+ break;
3701
+ }
3702
+ break;
3703
+ case 'deskbackground':
3704
+ try { require('win-deskutils'); } catch (ex) { response = 'Unknown command "deskbackground", type "help" for list of avaialble commands.'; break; }
3705
+ var id = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : null;
3706
+ switch (args['_'].length)
3707
+ {
3708
+ case 0:
3709
+ response = 'Desktop Background: ' + require('win-deskutils').background.get(id);
3710
+ break;
3711
+ case 1:
3712
+ require('win-deskutils').background.set(args['_'][0], id);
3713
+ response = 'Desktop Background: ' + require('win-deskutils').background.get(id);
3714
+ break;
3715
+ default:
3716
+ response = 'Proper usage: deskbackground [path]';
3717
+ break;
3718
+ }
3719
+ break;
3720
case 'taskbar':
3721
try { require('win-utils'); } catch (ex) { response = 'Unknown command "taskbar", type "help" for list of avaialble commands.'; break; }
3722
switch (args['_'].length) {
agents/modules_meshcore/win-deskutils.js
new
+194
@@ -0,0 +1,194 @@
1
+/*
2
+Copyright 2022 Intel Corporation
3
+@author Bryan Roe
4
+
5
+Licensed under the Apache License, Version 2.0 (the "License");
6
+you may not use this file except in compliance with the License.
7
+You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+Unless required by applicable law or agreed to in writing, software
12
+distributed under the License is distributed on an "AS IS" BASIS,
13
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+See the License for the specific language governing permissions and
15
+limitations under the License.
16
+*/
17
+
18
+//
19
+// win-deskutils is a utility module that exposes various desktop related features for Windows
20
+// such as MouseTrails Accessability and Windows Desktop Background
21
+//
22
+
23
+//
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
26
+//
27
+
28
+var SPI_GETDESKWALLPAPER = 0x0073;
29
+var SPI_SETDESKWALLPAPER = 0x0014;
30
+var SPI_GETMOUSETRAILS = 0x005E;
31
+var SPI_SETMOUSETRAILS = 0x005D;
32
+
33
+var GM = require('_GenericMarshal');
34
+var user32 = GM.CreateNativeProxy('user32.dll');
35
+user32.CreateMethod('SystemParametersInfoA');
36
+
37
+//
38
+// This function is a helper method to dispatch method calls to different user sessions
39
+//
40
+function sessionDispatch(tsid, parent, method, args)
41
+{
42
+ //
43
+ // Check to see if the process owner of the current processor is root
44
+ //
45
+ var sid = undefined;
46
+ var stype = require('user-sessions').getProcessOwnerName(process.pid).tsid == 0 ? 1 : 0;
47
+ /*
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
+ ------------------------------------------------------------------------
64
+ */
65
+ console.log('stype: ' + stype);
66
+ if (stype == 1)
67
+ {
68
+ if (tsid == null && require('MeshAgent')._tsid != null)
69
+ {
70
+ stype = 5; // ILibProcessPipe_SpawnTypes_SPECIFIED_USER
71
+ sid = require('MeshAgent')._tsid; // If this is set, it was set via user selection UI
72
+ }
73
+ else
74
+ {
75
+ sid = tsid; // Set the SID to be whatever was passed in
76
+ }
77
+ }
78
+
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') } });
83
+
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; });
88
+ child.waitExit();
89
+ if (child.exitCode == 0)
90
+ {
91
+ return (child.stdout.str.trim()); // If the return code was 0, then relay the response from stdout
92
+ }
93
+ else
94
+ {
95
+ throw (child.stdout.str.trim()); // If the return code was nonzero, then the stdout response is the exception that should be bubbled
96
+ }
97
+}
98
+
99
+//
100
+// This function gets the path of the windows desktop background of the specified user desktop session
101
+//
102
+function background_get(tsid)
103
+{
104
+ if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
105
+ {
106
+ // Need to disatch to different session first
107
+ return (sessionDispatch(tsid, 'background', 'get', []));
108
+ }
109
+ var v = GM.CreateVariable(1024);
110
+ var ret = user32.SystemParametersInfoA(SPI_GETDESKWALLPAPER, v._size, v, 0);
111
+ if (ret.Val == 0)
112
+ {
113
+ throw ('Error occured trying to fetch wallpaper');
114
+ }
115
+ return (v.String);
116
+}
117
+
118
+//
119
+// This function sets the path for the windows desktop background of the specified user desktop session
120
+//
121
+function background_set(path, tsid)
122
+{
123
+ if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
124
+ {
125
+ // Need to disatch to different session first
126
+ return (sessionDispatch(tsid, 'background', 'set', [path]));
127
+ }
128
+ var nb = GM.CreateVariable(path);
129
+ var ret = user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, nb._size, nb, 0);
130
+ if (ret.Val == 0)
131
+ {
132
+ throw ('Error occured trying to set wallpaper');
133
+ }
134
+ return;
135
+}
136
+
137
+//
138
+// This is a helper function that is called by the child process from sessionDispatch()
139
+//
140
+function dispatch(parent, method, args)
141
+{
142
+ try
143
+ {
144
+ return (this[parent][method].apply(this, args));
145
+ }
146
+ catch (e)
147
+ {
148
+ console.log('ERROR: ' + e);
149
+ throw ('Error occured trying to dispatch: ' + method);
150
+ }
151
+}
152
+
153
+//
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
157
+//
158
+function mousetrails_set(value, tsid)
159
+{
160
+ if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
161
+ {
162
+ // Need to disatch to different session first
163
+ return (sessionDispatch(tsid, 'mouse', 'setTrails', [value]));
164
+ }
165
+ var ret = user32.SystemParametersInfoA(SPI_SETMOUSETRAILS, value, 0, 0);
166
+ if (ret.Val == 0)
167
+ {
168
+ throw ('Error occured trying to fetch wallpaper');
169
+ }
170
+}
171
+
172
+//
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
175
+//
176
+function mousetrails_get(tsid)
177
+{
178
+ if (tsid != null || tsid === null) // TSID is not undefined or is explicitly null
179
+ {
180
+ // Need to disatch to different session first
181
+ return (sessionDispatch(tsid, 'mouse', 'getTrails', []));
182
+ }
183
+ var v = GM.CreateVariable(4);
184
+ var ret = user32.SystemParametersInfoA(SPI_GETMOUSETRAILS, v._size, v, 0);
185
+ if (ret.Val == 0)
186
+ {
187
+ throw ('Error occured trying to fetch wallpaper');
188
+ }
189
+ return (v.toBuffer().readUInt32LE());
190
+}
191
+
192
+module.exports = { background: { get: background_get, set: background_set } };
193
+module.exports.mouse = { getTrails: mousetrails_get, setTrails: mousetrails_set };
194
+module.exports.dispatch = dispatch;
\ No newline at end of file